I have a base.html which most of my pages inherit. Inside it defines a header which contains a search box. The code for the search box is some thing along the lines of....
if request.method == 'POST':
if 'search_button' in request.POST:
location = request.POST['location']
# Do something with location here and redirect to another page...
return HttpResponseRedirect('/lostandfound')
I have a couple of questions. First of all, how do I ensure that this code is sat in all my other views without rewriting it every time, this wouldn't be very DRY!!
Also how do I redirect to another page and pass the variable 'location' along with it? HttpResponseRedirect isn't the right way to do it i'm sure!
You should POST your search form to it's own search view, and display the results on that page.
Related
In my base template I want to have a search text box with a submit button on the top of every template. My button name is 'searchbutton'
I put it in a form with get method
I want to use this for all views in my application
I have a view with 2 more forms , one of theese has pagination with page buttons
I tried:
if ('searchbutton') in request.GET:
but this is true even user change pages on pagination.
How can I know when user clicked the search button to filter rows as I want?
Thanks in advance
Kostas
If you are defining all your forms as django.forms.Form and not just as pure HTML, you should be able to handle it in your view.
E.g.
class FooView(generic.FormView):
def post(self, request):
search_form = SearchForm(request.POST)
other_form = OtherForm(request.POST)
if search_form.is_valid() and search_form.has_changed():
# Handle Search Form here.
elif other_form.is_valid() and other_form.has_changed():
# Handle Other Form here.
HOWEVER! If this is a Search Function I suggest that instead of handling the logic on every view, you instead make the form submit to a specific view/url each time.
E.g. you create a form that submit to /search?q= where q is your query. And then you only create a single SearchView that handles this logic.
I've built a nested drop down menus on my HTML and based on what user clicks inside nested dropdown, I want it to change the default value inside WTF form and post it to database.
So I have multiple different views pointing to one 'post' view. These multiple different views are different menus in my nested dropdown menus.
views
#app.route('/first_drop_down')
def first_drop_down():
return redirect('http://127.0.0.1:5000/post_something/first/')
#app.route('/second_drop_down')
def second_drop_down():
return redirect('http://127.0.0.1:5000/post_something/second/')
#app.route('/post_something/<some_parameter>', methods=['GET','POST'])
def post_something(some_parameter)
some_form = SomeForm()
if some_parameter == 'first':
some_form = SomeForm(field_a = some_parameter)
elif some_parameter == 'second':
some_form = SomeForm(field_a = some_parameter )
if some_form.validate_on_submit():
.
.
.
.
insert to db
return redirect(url_for('index'))
return render_template('user_input.html', some_paramter = some_paramter)
So the problem that I'm having is that I keep getting 404 right after I press submit on my form. And when doing get request on post_something view, the url is /post_something/first/ but after pressing the submit button the url changes to /post_something// , so the url is empty for post and I'm guessing thats why it is throwing 404.
Even though I kind of assume why this is happening, I am kind of stuck of what to do to maintain that url when posting. Any help will be appreciated.
from the flask api documentation, you will notice
1. If a rule ends with a slash and is requested without a slash by the user, the user is automatically redirected to the same page with a trailing slash attached.
2. If a rule does not end with a trailing slash and the user requests the page with a trailing slash, a 404 not found is raised.
Now that you have defined:
#app.route('/post_something/<some_parameter>', methods=['GET','POST'])
you should use /post_something/first in your form; Or use url_for('post_something') instead.
How can I avoid duplicating the logic code from the GET block in the view below?
The logic is view-specific enough that I don't feel it makes sense to put a helper function in a separate utils.py.
'''
show_stuff view shows different stuff depending on how many other
POST requests have been submitted to view and saved to the DB.
All the users access the same URL randomly, so I don't believe it's possible to
split things up like "view_for_template1", "view_for_template2" in urls.py
'''
def show_stuff(request, url_dispatch_var1, url_dispatch_var2=None):
if request.method == "GET":
#30 lines of logic determining which Template and Context to return
if request.method =="POST":
#10 lines of logic determining which Form type to save
#then, the same 30 lines of logic as the GET block to determine
#which Template and Context to return
You can usually do something like the following:
def show_stuff(request, url_dispatch_var1, url_dispatch_var2=None):
if request.method =="POST":
#10 lines of logic determining which Form type to save
# redirect if form is valid
else:
# this is a GET request
form = MyForm() # unbound form for get request
# 30 lines of logic to determine which Template and Context to return
return render(request, template, context)
Note that after a successful post request, the usual approach is to redirect to prevent duplicate submissions.
This might be a case where class based views are useful. You could subclass FormView, then override get_context_data, get_template_names and so on.
Maybe instead of returning body for POST request you could redirect user to your GET view ?
I'm new to both web development and django so maybe that's a noob question.
I want to do the following:
Ask user to fill some form and submit it.
Then, parse and format the content and display it back to the user to let him verify it.
User can accept the result or go back to the previous view, update data and resend.
This is as far as I can think:
views.py
def add_content(request):
if request.method == 'POST':
form = AddContentForm(request.POST)
if form.is_valid():
content = form.save(commit=False)
return verify_content(request, content)
else:
form = AddContentForm()
return render(request, 'myapp/add_content.html', {'form' : form})
def verify_content(request, content):
return render(request, 'myapp/verify_content.html', {'content' : content})
The verify_content template will obviously contain two buttons ('back', 'ok'), but I don't know how to pass the content object to a view for saving it in the db, or send it back to the previous view from there. Should I use js? Can i do it with just server side code?
Maybe my whole logic is wrong. Should I save the object in the db before verification and then delete it if needed (sounds ugly)? What is a good way to implement this?
Thanks in advance for your time.
You could use the users session for this:
request.session['content'] = content
and in the view where the user should verify his input do:
content = request.session['content']
and voilá you got the content between 2 views.
Django also secures that users can't tinker with its data by either saving it server side, or in a signed cookie.
I would save the form with commit=True in the add_content view, and would add a verified field or something to the model. Then you can append the pk as GET parameter to the link which will get you back to add_content view from verify. You can extract the parameter from request.GET dict.
I have two form pages:
Start Form - where you input the basic information
Add product form - uses data from start form to populate some fields. And there you can also give more information in the form.
In the urls.py I have this:
urlpatterns = patterns('',
url(r'^$',add_product_start),
url(r'^add_product/$', add_product),
)
This is my add_product_start form view:
def add_product_start(request):
form = add_product_start_form()
if request.method == "POST":
form = add_product_start_form(request.POST)
if form.is_valid:
#return respose to the add_product url with request data
return render(request,'index.html',{'form':form})
And this is my add_product view:
def add_product(request):
images = []
if request.method == "POST":
initial = {field:value for (field,value) in request._post.iteritems() if value}
#a bunch of other code
#point is I want to receive post data from add_product_start view and at the same time redirect to a different url, because I don't want to have the same url of two different forms.
return render(request,'add_product.html' ,{'form':form,'images':images})
I know there is something like HttpResponseRedirect but they just redirect me to the page without any type of data.I want to get the data from the start form, validate it, and if valid pass it to the second view with a different page.
Can someone please help me. Thank you very much!
The best way is using the form wizard https://docs.djangoproject.com/en/1.7/ref/contrib/formtools/form-wizard/
I solved similar issue using redirect(obj).
This video may help
https://www.youtube.com/watch?v=YsHd-l7QdI8