#25397 closed Cleanup/optimization (fixed)
Warn of clash between generic view context variables and template context processor variables
Reported by: | Mathieu Hinderyckx | Owned by: | Jacek Bzdak |
---|---|---|---|
Component: | Documentation | Version: | 1.8 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | yes | UI/UX: | no |
Description
Problem
I have a custom User model, and a DetailView of that Model.
urls.py:
urlpatterns = [ url(r'^(?P<pk>\d+)/$', views.UserDetailView.as_view(), name='user-detail'), ]
views.py:
class UserDetailView(DetailView): model = User template_name = 'app_example/profile.html'
Template:
<h2>Log in information</h2> {% if user.is_authenticated %} <p>User authenticated. User oject: {{user}}.</p> {% else %} <p>User not authenticated. User object: {{user}}.</p> {% endif %} <h2>DetailView Object</h2> <p>{{object}}</p>
To replicate the problem; Create 2 users, log in with 1 user, and visit the detailpage with the pk of the 2nd user. Do this also when both users are logged out.
Now, what happens is that the user.is_authenticated block is (wrongfully) always shown, and {{user}} is always the Detailview object instead of the request.user. The {{object}} is the Detailview object (as expected).
Problem
The documentation and example on DetailView mentions that its item is available through {{object}}. However, it's also available by default as {{obj._meta.model_name}} through the get_object_context_name() method from the SingleObjectMixin, which is not clearly mentioned. When using the 'User' model, this interferes with the {{user}} context variable from middleware. In any case (user = request.user or user = object), the 'is_authenticad' field on that variable should evaluate to False in the example above, but does not, why that is, is not clear to me yet. As this {{user}} variable is commonly used with authentication on sites, I think this should be mentioned clearly. Now, for example menu's for logged-in users only are shown while this shouldn't be. If this variable is the object from the DetailView instead of the request, this might lead to a lot of unexpected behaviour when developing templates.
Workaround
set 'context_object_name' on the DetailView to something else.
Change History (8)
comment:1 by , 9 years ago
comment:2 by , 9 years ago
Component: | Generic views → Documentation |
---|---|
Easy pickings: | set |
Summary: | DetailView of User model breaks user context variable in templates → Warn of clash between generic view context varaibles and template context processor varaibles |
Triage Stage: | Unreviewed → Accepted |
Type: | Bug → Cleanup/optimization |
I think trying to be "smart" and change or disallow the certain context variable names won't be worth it. I'd rather work to deprecate the auth context_processor (user
can be replaced by request.user
, but a solution for replacing perms
isn't so clear). Meanwhile, we can certainly improve the documentation.
comment:3 by , 9 years ago
Summary: | Warn of clash between generic view context varaibles and template context processor varaibles → Warn of clash between generic view context variables and template context processor variables |
---|
Your solution seems to break forward compatibility, since the public method
get_context_object_name
describes the default behavior in the current documentation: https://docs.djangoproject.com/en/1.8/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.get_context_object_name, plus I think it is a good implementation, besides this case...Maybe we could either :
Both solutions have limits, especially the second one...