Django auth:self.request.user在视图集中始终是匿名的 [英] Django auth: self.request.user is always Anonymous in viewset

查看:104
本文介绍了Django auth:self.request.user在视图集中始终是匿名的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使服务器仅返回由登录用户创建的文档.我正在关注这篇文章这一个,但登录的用户返回为匿名".

I'm trying to make the server only return documents which were created by the logged-in user. I'm following this post and this one but the logged in user is returned as "Anonymous".

我正在将Django Rest Framework与Django Rest Auth和一个自定义用户一起使用,但没有其他自定义项.

I am using Django Rest Framework with Django Rest Auth, and a custom user, but no other customisations.

Django 2.0.10

Django 2.0.10

这是我在api.py中的视图集:

Here is my viewset in api.py:

from rest_framework import viewsets, permissions

from .models import List, Item
from .serializers import ListSerializer, ItemSerializer


class ListViewSet(viewsets.ModelViewSet):
    # queryset = List.objects.all()
    # permission_classes = [permissions.AllowAny, ]
    model = List
    serializer_class = ListSerializer

    def get_queryset(self):
        print(self.request.user)
        return List.objects.filter(created_by=self.request.user)

    def pre_save(self, obj):
        obj.created_by = self.request.user

Settings.py:

Settings.py:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',
    ],
}

AUTH_USER_MODEL = 'users.CustomUser'

# django rest auth
ACCOUNT_AUTHENTICATION_METHOD = 'email'

我已经阅读了有关此问题的其他文章,这些文章都谈论自定义中间件,但是除非django-rest-framework或django-rest-auth实际上是这样的事情,否则我还没有创建自定义中间件?而且这些帖子似乎并未显示如何吸引用户进入视图集.

I've read other posts about this issue which all talk about custom middleware, but I haven't created a custom middleware unless django-rest-framework or django-rest-auth is actually such a thing? And the posts don't seem to show how to get the user in the viewset.

帖子还很旧,所以Django可能已经改变了.

Also the posts are old, so Django has probably changed.

来自此帖子,我尝试过以下,它不起作用:

From this post I tried the following, it did not work:

class ListViewSet(viewsets.ModelViewSet):
    # queryset = List.objects.all()
    # permission_classes = [permissions.AllowAny, ]
    model = List
    serializer_class = ListSerializer

    def get_queryset(self):
        print(self.request.user)
        self.request.custom_prop = SimpleLazyObject(lambda: get_actual_value(self.request))
        print(self.request.custom_prop)
        return List.objects.filter(created_by=self.request.user)

    def pre_save(self, obj):
        obj.created_by = self.request.user

非常感谢您的帮助.这是一个基本的要求,应该很简单,但是我绝对会陷入困境.

I'd be very grateful for any help. This is such a basic requirement, it ought to be simple but I'm absolutely stuck.

如果可以帮助其他人,以下是我基于Lucas Weyne的回答的工作代码.我扩展了逻辑,以便用户看到他们创建的所有列表,以及所有带有标志"is_public"的列表,但只能修改他们创建的列表.

in case it helps somebody else, below is my working code based on Lucas Weyne's answer. I extended the logic so the user sees all Lists they created, AND all lists that have the flag "is_public", but can only modify lists they created.

我设置了权限.AllowAny,因为我希望未登录的用户查看公共列表.在客户端代码中,我检查用户是否已登录,如果是用户,则在查询标头中发送令牌.

I have set permissions.AllowAny because I want users who are not logged in to see public lists. In the client code, I check whether the user is logged in, and if they are I send the token in the query header.

请注意Q对象的使用,这是我发现返回满足两个条件之一的记录的最简单方法.我在 Django rest框架文档中找不到Q对象的任何提及.我最终在主要Django文档中找到了它.

Note the use of the Q object which is the easiest way I could find to return records that satisfy either of the two conditions. I couldn't find any mention of the Q object in the Django rest framework docs. I eventually found it in the main Django docs.

这一切似乎都奏效,但是如果您发现我做错了什么,请发表评论!我不确定这是否是满足要求的Django方法,但我喜欢这样的事实,即权限逻辑全部集中在一个地方.

This all seems to work but if you spot something I've done wrong, please comment! I am not sure if this is the Django way to approach the requirement but I like the fact that the permissions logic is all in one place.

from rest_framework import viewsets, permissions
from .models import List
from .serializers import ListSerializer
from django.db.models import Q


class ListViewSet(viewsets.ModelViewSet):
    """
    ViewSet for lists. Before allowing any operation, the user's status is checked.

    Anybody can view a public list.
    A logged-in user can create lists.
    A logged-in user can view, edit and delete the lists they created.
    """
    permission_classes = [permissions.AllowAny, ]
    model = List
    serializer_class = ListSerializer

    def get_queryset(self):
        # restrict any method that can alter a record
        restricted_methods = ['POST', 'PUT', 'PATCH', 'DELETE']
        if self.request.method in restricted_methods:
            # if you are not logged in you cannot modify any list
            if not self.request.user.is_authenticated:
              return List.objects.none()

            # you can only modify your own lists
            # only a logged-in user can create a list and view the returned data
            return List.objects.filter(created_by=self.request.user)

        # GET method (view list) is available to owner and for public lists
        if self.request.method == 'GET':
          if not self.request.user.is_authenticated:
            return List.objects.filter(is_public__exact=True)

          return List.objects.filter(Q(created_by=self.request.user) | Q(is_public__exact=True))

        # explicitly refuse any non-handled methods
        return List.objects.none()

    def pre_save(self, obj):
        obj.created_by = self.request.user

推荐答案

为使客户端通过TokenAuthentication进行身份验证,令牌密钥应包含在Authorization HTTP标头中.可浏览的API仅能够通过基本身份验证或会话身份验证传递用户凭据.要测试您的API,您需要一个HTTP客户端,例如 cURL

For clients to authenticate via TokenAuthentication, the token key should be included in the Authorization HTTP header. Browseable API is only able to pass user credentials through Basic or Session authentication. To test your API, you'll need a HTTP client like cURL

curl -H "Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b" <url>

允许对视图的任何访问将在List.objects.filter(created_by=self.request.user)处为未经授权的用户而不是401 Unauthorized引发内部服务器错误.如果查询集依赖于用户,则应添加权限类以要求用户凭据.

Allow any access to your view will raise an internal server error at List.objects.filter(created_by=self.request.user) for unauthorized users instead 401 Unauthorized. If the queryset is user dependant, you should add a permission class to require user credentials.

class ListViewSet(viewsets.ModelViewSet):
    permission_classes = [permissions.IsAuthenticated, ]
    serializer_class = ListSerializer

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

    def pre_save(self, obj):
        obj.created_by = self.request.user

这篇关于Django auth:self.request.user在视图集中始终是匿名的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