POSTing data to a django admin form - python

I'm writing a Django app whose data will be coming from different sources, including Excel spreadsheets. I've written some code to do an initial import from those sheets, but I don't like the idea to re-import the whole data each time a row is added - and my client does not want to re-type the data himself.
A possible solution would be to add a form with a simple textarea where the user could copy-paste a whole line of the spreadsheet. Then a view could split the data, pre-process it and post it to the standard admin form for the corresponding object.
Ideally, it would behave like the user has really posted from this form: if the data validates, the object is created and if not, the (admin) form is re-displayed with the nice red error boxes.
So I thought I would just need something like
from django.shortcuts import redirect
[...]
return redirect(to, method=POST, *args)
but it doesn't seem to be available.
I also thought of passing the data as a big query string like http://.../admin/app/object/add/?ID=1234&name=toto&... but my model has many fields, with one-to-many and many-to-many inlines, possibly long textfields, etc. so this approach seems like more trouble than necessary.
Any idea how to obtain something like a POST redirect? or another approach to this problem?

If you're already writing code that is specific to your form, why not create the objects in that same function instead of trying to fake a POST request to the admin site?
To me, it sounds more difficult to use the default admin form than to use your existing pre-processing view to start creating or updating objects.
I'd just hook up your pre-processing view to your ModelAdmin definition via the get_urls method, set up a template that could be as simple as
<form action="." method="post">
<textarea name="data"></textarea>
<input type="submit" value="submit" />
</form>
and manually process the data in the input form request.POST.get('data', '').split(',') (or what have you) and start populating your models.
When done, send a message and redirect back to your app view or changelist view.
request.user.message_set.create(message="Finished populating X models")
return http.HttpResponseRedirect('../')

For this, you should step away from the built-in admin interface.
Create your own ModelForm http://docs.djangoproject.com/en/dev/topics/forms/modelforms/
Create your own view functions that does validation and POST.
This should probably be a 2-step transaction.
view_function_1
if method is GET, present the empty form.
if method is POST, they have pasted a value into the text box and filled in the "other" fields.
Parse the data in the text box.
For fields which are empty, fill in the missing values from the text box.
Put the form's data into the session.
Do a redirect to a URL that will move to view_function_2
view_function_2
If the method is GET, fetch the form data from the session, fill things in and
present the form with data.
If the method is POST, validate and save the results.
redirect to a page which will display the details to the user.

Related

Django: how to get HTML input field value to django view?

i want to get a value in an input to a django views, this is not a form as i am not trying to submit any form, i just need the value that is in the input field
this is the html template
<input readonly name="ref_code" type="text" value="{{ request.user.profile.recommended_by.profile.code }}">
this is my django views
code = str(request.GET.get('ref_code'))
print("This is the code:" + code)
It keep printing This is the code: None
NOTE: i have also tried using request.POST.get("ref_code") it did not still work
What might be the issue?
You definitely need something like a form.
So, let's walk you step by step on how your code works.
First, there is a view which prepares the data to be rendered with the template. This view responds to the first request from the user's browser and returns the rendered template as a static html page to the user.
Second, user's browser displays received html page to the user.
Third, user enters something into the input field.
At this stage the data user has entered is still on their side in their browser.
At this point you have two options:
Use a form to let user send the data to some view on the server which will then process the received data.
Use JavaScript to capture the entered data and send it to the server using an AJAX request.
I guess, you would like to use the second option in this case.
I'd recommend to read a guide on AJAX basics. The Ajax guide on MDN is a good place to start.

How to have single form on multiple pages

I am looking for ways to best handle a single form on multiple pages. Like how a newsletter signup might be on a home page, an about page, and several blog pages.
I've handled this exact scenario in these 2 ways.
Write an API (using DRF) that takes a POST request, and then point the normal HTML form at that API. This works, and is very flexible, but feels like overkill.
Pass the form object into the context of each view I want the form to be on, and then include that into the template with includes form_snippet with form=form
The first approach is more flexible with wagtail, wherein all that needs to happen on the admin side is an inclusion of the newsletter as a snippet, where the admin user is able to choose if they want the newsletter on the page or not.
While both approaches work just fine, neither of them "feels" right, as I would think there is a simple way to do this without creating a big API, or passing around the form object to every single view.
three years later on you probably found an answer.
For documentation purposes and Google searchers, Wagtail offers an explanation on how to make a multiple step form here:
https://docs.wagtail.org/en/v3.0.1/reference/contrib/forms/customisation.html#multi-step-form
I did this with a contact formular. I handled it with a new app for my contact formular.
In this contactApp is the templates/contactForm.html. To include this contactForm where I want I use {% include 'contact/contactForm.html' %} so it loads the contactForm.html from my app called contact.

