I'm currently learning django from the 'How to tango with django' site and i'm unable to understand the chapter dealing with forms.
Appreciate it if someone would help me out.
http://www.tangowithdjango.com/book17/chapters/forms.html
the first step is to create a forms page which maps to models.py. I seem to understand this part. I also understand that we create
a view to process the data acquired from these forms. I'm not able to understand the below code in the views page.
from rango.forms import CategoryForm
def add_category(request):
# A HTTP POST?
if request.method == 'POST':
form = CategoryForm(request.POST)
else:
# If the request was not a POST, display the form to enter details.
form = CategoryForm()
How do the urlmapper know that a request method is POST or GET before the user actually enters any data in the form?
On a similar note, when would a form have a get method?
form = CategoryForm(request.POST) - would someone explain this to me? CategoryForm looks to be a class which is already inheriting from another class
what does the request.POST argument convey ?
1) The urlmapper does by default not care about GET or POST request method. It will route any request to the given view-function.
Normally, your form html-code will look like this:
<form method="post" action="some_url">
...
</form>
So, when you submit the form, the data will be send to some_url with the specified method, in this case post.
You may want to read something about when to use GET or POST, normally forms are transferred using POST.
2) form = CategoryForm(request.POST) will bind the values provided in the request's POST-dictionary to the form. You may say, it prepopulates this. This way, further working with the form (like validating it by calling form.is_valid()) will be made possible.
Perhaps you should investigate further on Django forms and modelforms by reading some official documentation.
Why do you think the URL mapper knows if it's a post it a get? It doesn't, and it doesn't care.
The thing you are missing is that this view has two responsibilities: showing the initial form (on GET) and processing the submitted form (on POST).
Your second question shows an unfamiliarity with basic Python syntax. request.POST is the parameter to the initialisation of the form instance.
Related
I can't really seem to find the answer anywhere.
Basically, I have data in my view coming from an API that I want to pass into form fields. Is that possible?
I'm using Django-fobi, and I don't know how to do the following:
1) get a url for sharing the form without allowing a user to edit the form
2) include the form in another existing template
Any help is appreciated.
Only authors of the form are able to edit it.
Regarding embedding the form in another existing template, that part isn't difficult, read the docs. It's all about rendering the form. Otherwise integration with third party packages wouldn't be possible. See this.
I am developing a web-site using Django/Python. I am quite new to this technology and I want to do the web-site in a right way.
So here is my problem:
Imagine, that there is a Product entity and product view to display the Product info.
I use (product_view in my views.py ).
There is also Message entity and the Product might have multiple of them.
In Product view page ( I use "product_view" action in my views.py ) I also query for the messages and display them.
Now, there should be a form to submit a new message ( in product view page ).
Question #1: what action name should form have ( Django way, I do understand I might assign whatever action I want )?
Option #1: it might be the same action "product_view". In product_view logic I might check for the HTTP method ( get or post ) and handle form submit or just get request. But it feels a bit controversial for me to submit a message to the "product_view" action.
Option #2: create an action named "product_view_message_save". ( I don't want to create just "message_save", because there might be multiple ways to submit a message ). So I handle the logic there and then I make a redirect to product_view. Now the fun part is: if the form is invalid, I try to put this form to the session, make the redirect to the "product_view", get the form there and display an error near the message field. However, the form in Django is not serializable. I can find a workaround, but it just doesn't feel right again.
What would you say?
Any help/advice would be highly appreciated!
Best Regards,
Maksim
You could use either option.
Option #1: In the post method (if using Class-based-views, otherwise check for "post" as the request type), just instantiate the form with MessageForm(request.POST), and then check the form's is_valid() method. If the form is valid, save the Message object and redirect back to the same view using HttpResponseRedirect within the if form.is_valid(): code block.
If you're checking for the related Messages objects in your template, the newly created message should be there.
Option #2: Very similar to Option #1, except if the form is not valid, re-render the same template that is used for the product_view with the non-valid form instance included in the template context.
I've been developing a django project for 1 month. So I'm new at Django. My current problem with Django is; When I have multiple forms in one page and the page is submitted for a form, the other forms field values are lost. Because they are not posted.
I've found a solution for this problem;
When there is get method, I send the other forms value with the page url and I can handle them from the get request.
When there is post method, I keep the others form fields value in
hidden inputs in HTML side in the form which is posted. Hence I
can handle it from the post request.
Maybe I can keep them in session object. But it may not be good to keep them for whole time which the user logg in. But I dont know. I may have to use this method.
Is there another way which is more effective to keep all forms fields in Django?
Any Suggestion?
Thank!
You can make use of AJAX for a single form submission instead of whole page submit.
In a previous question, I was trying to figure out the right strategy for to passing data between forms in Pyramid. Based on the answer I received, I decided the approach of using a hidden form.
I started implementing this and think there must be a better way of passing along the data. Specifically, passing parameters through the url results in a tuple that is messy to parse.
I want it to be general enough to not to know what parameters the form has and also it needs to handle file fields as well.
How I'm currently attempting to pass the form data to the confirmation page:
#view_config(renderer="templates/derived/load/error.mak", route_name='process_model_route')
def process_model(self):
#processing logic and validaton, failiure in validation sends user to error.mak
return HTTPFound(route_url('confirm_model_route', self.request, fparams=self.request.POST))
Route: config.add_route('confirm_model_route', 'rnd2/model/confirm/*fparams')
#view_config(renderer="templates/derived/confirm/model.mak", route_name='confirm_model_route')
def confirm_model(self):
form_dict = self.request.matchdict['fparams']
#need to decode and pass to template
return dict({'load_route':load_route, 'form_dict':form_dict})
The confirm/model.mak template would contain the hidden form.
The idea with this method is:
Client visits page.
Server renders the form.
Client fills in form and POSTs to URL.
Server renders a new page that contains a hidden form with all of the data it just received in the POST.
Client POSTs to a URL, confirming the submission.
Server persists the data from the hidden form and redirects.
Now depending on usability, it's up to you to decide how many different URLs you actually want here and how many views in Pyramid. You have to think about what happens with invalid data?
Notice in the outline above, once the user POSTs the form to a URL, that URL must return the confirmation page containing a hidden form. If you try to redirect the user to a confirmation page instead, you must persist the data somehow, either in a session or through the hack you showed in your example (shoving all of the data into the GET). The second solution is very bad because it abuses the true purpose of GET in HTTP.
There is also the convention that every POST should result in a redirect to avoid a client submitting the form multiple times. With this in mind you might consider the simple solution of rejecting POSTs that do not have a "confirmed" flag and simply setting the "confirmed" flag in javascript after prompting the user. This allows you to keep your form handling logic simple.
If you don't want to rely on javascript and you don't want to persist the form data in a session, then you run into the issue of not redirecting after the first POST but other than that it should be simple from the outline above.