Using Django I want to implement some middleware that will calculate some context that is to be used by the view itself.
For example, I have a middleware that looks at the request, and adds the user's permissions to the request, or some user configuration. The view looks at these permissions and decides how to handle the request using it.
This saves the need for multiple views (and multiple parts within the view) to query for this information.
I'm wondering what is the correct way to do that. One option is to just add request.user_permissions=... directly on the request. But is there some documented and expected way to do that?
There's no real documented way to do that, but Middleware is the correct place to do it and just adding properties to the request object is also the correct way.
You can confirm this, because Django is already doing it:
LocaleMiddelware
AuthenticationMiddleware
RemoteUserMiddleware
CurrentSiteMiddleware
SessionMiddleware
So just pick whatever is the most convenient data structure for your use case and tack that on to the request object.
This is not a perfect answer but at my experience I use this code. Every permission is saved in a boolean value which is true or false. You can access it in a html template like.
{% if request.user.is_admin %}
"Your code here"
{% else %}
"Your code here"
{% endif %}
and to send extra context you should create and pass an dicionary and pass it as as an argument to the render method from the view.
For eg:
def view(request, slug):
context = {'administrator':True}
blog_post = get_object_or_404(BlogPost, slug=slug)
context['blog_post'] = blog_post
return render(request, 'blog/detail_blog.html', context)
and access it like
{% if context.administrator %}
"Your code here"
{% else %}
"Your code here"
{% endif %}
I believe, since your middleware will calculate context, it should be implemented as context processor.
https://docs.djangoproject.com/en/3.1/ref/templates/api/#using-requestcontext
https://docs.djangoproject.com/en/3.1/ref/templates/api/#writing-your-own-context-processors
I'm using Django's messaging framework to alert a user that a message was sent successfully. By default, you display a Django message in a template using {{ messages }}. I want to avoid any possibility of confusion by renaming the variable to refer to Django's system message as something like {{ system_message }}, leaving {{ message }} free for referring to user messages.
I've tried doing something like
from django.contrib import messages as system_message
but renaming it in this context doesn't carry through to my template. Any suggestions?
Messages isn't a template tag but a template context variable provided by the "django.contrib.messages.context_processors.messages" processor. I think the best way to rename it is simply replacing django's context processor with your own version, e.g:
from django.contrib.messages.api import get_messages
def messages(request):
"""
Returns a lazy 'messages' context variable.
"""
return {'your_name_space': get_messages(request)}
I am trying to simply render {{ request.user }} from my base template and for whatever reason it is not rendering anything. I have even tested trying to return {{ request }} to no avail.
I am currently using django-annoying to render to the template (render_to) and have tried to switch back to using django.templates.RequestContext and that hasn't worked either.
I have a feeling it has something to do with caching, but I have edited my template to show test - {{ request }} and "test - " shows up just fine.
I have also tried to upgrade my django to 1.4 alpha to see if it resolves my issue.
This does not send the request to the template
#render_to('profile/index.html')
def home(request):
return {}
This works
#render_to('profile/index.html')
def home(request):
return {'request': request}
However, if I pass 'request': request into the template everything works.
Link to settings.py
I can give any more information that is requested.
You need to add the django.core.context_processors.request context processor.
I have a view that accepts a form submission and updates a model.
After updating the model, I want to redirect to another page, and I want a message such as "Field X successfully updated" to appear on this page.
How can I "pass" this message to the other page? HttpResponseRedirect only accepts a URL. I've seen this done before on other sites. How is this accomplished?
This is a built-in feature of Django, called "messages"
See http://docs.djangoproject.com/en/dev/topics/auth/#messages
From the documentation:
A message is associated with a User.
There's no concept of expiration or
timestamps.
Messages are used by the Django admin
after successful actions. For example,
"The poll Foo was created
successfully." is a message.
You can use django-flashcookie app
http://bitbucket.org/offline/django-flashcookie/wiki/Home
it can send multiple messages and have unlimited types of messages. Lets say you want one message type for warning and one for error messages, you can write
def simple_action(request):
...
request.flash['notice'] = 'Hello World'
return HttpResponseRedirect("/")
or
def simple_action(request):
...
request.flash['error'] = 'something wrong'
return HttpResponseRedirect("/")
or
def simple_action(request):
...
request.flash['notice'] = 'Hello World'
request.flash['error'] = 'something wrong'
return HttpResponseRedirect("/")
or even
def simple_action(request):
...
request.flash['notice'] = 'Hello World'
request.flash['notice'] = 'Hello World 2'
request.flash['error'] = 'something wrong'
request.flash['error'] = 'something wrong 2'
return HttpResponseRedirect("/")
and then in you template show it with
{% for message in flash.notice %}
{{ message }}
{% endfor }}
or
{% for message in flash.notice %}
{{ message }}
{% endfor }}
{% for message in flash.error %}
{{ message }}
{% endfor }}
I liked the idea of using the message framework, but the example in the django documentation doesn't work for me in the context of the question above.
What really annoys me, is the line in the django docs:
If you're using the context processor, your template should be rendered with a RequestContext. Otherwise, ensure messages is available to the template context.
which is incomprehensible to a newbie (like me) and needs to expanded upon, preferably with what those 2 options look like.
I was only able to find solutions that required rendering with RequestContext... which doesn't answer the question above.
I believe I've created a solution for the 2nd option below:
Hopefully this will help someone else.
== urls.py ==
from django.conf.urls.defaults import *
from views import *
urlpatterns = patterns('',
(r'^$', main_page, { 'template_name': 'main_page.html', }, 'main_page'),
(r'^test/$', test ),
== viewtest.py ==
from django.contrib import messages
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
def test(request):
messages.success( request, 'Test successful' )
return HttpResponseRedirect( reverse('main_page') )
== viewmain.py ==
from django.contrib.messages import get_messages
from django.shortcuts import render_to_response
def main_page(request, template_name ):
# create dictionary of items to be passed to the template
c = { messages': get_messages( request ) }
# render page
return render_to_response( template_name, c, )
== main_page.html ==
{% block content %}
{% if messages %}
<div>
{% for message in messages %}
<h2 class="{{message.tag}}">{{ message.message }}</h2>
{% endfor %}
</div>
{% endif %}
{% endblock %}
I have read and checked all answers, and it seems to me that the way to go now is using the messaging framework. Some of the replies are fairly old and have probably been the right way at the time of the posting.
There is a lot of solutions
1 Use Django-trunk version - it support sending messages to Anonymous Users
2 Sessions
def view1(request):
request.session['message'] = 'Hello view2!'
return HttpResponseRedirect('/view2/')
def view2(request):
return HttpResponse(request.session['message'])
3 redirect with param
return HttpResponseRedirect('/view2/?message=Hello+view2')
4 Cookies
Can you just pass the message as a query param oon the URL to which you're redirecting? It's not terribly RESTy, but it ought to work:
return HttpResponseRedirect('/polls/%s/results/?message=Updated" % p.id)
and have that view check for a message param, scrub it for nasties, and display it at the top.
I think this code should work for you
request.user.message_set.create(message="This is some message")
return http.HttpResponseRedirect('/url')
Take a look at Django's messages framework. http://docs.djangoproject.com/en/dev/ref/contrib/messages/#ref-contrib-messages
You could also have the redirect url be the path to an already parameterized view.
urls.py:
(r'^some/path/(?P<field_name>\w+)/$', direct_to_template,
{'template': 'field_updated_message.html',
},
'url-name'
),
views.py:
HttpResponseRedirect( reverse('url-name', args=(myfieldname,)) )
Note that args= needs to take a tuple.
The solution used by Pydev UA is the less intrusive and can be used without modifying almost nothing in your code. When you pass the message, you can update your context in the view that handles the message and in your template you can show it.
I used the same approach, but instead passing a simple text, passed a dict with the information in useful fields for me. Then in the view, updated context as well and then returned the rendered template with the updated context.
Simple, effective and very unobstrusive.
While all suggestions so far work, I would suggest going with Ry4an's (pass it in the request URL) - just change the actual text to a coded text within a predefined set of text messages.
Two advantages here:
Less chance of something hacking through your scrubbing of bad content
You can localize your messages later if needed.
The other cookie related methods.. well, they don't work if the browser doesn't support cookies, and are slightly more expensive.. But only slightly. They're indeed cleaner to the eye.
I often show messages about user actions to logged in users in my Django app views using:
request.user.message_set.create("message to user")
How could I do the same for anonymous (not logged in) users? There is no request.user for anonymous users, but the Django documentation says that using the "session" middleware you can do the same thing as the above code. The Django documentation that links to the session middleware claims it is possible, but I couldn't find how to do it from the session documentation.
This is what I do, using context processors:
project/application/context.py (check for messages and add them to the context):
def messages(request):
messages = {}
if 'message' in request.session:
message_type = request.session.get('message_type', 'error')
messages = {'message': request.session['message'],
'message_type': message_type}
del request.session['message']
if 'message_type' in request.session:
del request.session['message_type']
return messages
project/settings.py (add the context to the TEMPLATE_CONTEXT_PROCESSORS):
TEMPLATE_CONTEXT_PROCESSORS = (
"django.core.context_processors.request",
"django.core.context_processors.debug",
"django.core.context_processors.media",
"django.core.context_processors.auth",
"project.application.context.messages",
)
With the above the function messages will be called on every request and whatever it returns will be added to the template's context. With this in place, if I want to give a user a message, I can do this:
def my_view(request):
if someCondition:
request.session['message'] = 'Some Error Message'
Finally, in a template you can just check if there are errors to display:
{% if message %}
<div id="system_message" class="{{ message_type }}">
{{ message }}
</div>
{% endif %}
The message type is just used to style depending on what it is ("error","notice","success") and the way that this is setup you can only add 1 message at a time for a user, but that is all I really ever need so it works for me. It could be easily changed to allow for multiple messages and such.
See http://code.google.com/p/django-session-messages/ until the patch that enables session based messages lands in Django tree (as I saw recently, it's marked for 1.2, so no hope for quick addition...).
Another project with similar functionality is Django Flash (http://djangoflash.destaquenet.com/).
Store the data directly in the session, which is a dict-like object. Then in the view/template, check for the value.
More information here:
http://docs.djangoproject.com/en/dev/topics/http/sessions/#using-sessions-in-views
You could also create a middleware class to check for the session object on each request, and do your build up/tear down there.