How to work with JSON object after it has been passed from views.py in django?

Consider a django model which stores the name, phone number and address of people.
To allow users to edit its contents, I have created an edit form in html template using bootstrap modals. I want to provide an option to the user to 'leave the field blank to retain old information' (which is not the problem).
Along with this, I would also like to display the current information of each field as present in the database (as a placeholder value of the <input> tag).
In order to do that, I have created a 'context' dictionary in views.py which contains the data to be sent.
My question is, how do I send this dictionary from views.py to an html template without rendering any html page and how to parse this data on the template.
Note: I don't want to render any new page since I am using the bootstrap modal for the edit form.

Proper way to handle updating a view for Flask SPA using AJAX

This is a high level architectural question because I do not have web development experience, and I haven't found any succinct answers online.
Say I have a Flask app that starts off has a very simple html page with a few form fields. You key in some data into the form fields, submit, and the submission triggers an AJAX call onclick which then posts the results to your flask route.
When it comes time to display the data, you pull it out of the requests object which was posted to the relevant view, and then render a template passing through your formatted data.
My question is... if you want to continually make updates to the same page, how does that work? For example maybe after the first post hits your view you show a chart on the page with information passed to that view from the route. If you then decide to get a new graph for a different set of inputs to the form data, since you aren't hitting a new route do you just basically reload the page whenever the user keys in new data to the form fields and submits? How does this work if you want subsequent data to pop up after the chart? Do you just have multiple divs hidden/chilling in the background that unhide whenever certain events occur?
you usually use jquery to populate a div something like
<form id="my_form"> ... </form><button id="my_button">Clicky</button>
<div id="info_div"></div>
<script>
$("#my_button").click(function(){
var data = $("#my_form").serialize()
$("#info_div").load("/url/of/bit/to/load?"+data)
})</script>

Is there pyramid package for storing form related information serverside (avoid mirroring hidden fields)?

Background: I'm currently creating a project in pyramid. It uses beaker sessions and SQLAlchemy as DB-backend.
Some forms contain information in hidden fields, with the only purpose of supplying it to the view that processes the post, the user never sees them and doesn't need to. An example:
A DB-entity can be edited by the user. Since all data fields of the entity, including the name, can be edited, the ID of the entity is put in a hidden field, so the view can query the object and update it. This approach has some flaws:
The ID of my entities is no concern of my users. They should not even be aware of it.
Data being resubmitted by the client can be tinkered with. Someone might try to get access to other entities by forging a different id here.
In other scenarios there could be more mirrored data than just an id (maybe the return to url? Maybe much more somewhere). Using hidden fields for that would transmit the data to the client and back, needlessly (bandwidth) and makes it necessary to validate it.
Transmitting data over insecure channels (the client) without need is just wrong. The solution is not that complicated: store that information on the server (in session or DB), and make it accessible with a key (form-id?), similar to a session, with a session-id. Put that totally anonymous token into a hidden field. That will be the only hidden field needed in the form. Everything else would be stored on the server and be restored from the view responding to the post-request (well - I would still have my CSRF-token in there, because it's in all my post requests). This would also make it easy, to give forms a timeout, since you can make the form-id expire after some hours or so.
If I recall correctly, drupals does supply like this by default. I would not really expect pyramid itself to have support for this, but would imagine there must be a package doing this, using the pyramid supplied session object, still could not find any. I'm sure I could write something usable myself, but why do so if there might be something awesome out there already?
Anyone knows of such packages?
If I understand you, you want to update a model without using hidden fields on forms.
Here is how to do it
Using pyramid_simpleform and Urldispatch
#view_config(route_name="my_route",renderer="myrenderer.mako")
def update(request):
id = request.matchdict['id']
#assuming you have an SQLalchemy model called MyModel which you imported
#your model has a method that gets by id
toupdate = MyModel.get_by_id(id)
form = Form(request, schema=MyModelSchema,obj=toupdate)
if not toupdate:
#you can flash a message here and redirect wherever you want
return HTTPFound(location=request.route_url('home'))
if 'submit' in request.POST and form.validate():
form.bind(toupdate)
DBSession.add(toupdate)
DBSession.flush()
#redirect
return HTTPFound(location=request.route_url('home'))
return dict(form=FormRenderer(form))
At the view, just draw your form fields without any hidden field using the form object.
#configure your route as below
config.add_route('my_route','/myroute/{id}/edit')
UPDATE
to use webhelpers tool. Follow as bellow(Using Mako template)
<%
from webhelpers.html.tools import js_obfuscate
%>
js_obfuscate("<input type='hidden' name='check' value='valid' />")
to obfuscate the data in javascript tag

Categories