i am trying to set django test cookies on homepage but it is not getting set set.I have tried everything from changing middleware classes to sessionengines
my index function
def index(request):
request.session.set_test_cookie()
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = NameForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
return HttpResponseRedirect('/thanks/')
# if a GET (or any other method) we'll create a blank form
else:
form = NameForm()
return render(request, 'name.html', {'form': form})
here is my other function to test cookie
def register(request):
if request.session.test_cookie_worked():
print ">>>> TEST COOKIE WORKED!"
request.session.delete_test_cookie()
# Like before, get the request's context.
context = RequestContext(request)
# A boolean value for telling the template whether the registration was successful.
# Set to False initially. Code changes value to True when registration succeeds.
registered = False
# If it's a HTTP POST, we're interested in processing form data.
if request.method == 'POST':
# Attempt to grab information from the raw form information.
# Note that we make use of both UserForm and UserProfileForm.
user_form = UserForm(data=request.POST)
profile_form = UserProfileForm(data=request.POST)
# If the two forms are valid...
if user_form.is_valid() and profile_form.is_valid():
# Save the user's form data to the database.
user = user_form.save()
# Now we hash the password with the set_password method.
# Once hashed, we can update the user object.
user.set_password(user.password)
user.save()
# Now sort out the UserProfile instance.
# Since we need to set the user attribute ourselves, we set commit=False.
# This delays saving the model until we're ready to avoid integrity problems.
profile = profile_form.save(commit=False)
profile.user = user
# Did the user provide a profile picture?
# If so, we need to get it from the input form and put it in the UserProfile model.
# Now we save the UserProfile model instance.
profile.save()
# Update our variable to tell the template registration was successful.
registered = True
# Invalid form or forms - mistakes or something else?
# Print problems to the terminal.
# They'll also be shown to the user.
else:
print user_form.errors, profile_form.errors
# Not a HTTP POST, so we render our form using two ModelForm instances.
# These forms will be blank, ready for user input.
else:
user_form = UserForm()
profile_form = UserProfileForm()
# Render the template depending on the context.
return render_to_response(
'register.html',
{'user_form': user_form, 'profile_form': profile_form, 'registered': registered},
context)
you do not need to do all those middle ware changes to your settings file. I have just tried setting up a simple demonstration of your code and it works perfect.
First thing, try minimizing your code to only the cookie setting 'experiment'. You can try this demo here.
One one view maybe an index of a home view set the cookie.
On another view maybe an index view of another app test the cookie.
From the docs you can only test using another page request I quote
*test_cookie_worked()* "Returns either True or False, depending on whether the user’s
browser accepted the test cookie. Due to the way cookies work,
you’ll have to call set_test_cookie() on a previous,
separate page request. See Setting test cookies below for more information."
project/appxx/views ... request.session.set_test_cookie() #inside a view
project/appyy/views ... if request.session.test_cookie_worked():
request.session.delete_test_cookie()
return HttpResponse(">>>> TEST COOKIE WORKED!")
Then you can add on the logic later. I have used the HttResponse method instead of the print statment you used.
Related
I have a Django app with two views (actually more but I'm simplifying). The first view shows a page with details regarding an object and has a form which can be submitted. The second view is called buy the POST request on submitting the form and then redirects back to the first view:
views.py:
def main_view(request):
context = {}
# other view code here
context['form'] = Form()
return render(request, 'mypage.html', context)
def form_view(request):
form_data = Form(request.POST)
if form_data.is_valid():
# process form here
else:
# add an informative message
messages.add_message(request, messages.INFO, "Error message here")
return redirect('url_of_main_view')
The issue I have here is that I want to pass the form data back to the main view, both to prevent the need to fill in the whole form again, and to allow the validation errors to be displayed.
I would normally do this by simply processing the form within one single view, such as:
def view(request):
context = {}
# other view code here
context['form'] = Form()
if request.method == 'POST':
form_data = Form(request.POST)
if form_data.is_valid():
# process form data
else:
# handle messages
context['form'] = form_data
return render(request, 'mypage.html', context)
However, this (in my case at least) would result in a large view as I have a number of different forms that can be submitted from this page. I also like to redirect after a form post to avoid the data being re-submitted if the user refreshes the page.
My questions:
Is this (the first example) indeed a sensible way of structuring the code for handling forms? Is the second example a more sensible way of doing this, or is there a better idea? Perhaps I should perform form validation within the main view then call a separate method to process the form data?
If I were to use the first example, with a separate view to handle a form post, what is the best way to go about handling instances in which the form fails validation and should be passed back to the main view? Should I be using sessions for this, or is there a more efficient/cleaner way of doing this?
Thanks!
Alex
I have a very simple index page view, from which the user can fill in a login popup, which sends a post request to /login
def index(request):
"""Shows list of studyspaces, along with corresponding 'busyness' score"""
context = {'study_space_list': StudySpace.objects.order_by('-avg_rating')}
if request.user.is_authenticated():
context['user'] = request.user
else:
context['login_form'] = LoginForm()
context['user_form'] = UserForm()
context['student_form'] = StudentForm()
return render(request, 'spacefinder/index.html', context)
If the login is valid it simply redirects to the index page, this works fine.
The login view looks as follows:
def user_login(request):
form = LoginForm(request.POST)
if request.method == 'POST' and form.is_valid():
user = form.login(request)
if user:
login(request, user)
return redirect(reverse('spacefinder:index'))
# Load the context all over again
context = {
'study_space_list': StudySpace.objects.order_by('-avg_rating')
}
context['login_form'] = form
context['user_form'] = UserForm()
context['student_form'] = StudentForm()
return render(request, 'spacefinder/index.html', context)
However when the login is incorrect I want to be able to refresh the page and show the login form errors inside the index template (in the login popup)
I'm actually able to achieve this with the above code, but I'm unhappy with the solution for the following reasons:
I have to manually fetch the context all over again, e.g user/student forms and studyspaces, this goes against the DRY principle
When the page is refreshed the url is localhost:8000/spacefinder/login
Screenshot of behaviour here
I'm wondering if there's somehow a way to use redirect to reload the index page and somehow pass errors from my login_form, e.g. something like:
return redirect('spacefinder:index', {'login_form': form})
I've looked into using messages to pass form validation errors, but struggled to get this working since Validation Errors are thrown inside forms.py, and I'm unable to fetch the request instance from inside a ModalForm to properly create a message
You are doing it the wrong way around.
Consider these prerequisites:
entry point to your page is the index view
the index view must only be accessible by authenticated users
the login view allows both methods GET and POST and is accessible to anonymous users only
The reason to use Django is to make use of all the features that it offers, and that includes handling of the above (because that is what most pages need, not only you).
To set it up correctly you need to define your urls.py like this:
from django.contrib.auth.decorators import login_required
urlpatterns = [
....
url('^login/$', user_login, 'login'),
url('^/$', login_required(index), 'index'),
....
]
In your settings/base.py (or settings.py if you have no environment differentiation) tell Django how to redirect users:
LOGIN_URL = reverse_lazy('login')
LOGIN_REDIRECT_URL = reverse_lazy('index')
https://docs.djangoproject.com/en/1.9/ref/settings/#login-url
https://docs.djangoproject.com/en/1.9/ref/settings/#login-redirect-url
Simplify your index view:
def index(request):
"""Shows list of studyspaces, along with corresponding 'busyness' score"""
context = {'study_space_list': StudySpace.objects.order_by('-avg_rating')}
if request.user.is_authenticated():
context['user'] = request.user
else:
return HttpResponseForbidden() # prevented by Django, should never happen
return render(request, 'spacefinder/index.html', context)
Let the user_login view deliver the empty login form:
#require_http_methods(["GET", "POST"])
def user_login(request):
params = getattr(request, request.method)
form = LoginForm(params)
if request.method == 'POST' and form.is_valid():
user = form.login(request)
if user:
login(request, user)
return redirect(reverse('spacefinder:index'))
# Load the context for new form or form with errors
context = {
'study_space_list': StudySpace.objects.order_by('-avg_rating')
}
context['login_form'] = form
context['user_form'] = UserForm()
context['student_form'] = StudentForm()
return render(request, 'spacefinder/index.html', context)
You have not presented any code that handles the UserForm or the StudendForm. You would need to add that to the user_login view, as well - if this is something that all users should fill in every time they login. Otherwise use a different view.
It's worth looking at modules like allauth. They might spare you some work when it comes to allowing users to login with their e-mail addresses, ascertain that e-mail addresses are unique in the system etc.
I've read a lot topics about this problem but still can't fix problem.
I am going by Tango With Django tutorial (part 9) and get strange problem.
When I create user, I can't then get user object using authenticate method.
GitHub project: (link)
This is my register function from views:
def register(request):
# A boolean value for telling the template whether the registration was
# successful.
# Set to False initially. Code changes value to True when registration
# succeeds.
registered = False
# If it's a HTTP POST, we're interested in processing form data.
if request.method == 'POST':
# Attempt to grab information from the raw form information
# Note that we make use of both UserForm and UserProfileForm
user_form = UserForm(data=request.POST)
profile_form = UserProfileForm(data=request.POST)
# If the two forms are valid...
if user_form.is_valid() and profile_form.is_valid():
# Save the user's form data to the database.
user = user_form.save()
# Now we hash the password with the set_password method.
# Once hashed, we can update the user object
user.set_password(user.set_password)
user.save()
# Now sort out the UserProfile instance.
# Since we need to set the user attribute ourselves, we set
# commit=False
# This delays saving the model until we're ready to avoid
# integrity problems.
profile = profile_form.save(commit=False)
profile.user = user
# Did the user provide a profile picture?
# If so, we need to get it from the input form and put it in the
# UserProfile
if 'picture' in request.FILES:
profile.picture = request.FILES['picture']
# Now we save the UserProfile model instance
profile.save()
# Update our variable to tell the template registration was
# successful
registered = True
# Invalid form or forms - mistakes or something else?
# Print problems to the terminal.
# They'll also shown to the user
else:
print user_form.errors, profile_form.errors
# Not a HTTP POST, so we render out form using two ModelForm instances.
# These forms will be blank, ready for user input.
else:
user_form = UserForm()
profile_form = UserProfileForm()
context_dict = {
'user_form': user_form,
'profile_form': profile_form,
'registered': registered
}
# Render the template depending on the context.
return render(request, 'rango/register.html', context_dict)
user_login function from views:
def user_login(request):
# If the request is a HTTP POST, try to pull out the relevant information
if request.method == 'POST':
# Gather the username and password provided by the user.
# This information is obtained from the login form.
# We use request.POST.get('<variable>') as opposed to
# request.POST['variable'], because the
# request.POST.get('<variables>') return None, if the value does not
# exist, while the request.POST['<variable>'] will raise
# key error exception
username = request.POST.get('username')
password = request.POST.get('password')
# Use Django's machinery to attempt to see if the username/password
# combination is valid - a User object is returned if it is.
user = authenticate(username=username, password=password)
# user = User.objects.get(username='user1')
print user
# If we have a User object, the details are correct.
# If None (Python's way of representing the absence of a value), no
# user with matching credentials was found.
if user:
# Is the account active? It could have been disabled
if user.is_active:
# If the account is valid and active, we can log the user in.
# We'll send the user back to the homepage
login(request, user)
return redirect('rango:index')
else:
# An inactive account was user - no logging in
return HttpResponse("Your Rango account is disabled.")
else:
# Bad login details were provided. So we can't log the user in.
print "Invalid login details: {0}, {1}".format(username, password)
return HttpResponse("Invalid login details supplied")
# The request is not a HTTP POST, so display the login form.
# This scenario would most likely be a HTTP GET.
else:
# No context variables to pass to the template system, hence
# the blank dictionary object..
return render(request, 'rango/login.html')
This is the code in Tango with django
user.set_password(user.password)
user.save()
And your's is
user.set_password(user.set_password)
user.save()
Try to replace set_password with password.
Hello I am working on a simple form. The form submits fine but if I refresh the page it resubmits the data. Seems the form is holding the data after submit and I assume since after the submit the request method is post. Question is what is the best way after the submit to clear the form in Django. After the submit the form variables should not be holding the values anymore. Thanks
def testimonials(request, template_name="testimonials.html"):
reviews = Reviews.objects.all()
if request.method == 'POST':
form = forms.ReviewsForm(data = request.POST)
# create a new item
if form.is_valid(): # All validation rules pass
# Process the data in form.cleaned_data
# ...
if form.is_valid():
nameIn = form.cleaned_data['name']
reviewIn = form.cleaned_data['review']
newReview = Reviews(name = nameIn, review = reviewIn)
newReview.save()
return render_to_response(template_name, locals(), context_instance=RequestContext(request))
else:
# This the the first page load, display a blank form
form = forms.ReviewsForm()
return render_to_response(template_name, locals(), context_instance=RequestContext(request))
Typically, you would issue a redirect after processing a form/POST request (this is common web development practice to avoid the resubmission issue you mentioned). So instead of a render_to_response, you might issue a HttpResponseRedirect like so:
if form.is_valid():
# Process form as desired here
# Simple example; use reverse() to avoid hard-coding URLs
return HttpResponseRedirect('/success/')
Check out the using a form in view for a skeleton of how forms are typically processed.
use reverse instead of render to response
if form.is_valid():
nameIn = form.cleaned_data['name']
reviewIn = form.cleaned_data['review']
newReview = Reviews(name = nameIn, review = reviewIn)
newReview.save()
return HttpResponseRedirect(reverse('app_name:url'))
You could also use the 'redirect' shortcut:
from django.shortcuts import redirect
...
return redirect(newReview)
This is assuming you have get_absolute_url defined in your Review Model.
See the docs for more info.
I have a form MyForm which I update using ajax as the user fills it out. I have a view method which updates the form by constructing a MyForm from request.POST and feeding it back.
def update_form(request):
if request.method == 'POST':
dict = {}
dict['form'] = MyForm(request.POST).as_p()
return HttpResponse(json.dumps(dict), mimetype='application/javascript')
return HttpResponseBadRequest()
However, this invokes the cleaning/validation routines, and I don't want to show error messages to the user until they've actually actively clicked "submit".
So the question is: how can I construct a django.forms.Form from existing data without invoking validation?
Validation never invokes until you call form.is_valid().
But as i am guessing, you want your form filled with data user types in, until user clicks submit.
def update_form(request):
if request.method == 'POST':
if not request.POST.get('submit'):
dict = {}
dict['form'] = MyForm(initial = dict(request.POST.items())).as_p()
return HttpResponse(json.dumps(dict), mimetype='application/javascript')
else:
form = MyForm(request.POST)
if form.is_valid():
# Your Final Stuff
pass
return HttpResponseBadRequest()
Happy Coding.