Vic Nicethemer
Vic Nicethemer

Reputation: 1111

How to access current user in Django class based view

I cannot access current logged in user in Django class based view:

models.py:

class Userproject(models.Model):
    class Meta:
        verbose_name = u'pp'
        verbose_name_plural = u'pps'

    user = models.ForeignKey(settings.AUTH_USER_MODEL, 
    related_name="project", verbose_name=_("Владелец проекта"))
    #user = models.ForeignKey(User, unique=True)

    name = models.TextField(u'Название проекта', unique=True)
    date_created = models.DateTimeField(u'Дата создания', 
        default=datetime.now(), db_index=True)
    date_until = models.DateTimeField(u'Оплачен по', default=datetime.now(), db_index=True)

views.py:

@login_required
class UserprojectList(ListView):
    context_object_name = 'userproject_list'
    queryset = Userproject.objects.filter(user=self.request.user)
    template_name = 'userproject_list.html'  

when i navigate to url i see error: name 'self' is not defined

if i change self.request.user to request.user the error is: name 'request' is not defined

Note that without user filtering view is working and shows data django 1.8.5

Upvotes: 15

Views: 27444

Answers (5)

moein zed
moein zed

Reputation: 11

You can also use self.kwargs.get("username") in def get_queryset(self): and then in your template have an anchor tag or a button that returns a URL with an argument named "username" <a href="{% url "myview" username=user.get_username() %}" >Link text</a>

class studentcourse(ListView):

    template_name = "course.html"
    model = course

    def get_queryset(self):
        qs =User.objects.prefetch_related("courses").get(
                username__iexact=self.kwargs.get("username")
 #where **courses** is the related_name in course model for
 #student foreign key field
         
        return qs

Upvotes: 1

Quique
Quique

Reputation: 956

@pythad's answer is correct. But on Django 1.9+, instead of the dispatch method, you can use django.contrib.auth.mixins.LoginRequiredMixin to replace the old-style @login_required decorator.

from django.contrib.auth.mixins import LoginRequiredMixin

class UserprojectList(LoginRequiredMixin, ListView):
    context_object_name = 'userproject_list'
    template_name = 'userproject_list.html'

    def get_queryset(self):
        return Userproject.objects.filter(user=self.request.user)

Upvotes: 6

pythad
pythad

Reputation: 4267

You can just overwrite get_queryset:

@login_required
class UserprojectList(ListView):
    context_object_name = 'userproject_list'
    template_name = 'userproject_list.html'
    def get_queryset(self):
        return Userproject.objects.filter(user=self.request.user)

Also you can't use decorators on classes, so you have to write something like this:

from django.utils.decorators import method_decorator

class UserprojectList(ListView):
    context_object_name = 'userproject_list'
    template_name = 'userproject_list.html'

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super(UserprojectList, self).dispatch(*args, **kwargs)

    def get_queryset(self):
        return Userproject.objects.filter(user=self.request.user)

Upvotes: 21

devinformatics
devinformatics

Reputation: 72

I think in the class-based views you would need to override the get_queryset() method in order to have access to the self.request object attached to the instance of the view rather than do this at the class level. The Classy Class-Based Views site has more information: http://ccbv.co.uk/projects/Django/1.8/django.views.generic.list/ListView/

Upvotes: 0

Aidas Bendoraitis
Aidas Bendoraitis

Reputation: 4003

I would try to do that in the __init__ method:

@login_required
class UserprojectList(ListView):
    context_object_name = 'userproject_list'
    template_name = 'userproject_list.html'
    def __init__(self, *args, **kwargs):
        super(UserprojectList, self).__init__(*args, **kwargs)
        self.queryset = Userproject.objects.filter(user=self.request.user)

Upvotes: 0

Related Questions