def demo(request):
if data:
request.session['success'] = "Success'
else:
request.session['failed'] = "Failed'
Here I've defined one method and in that if I got data then success session is stored or else failed one.
After that I'm redirecting user to the another page and there I'm displaying this session variable in template.
But after the display of this session status I want to delete that session variable. Because I want to display this message only onetime to user. If user refreshes the page then this variable should be deleted.
I tried to find online but didn't get any help. So please help me with this.
Thank you
P.S: I'm redirecting user to another page using return redirect('page'). Rendering another template using return render(request, "my_tmp.html") doesn't work because that will only load template in current url (URL will not change, only content will). So I don't want that. I know I can use this way by passing session variable in context but that's not I want.
I'm using Django 2
Please do not use session variables for that. Session variables should be used, like the name suggests, for variables that typically have a livespan that is the same as the session. Doing this yourself will also result in a lot of coding, special edge-cases, and likely it will be error-prone.
Django has tooling to show messages to the user: the messages framework [Django-doc]. The documentation specifies how you can set up this framework, although by default it is already installed (so if you did not remove it, there is not much that you need to do).
In your view, you can then add messages, like:
from django.contrib import messages
def demo(request):
if data:
messages.success(request, 'Operation successful')
else:
messages.error(request, 'Operation failed!')
return render(request, 'some_template.html', {})
In your template you can then render the messages like specified in the documentation [Django-doc]:
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
You can for example include that in your base.html (and thus extend all other pages from that super template) such that you render the messages on all pages.
Django will automatically clear the messages once these are rendered. So there is no need to do the bookkeeping yourself.
Related
I have a page in my Django app that needs to do one of the following depending on the status of the logged in user in relation to a group (not a Django user group; something custom to my app) represented on the page:
If the user can join the group, display a link to join the group.
If the user is in the group, display a link to leave the group.
If the user can't join the group, don't display either link.
One way of doing this would be to create three templates (one with the join link, one with the leave link, and one with no link) and choose the appropriate one in the view. I feel like it may be overkill to have three different templates that will only differ in one line of code, so I have not gone that route as of yet.
Displaying the correct content for conditions 1 and 2 exclusively using a template is not possible, and if it were I do not think it would be advisable. Users to groups is a many-to-many relationship, and determining group membership requires passing a user to the group or passing a group to the user.
Since Django templates don't allow passing function arguments, I am trying to solve this by passing a context variable to the template using get_context_data.
def get_context_data(self, **kwargs):
context = super(NetworkDetails, self).get_context_data(**kwargs)
user = ???
context['in_group'] = user.in_group(context['group_detail'])
return context
If I do that, how can I get the currently logged in user within that method? If that isn't possible, where else can I get that information outside of the template? Is there an accepted method of doing something like this?
Thanks!
One way of doing this would be to create three templates (one with the
join link, one with the leave link, and one with no link) and choose
the appropriate one in the view
That's funny because if you can choose what template to include, you can just choose what html to display. Instead of:
{% if join_link %}
{% include 'join_link.html' %}
{% endif %}
{% if leave_link %}
{% include 'leave_link.html' %}
{% endif %}
{% if not join_link and not leave_link %}
you can't join
{% endif %}
You could just have:
{% if join_link %}
join
{% endif %}
{% if leave_link %}
leave
{% endif %}
{% if not join_link and not leave_link %}
you can't join
{% endif %}
So, I don't understand why you want to use template inclusion.
If I do that, how can I get the currently logged in user within that method?
self.request.user
self.request.user.is_authenticated() # return True if the user is logged in
You can determine the condition in your view and pass appropriate flag(s) to the template using context.
If there are multiple views/templates that need this info, you could implement custom context processor which can add this info in context and its available in each template.
Or If you have any OneToOne or any such relationship with User in your app, you can implement method in that model.
You can check if a user is logged in by checking permissions
https://docs.djangoproject.com/en/dev/topics/auth/ also you can do the similar for your other needs.
I have the following code in my template:
{% for req in user.requests_made_set.all %}
{% if not req.is_published %}
{{ req }}
{% endif %}
{% empty %}
No requests
{% endfor %}
If there are some requests but none has the is_published = True then how could I output a message (like "No requests") ?? I'd only like to use Django templates and not do it in my view!
Thanks
Even if this might be possible to achieve in the template, I (and probably many other people) would advise against it. To achieve this, you basically need to find out whether there are any objects in the database matching some criteria. That is certainly not something that belongs into a template.
Templates are intended to be used to define how stuff is displayed. The task you're solving is determining what stuff to display. This definitely belongs in a view and not a template.
If you want to avoid placing it in a view just because you want the information to appear on each page, regardless of the view, consider using a context processor which would add the required information to your template context automatically, or writing a template tag that would solve this for you.
I used django-registration app. Everything goes fine. User gets registered with email verification but when user logs in and is redirected to mainpage the auth template tags such as {% if user.is_authenticated %} returns false.
I am having this in my login.html
<input type="hidden" name="next" value="/" />
After login I want to redirect the user to main page and in mainpage.html
{% if user.is_authenticated %}
<p>Welcome, {{ user.username }}. Thanks for logging in.</p>
{% else %}
<p>Welcome, new user. Please log in.</p>
{% endif %}
but user.is_authenticated returns false here. What might be the problem here? Thanks
Try using {% if request.user.is_authenticated %} instead. It's entirely possible that user isn't being passed into the context dictionary within the view. If the object is not found within the template, it will just skip to the else portion of the block. Rendering templates are strange in django, as what would normally be an exception, is swallowed.
Can you show us the code for the view which handles the URL '/'? I think this is where your problem lies, rather than in your use of django-registration.
Does this view put user in the context? If you want to use it in the template, you're going to have to put it in. If you want to use request in the context, then you need to make sure that you pass an instance of RequestContext as the context rather than just a standard context object.
Here's what worked for me.
Suppose your main page gets processed by a view in views.py
from django.shortcuts import render_to_response
def mainpage(request):
return render_to_response('mainpage.html')
You need to add RequestContext to include to user object. Change your view to
from django.shortcuts import render_to_response
from django.template import RequestContext
def mainpage(request):
return render_to_response('mainpage.html', context_instance=RequestContext(request))
I have a view that validates and saves a form. After the form is saved, I'd like redirect back to a list_object view with a success message "form for customer xyz was successfully updated..."
HttpResponseRedirect doesn't seem like it would work, because it only has an argument for the url, no way to pass dictionary with it.
I've tried modifying my wrapper for object_list to take a dict as a parameter that has the necessary context. I the return a call to this wrapper from inside the view that saves the form. However, when the page is rendered, the url is '/customer_form/' rather than '/list_customers/'. I tried modifying the request object, before passing it to the object_list wrapper, but that did not work.
Thanks.
request.user.message_set was deprecated in Django 1.2 and has been removed since Django 1.4, the message framework should be used instead.
from django.contrib import messages
# messages.add_message(request, level, message, extra_tags='', fail_silently=False)
messages.add_message(request, messages.INFO, "Your Message")
Alternatively, you can use one of the shortcut functions:
from django.contrib import messages
messages.debug(request, "Your Message")
messages.info(request, "Your Message")
messages.success(request, "Your Message")
messages.warning(request, "Your Message")
messages.error(request, "Your Message")
Messages can then be rendered on the template with:
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
Please note the answer suggested here is only applicable to Django < 1.2:
Do you have control over the view that you are redirecting to? In that case you can save the context in the session before redirecting. The target view can pick up the context (and delete it) from the session and use it to render the template.
If your only requirement is to display a message then there is a better way to do this. Your first view can create a message for the current using auth and have the second view read and delete it. Something like this:
def save_form(request, *args, **kwargs):
# all goes well
message = _("form for customer xyz was successfully updated...")
request.user.message_set.create(message = message)
return redirect('list_view')
def list_view(request, *args, **kwargs):
# Render page
# Template for list_view:
{% for message in messages %}
...
{% endfor %}
Messages are saved to the database. This means that you can access them even after a redirect. They are automatically read and deleted on rendering the template. You will have to use RequestContext for this to work.
For Django => 1.2 read the answer involving messages
To expand on Antoine's helpful answer: if you want to process the messages in your views module, rather than the template:
from django.contrib.messages import get_messages
def my_view(request):
# Process your form data from the POST, or whatever you need to do
# Add the messages, as mentioned above
messages.add_message(request, messages.INFO, form.cleaned_data['name'])
return HttpResponseRedirect('/other_view_url/')
def other_view(request):
storage = get_messages(request)
name = None
for message in storage:
name = message
break
return render(request, 'general/other_view.html', {'name': name})
I found the following to work if more than just a message needs to be added to the redirect:
from django.shortcuts import redirect
import urllib
def my_view(request):
...
context = {'foo1': bar1, 'foo2': bar2, 'foo3': bar3}
return redirect('/redirect_link/?' + urllib.parse.urlencode(context))
See also
how to pass context data with django redirect function?
In Django 2.x + you can simply use messages framework that comes with Django
views.py
from django.contrib import messages
def register(request):
....
messages.success(request,"You have registered successfully, now login!")
return redirect('login-page')
And in you, login.html template do add this code
{% if messages %}
{% for message in messages %}
<div class="alert alert-success alert-dismissible fade show">
<strong>Success!</strong> {{message}}
<button type="button" class="close" data-dismiss="alert">×</button>
</div>
{% endfor %}
{% endif %}
Note this example can be applied to anywhere you want to display a message for success
If you want to pass an error message simply use messages.error(request, "Error message")
To Django Admin, I could redirect with the several types of messages as shown below:
# "views.py"
from django.contrib import messages # Here
from django.shortcuts import redirect
def my_view(request):
messages.debug(request, 'This is debug')
messages.info(request, 'This is info')
messages.success(request, 'This is success')
messages.warning(request, 'This is warning')
messages.error(request, 'This is error')
return redirect("http://localhost:8000/admin/store/order/")
But, I don't know why only "debug" message is not displayed even though "DEBUG = True" in "settings.py":
I have a form that redirects to the same page after a user enters information (so that they can continue entering information). If the form submission is successful, I'm returning
HttpResponseRedirect(request.path)
which works fine. However, I'd also like to display some messages to the user in this case (e.g., "Your data has been saved" at the top of the screen). If I weren't redirecting, I'd just return these messages in the context dictionary. With the redirect, however, I can't do this.
So how can I pass template context information when using HttpResponseRedirect?
What I'm trying to do seems like it would be incredibly common, so please excuse me if I'm missing something obvious.
For the sake of completion and future reference, you can now use the messages framework. After you install it:
views.py
from django.contrib import messages
def view(request):
# your code
messages.success(request, "Your data has been saved!")
HttpResponseRedirect(request.path)
template.html
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
if you are using auth and have a logged in user you could:
http://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.models.User.message_set.create
GET params are also hackable. The querystring, as mentioned in other answers, could be used.
I think the most preferred way would be to use the sessions framework. That way you can load up whatever you want in the context and get
{{ request.session.foo }}
foo could be the message or you could do:
{% ifequal request.session.foo 1 %} Nice work! {% else %} Almost! {% endifequal %}
and other fun stuff.
http://docs.djangoproject.com/en/dev/topics/http/sessions/#using-sessions-in-views
You can't. HttpResponseRedirect sends a client-side redirect (HTTP status code 302) to the browser, and then the browser re-requests another page.
You can set a URL query string on the redirect, though that will be visible to the user and anyone intercepting HTTP requests (i.e. proxies), and is therefore not suitable for sensitive information.
The best way would probably be to use a coded querystring on the redirect URL... its an old school approach.
You could do something like
/page/?m=1, /page/?m=2, etc
You would then parse that variable with request.GET in the view code and show the appropriate message.
From your views.py you hast have to put a key/value-pair into the session and then read it from the HTML template.
For example:
views.py
# your code here
request.session['vote'] = 1
return HttpResponseRedirect(request.path)
your_template.html
{% ifequal request.session.vote 1 %}
<!-- Your action here -->
{% endifequal %}
The only way I know of to pass any data with a redirect is to add GET parameters to the URL you're passing in. To avoid XSS hacks you'd want to pass a specific constant like:
[current path you're passing in]?message=saved
And then process the message=saved parameter in the handler for the path you passed in.
A somewhat more complicated way would be not passing the data in the redirect, and instead using something like http://code.google.com/p/django-notify/ to store session-based data that is displayed to the user following the redirect.
You add ?saved=1 to the query string and check for it with something like:
saved = request.GET.get('saved', False)