简体   繁体   中英

How to use current logged in user as PK for Django DetailView?

When defining URL patterns, I am supposed to use a regular expression to acquire a PK from the URL.

What if I want a URL that has no PK, and if it's not provided, it will use the currently logged in user? Examples:

  • visiting /user will get a DetailView of the currently logged in user
  • /user/edit will show an UpdateView for the currently logged in user

I tried hard-coding the pk= in the Detail.as_view() call but it reports invalid keyword.

How do I specify that in the URL conf?

My sample code that shows PK required error when visiting /user URL:

urlpatterns = patterns('',
    url(r'user/$', 
        DetailView.as_view(
            model=Account,
            template_name='user/detail.html')),
)`

An alternative approach would be overriding the get_object method of the DetailView subclass, something along the line of:

class CurrentUserDetailView(UserDetailView):
    def get_object(self):
        return self.request.user

Much cleaner, simpler and more in the spirit of the class-based views than the mixin approach.

EDIT: To clarify, I believe that two different URL patterns (ie one with a pk and the other without) should be defined separately in the urlconf. Therefore they could be served by two different views as well, especially as this makes the code cleaner. In this case the urlconf might look something like:

urlpatterns = patterns('',
    url(r"^users/(?P<pk>\d+)/$", UserDetailView.as_view(), name="user_detail"),
    url(r"^users/current/$", CurrentUserDetailView.as_view(), name="current_user_detail"),
    url(r"^users/$", UserListView.as_view(), name="user_list"),
)

And I've updated my example above to note that it inherits the UserDetailView , which makes it even cleaner, and makes it clear what it really is: a special case of the parent view.

As far as I know, you can't define that on the URL definition, since you don't have access to that information.

However, what you can do is create your own mixin and use it to build views that behave like you want.

Your mixin would look something like this:

class CurrentUserMixin(object):
    model = Account

    def get_object(self, *args, **kwargs):
        try:
            obj = super(CurrentUserMixin, self).get_object(*args, **kwargs)
        except AttributeError:
            # SingleObjectMixin throws an AttributeError when no pk or slug
            # is present on the url. In those cases, we use the current user
            obj = self.request.user.account

        return obj

and then, make your custom views:

class UserDetailView(CurrentUserMixin, DetailView):
    pass

class UserUpdateView(CurrentUserMixin, UpdateView):
    pass

Generic views uses always RequestContext . And this paragraph in the Django Documentation says that when using RequestContext with auth app, the template gets passed an user variable that represents current user logged in. So, go ahead, and feel free to reference user in your templates.

You can get the details of the current user from the request object . If you'd like to see a different user's details, you can pass the url as parameter. The url would be encoded like:

url(r'user/(?P<user_id>.*)$', 'views.user_details', name='user-details'),

views.user_details 2nd parameter would be user_id which is a string (you can change the regex in the url to restrict integer values, but the parameter would still of type string). Here 'sa list of other examples for url patterns from the Django documentation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM