【问题标题】:How to set different permissions depending on the request method?如何根据请求方式设置不同的权限?
【发布时间】:2021-09-26 00:01:42
【问题描述】:

我正在为一些投票创建一个 API。我需要作者是唯一可以查看投票的人,但需要经过身份验证的用户才能查看投票、问题和发布投票。作者只是用户的一个实例,就像选民一样。 我正在使用 Djoser 提供身份验证 API、模型序列化程序,并在 CBV 和视图集之间打破我的想法。

这是我的模型,如果有帮助的话。

from django.db import models
from django.contrib.auth import get_user_model
from django.utils import timezone
import datetime

User = get_user_model()


class Poll(models.Model):
    title = models.CharField(max_length=200, verbose_name="Naslov ankete")
    description = models.TextField(verbose_name="Opis ankete")
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name="polls", verbose_name="Autor")

    class Meta:
        verbose_name = "Anketa"
        verbose_name_plural = "Ankete"

    def __str__(self):
        return self.title


class Question(models.Model):
    poll = models.ForeignKey(Poll, on_delete=models.CASCADE, related_name="questions", verbose_name="Anketa")
    question_text = models.CharField(max_length=200, verbose_name="Tekst pitanja")
    pub_date = models.DateTimeField(verbose_name="Datum objavljivanja")

    class Meta:
        ordering = ["pub_date", "question_text"]
        verbose_name = "Pitanje"
        verbose_name_plural = "Pitanja"

    def __str__(self):
        return self.question_text

    def was_published_recently(self):
        now = timezone.now()
        return now - datetime.timedelta(days=1) <= self.pub_date <= now

    def verbose_question_text(self):
        return f"Pitanje: {self.question_text}"


class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name="choices", verbose_name="Pitanje")
    choice_text = models.CharField(max_length=200, verbose_name="Tekst opcije")
    # votes = models.IntegerField(default=0, verbose_name="Glasovi")

    class Meta:
        ordering = ["-votes", "pk"]
        verbose_name = "Opcija"
        verbose_name_plural = "Opcije"

    def __str__(self):
        return self.choice_text


class Vote(models.Model):
    choice = models.ForeignKey(Choice, on_delete=models.CASCADE, related_name="votes", verbose_name="Opcija")

    def __str__(self):
        return self.choice.choice_text

P。 S.:如果您认为投票可以更好地解决,也请提出建议。

【问题讨论】:

    标签: python django django-rest-framework permissions


    【解决方案1】:

    我认为您可以通过创建自定义权限(从 IsAuthenticated 类扩展)并覆盖方法 has_object_permissionsee documentation 来做到这一点。

    from rest_framework.permissions import IsAuthenticated
    
    
    class AuthorFullAccessUserPostOnly(IsAuthenticated):
        def has_object_permission(self, request, view, obj):
            if request.method == "POST":
                return True
            # This part better to implement with query
            # Also, it will work only for Vote object. 
            # You need to extend this method if you are going to use for another objects
            return request.user == obj.choice.question.poll.author
    

    您可以为每个视图(或视图集)创建一个 Permission 类,或者扩展这个类,尊重对象类型

    如果你想对不同的请求方法使用不同的条件,你可以使用某种这种逻辑

    class PoolPermissions(IsAuthenticated):
        def has_object_permission(self, request, view, obj):
            if request.method == "POST":
                self.has_post_object_permission(request, view, obj)
            elif request.method == "GET":
                self.has_get_object_permission(request, view, obj)
            elif request.method == "PUT":
                self.has_put_object_permission(request, view, obj)
            # etc.
            ...
    
        def has_get_object_permission(self, request, view, obj):
            # your logic
            pass
    
        def has_post_object_permission(self, request, view, obj):
            # your logic
            pass
    
        def has_put_object_permission(self, request, view, obj):
            # your logic
            pass
    
    
    

    【讨论】:

    • 只有一个细节... :) 如果我为每个方法创建不同的权限并将它们列在视图集的 permission_classes 属性中,这会起作用吗?
    • 你的意思是每个请求方法? :) 如果您为其他方法返回 True,它将起作用。根据我的喜好,创建一个 Permission 类并为每个请求方法调用不同的方法(我将在响应中添加一个示例)
    • 是的,我的意思是请求方法。 ? 谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-27
    • 2019-08-28
    • 1970-01-01
    • 2019-06-01
    • 2020-02-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多