I am currently building an ecommerce style app. I have a view new_order that processes the POST data (order info). After that, it renders an HttpResponseRedirect to order_complete which just renders order_complete.html template.
What is the best way to pass the order number to the template. Here's what I did:
messages.success(request, 'Your order number is %s ' % order.order_id)
return HttpResponseRedirect(reverse('orders:order_complete_url'))
That works nicely, however, due to the nature of messages, it disappears on page refresh. Is this an ideal behavior or there is a better way to accomplish it? Also, how would i go about passing for instance order detail, total etc, to the template?
Django's messages framework allow us to display a one-time notification message to the user after processing a form or some other types of user input. It temporarily stores messages in one request and retrieves them for display in a subsequent request (usually the next one).
So, when you refresh the page, that message will disappear and will not be displayed again.
You can use session to store variables which you want to use in your subsequent requests also.
For example:
request.session['order_number'] = order.order_id # set in session
return HttpResponseRedirect(reverse('orders:order_complete_url'))
This will set order_number in the session. Here, you can also set other variables which you need in order_complete_url view.
Then in your order_complete_url view, you can access order_number by:
order_number = request.session['order_number'] # retrieve order number from session
You can pass this order_number to context then for displaying in the template. Now, when you refresh the page, order_number will be displayed in the template.
Related
My Django application allows a user to navigate to an Update Form (UpdateView) from multiple locations in the application. Currently, if the form is saved successfully I can redirect without a problem to the referring page by saving request.META.HTTP_REFERER in a hidden field in the template and retrieving it in form_valid. I can leverage the HTTP_REFERER data in MOST, but not ALL cases. One of those is the following scenario:
My user navigates to the FORM A from Page X (HTTP_REFERER is set to Page X)
FORM A is submitted and does not pass validation (HTTP_REFERER is now set to FORM A instead of Page X because indeed it has self-refered.)
My user clicks Cancel (they are redirected back to FORM A instead of Page X)
Is there a way to capture the Cancel event before it is processed and perform some logic so my user gets referred back to Page X instead of being stuck in the form?
In general how do we know if user is visiting the page for the first time? Technically, do we store the number of visits to each page in the Model(I am using django) or is there some other pattern that I could follow to ease up the operation.
I m just looking for a design for implementing this.
I think you will have to create your own mechanism for this.
I would make a model storing first visits for every url and user called e.g FirstVisit. Then if a user requests a page in a view you can search if there is an entry in FirstVisit for current user and url and find out if it's his first time or not. After that, if he hasn't visited yet, you store the entry to the FirstVisit model, because he is just going to get the content of the page.
I will try and write the code:
#models.py
class FirstVisit(models.Model):
url = models.URLField()
user = models.ForeignKey('auth.User')
#views.py
def my_view(request):
if not FisrtVisit.objects.filter(user=request.user.id, url=request.path).exists():
#he visits for the first time
#your code...
FisrtVisit(user=request.user, url=request.path).save()
You can create a decorator and put in there this functionality. Then add the decorator to any view you want to store this information and from the decorator pass a flag argument to the view determining if user is there for the first time.
Following #davekr suggestion, I would create a model like FirstVisit with some attributes like ip-address, time registered and instante it on the get method (that is tied to the root url) with some validation if the user is valid or authenticated.
PS: Check this (https://docs.djangoproject.com/en/2.0/ref/request-response/) django docs to indentify the request attributes that could be of your interest to construct the FirstVisit.
Is here any way to store formset to a session ?
My Scenario is like this . I have a form to fill user data and upload user certificates, and in the next page(form by clicking next) there is a form to enter Professional details .
Is it possible to limit Maximum number of forms generated using a formset?
If I understand your question correctly - how to save a state of the from in a session, then starting with Django 1.4, it actually comes with a way on how to do that out of the box.
https://docs.djangoproject.com/en/dev/ref/contrib/formtools/form-wizard/
It allows you to split a form into multiple section, which then user can fill separately. Once user fills any one section, he/she go to the next page, at which point the state of the form will be saved in a session. Once all the pages are filled, then everything can be saved to a database.
In addition, while going from one page to the other, you add logic of what should be on the next page.
Image that you have a wizard where on the first page it asks what type of content user wants to upload. Then upon going to the second page, then depending on the answer from the first page, appropriate upload fields can be present - field for video, music, or graphics.
I would have answered FormWizard but if you don't want to use it, you can simply create two forms. when the user submit the first one, you pickle it into a session and then you generate the second form. When he clicks on back link, you unPickle saved data and you prefill the form.
def submitFirstForm(request):
data = request.POST['data']
import cPickle
request.session['data'] = cPickle.dumps(data)
...
def backBtn(request):
import cPickle
data = cPickle.loads(request.session['page'])
form = DataForm(data)
...
I want to have a page counter that displays the number of visitors who have viewed a particular page on my site. Is it possible to do this using Django?
There's a Django app for that problem called django-hitcount. It's easy to use, and reusable in any of your projects.
A "page counter" is what? A persistent piece of data which gets updated by view functions and displayed by a template.
As you are no doubt already aware, all Django things have the following parts.
Model
View Function
Template
Model
If you want to keep the page counter in the database, you need a Django model.
class PageCounter( Model ):
You need to put a row into this model. Usually a "fixture" will help do this, since it's one row and you only put it in once when doing a syncdb.
View Function
Then you need to fetch and update the page counter in your view function.
pageCounter= PageCounter.objects.all()[0]
pageCounter.count += 1
pageCounter.save()
Template
Now you need to provide the value to your templates so it can be displayed.
I know this is an old post but occasionally people might have the same question.
If you want to avoid a third party library and prevent the counter being updated at every page refresh you could do the following Mixin (building on S.Lott's answer)
class BlogPostCounterMixin(object):
def get_context_data(self, **kwargs):
context = super(BlogPostCounterMixin, self).get_context_data(**kwargs)
blog_post_slug = self.kwargs['slug']
if not blog_post_slug in self.request.session:
bp = BlogPost.objects.filter(slug=blog_post_slug).update(counter=+1)
# Insert the slug into the session as the user has seen it
self.request.session[blog_post_slug] = blog_post_slug
return context
It checks if the accessed model has been stored in the session. If it has been stored in the session, it skips incrementing, else it increments the counter and adds the slug of the model to the session preventing increments for page refreshes.
Note: This is a Mixin which you require to add into your view.
I have a form in which the user selects a few items to display on "the following page". This selection is always unique, and we will store each set of selections made using a model, indexed by the id as is par with Django models. When the user selects her choices and POSTs using the submit button, I would like for our application to store her selections in the model, and then render a page with the id of the model so that the user can get back to the page she created at any point with a simple GET request.
For example, the user goes to /coolapp/selectprefs/, makes a few selections, and clicks submit. The user should then be taken to /coolapp/selections/42 given that when the user submitted and created the record, the record was given an id of 42.
What I don't understand is how to send the user to "the following page" as a response (e.g., /coolapp/selections/42 in the above example) after she clicks the submit button. Taking a user to a page of a unique ID based on what she entered seems like a common task (e.g., it will happen when I click the button to submit this question on SO), but I'm not sure how to go about doing it, and would appreciate your advice.
Return a HttpResponseRedirect from your view that handles the POST.