Django variable: declare in urls - django

In urls.py:
(r'^bbb/id(?P<user_id>[0-9]+)/$', 'django.views.generic.simple.direct_to_template,
{'template': 'some.html', 'extra_context': {'user_id': user_id}}),
In some.html: {{ user_id }}
But there is an error: name 'user_id' is not defined (in urls.py)
So, how to declare that variable in urls.py and send it directly to 'some.html'???
Thanks.

You don't need to put it in extra_context. It's already captured in the URL, so is present in the params dictionary in the template: {{ params.user_id }}.
See the documentation - and also note that these old function-based generic views are deprecated, and you should be using the class-based TemplateView.

The variable really isn't declared in that python code. :) You do not need to set this variable in the view context. The view will receive named matches as **kwargs.

Related

Django get url variables within get_context data?

Say I have a url likes this
path(
'foo/<int:foo_id>/edit/',
views.FooView.as_view(),
name='foo',
),
and a view likes this:
def get(self, request, foo_id):
I find a common idiom is getting the URL variable foo_id into the context.
The only thing context has access to be default is request. I tried checking request and request.GET and could not see anything.
Is there a better way than:
Manually adding url variables to the context_data after get_context_data()
or passing it into get_context_data from a custom call from get? (ugly because class based views expect the same get_context_data signature)
The url parameters are stored in the .kwargs of the view. You thus can access and render these with:
{{ view.kwargs.foo_id }}
There is a reference with the name view that is passed which is the View object that is constructed when handling a request. We thus access the .kwargs attribute of that View object, and in the kwargs, we look for kwargs['foo_id'].
A peculiarity in Django is that a TemplateView [Django-doc] passes all it kwargs items as context data, if your view is thus a TemplateView, then you can render this with
<!-- only a TemplateView -->
{{ foo_id }}

Django Nested URL passing slugs

I'm looking to accomplish a URL as so:
/group/<group_name>/discussion/<discussion_name>/
My implementation is shown below
project urls.py
url(r'^group/', include('groups.urls')
group urls.py
url(r'^(?P<gslug>[\w-]+)/discussion/', include('discussions.urls')),
discussion urls.py
url(r'^(?P<slug>[\w-]+)',views.discussion_detail, name='discussion_detail'))
Unfortunately in my views.discussion_detail I do not have access to both gslug and slug. Where have I gone wrong?
discussion views.py
def discussion_detail(request, gslug, slug):
pass //logic in here
Make sure that you're passing variables into the view properly with the 'url' template tag like so
{% url 'discussion_detail' group.slug discussion.slug %}
Let me know if that works :)

django {% url %} tag without parameters

I have a url defined as follows:
url(r'^details/(?P<id>\d+)$', DetailView.as_view(), name='detail_view'),
In my templates, I want to be able to get the following url: /details/ from the defined url.
I tried {% url detail_view %}, but I get an error since I am not specifying the id parameter.
I need the url without the ID because I will be appending it using JS.
How can I accomplish this?
Just add this line to your urls.py:
url(r'^details/$', DetailView.as_view(), name='detail_view'),
or:
url(r'^details/(?P<id>\d*)$', DetailView.as_view(), name='detail_view'),
(This is a cleaner solution - thanks to Thomas Orozco)
You'll need to specify that id is optional in your view function:
def view(request, id=None):

django.contrib.auth views and template vars

In my "root" template I have something like this
{% if special %}
some_special_html
{% endif %}
The special template var is inserted in template by certain views.
The problem is that I need the password_change view to allso set the special template var.
What's best way to approach this?
Currently, the password_change view is called directly from urls.py:
url(r'^change_password/$', 'django.contrib.auth.views.password_change',
{'template_name': 'profile/password_change.html'},
name='password_change'),
As of at least Django 1.3, the password_change view does take extra context, although the documentation doesn't mention it.
You can pass extra keyword arguments to a view by using the kwargs argument of the url function, so to get the extra context in, do something like this:
url(r'^password/change/$',
auth_views.password_change,
{'template_name': 'profile/password_change.html'},
name='password_change',
kwargs=dict(extra_context={'special': 'special'}),
),
Either move your processing of the special var into a context_processor, or just wrap the password_change auth view with your own view that passes in the correct context.

Django: How to write current users name from every view (django)

I am writing small social application. One of the features is to write user name in the header of the site. So for example if I am logged in and my name is Oleg (username), then I should see:
Hello, Oleg | Click to edit profile
Otherwise I should see something like:
Hello Please sign-up or join
What I want is to show this on every page of my site. The obvious solution is to pass request.user object into every view of my site. But here http://www.willmer.com/kb/category/django/
I read that I can simply access request object from any template, just by enabling:
TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.request',
)
Not sure why but it actually didn't work :(
Maybe someone can help me and suggest a solution?
Thanks a lot,
Oleg
Also note that you should use django.core.context_processors.auth instead of django.core.context_processors.request if you don't need the whole request context. Then you can simply type:
Hello {{ user.get_full_name }}
in your template.
Don't forget to pass context_instance=RequestContext(request) when you call render_to_response (or use direct_to_template).
There are probably two issues here.
Firstly, if you redefine TEMPLATE_CONTEXT_PROCESSORS as you have done you will override the default, which is probably not a good idea. By default, the setting already includes the auth processor, which gives you a user variable anyway. If you definitely need the request as well you should do this (notice the +=):
TEMPLATE_CONTEXT_PROCESSORS += (
'django.core.context_processors.request',
)
Secondly, as described in the documentation here when using context processors you need to ensure that you are using a RequestContext in your template. If you're using render_to_response you should do it like this:
return render_to_response('my_template.html',
my_data_dictionary,
context_instance=RequestContext(request))
Use
from django.template import RequestContext
instead of
from django.template import Context
So now just call RequestContext(request, context)
More here.
Once you have set up the context process, the request is passed to the template as a variable named request. To access the user object within the variable you need to drill into it:
{{ request.user }}
Here is a list of attributes stored in the Django Request object. More specifically, here is the user attribute.
{% if user.is_authenticated %}
<p>Welcome, {{ user.username }}. Thanks for logging in.</p>
{% else %}
<p>Welcome, new user. Please log in.</p>
{% endif %}
Would be enough if you have TEMPLATE_CONTEXT_PROCESSORS already set.
I think just by adding locals() can solve the problem.
return render_to_response('my_template.html',
my_data_dictionary,locals())