基本的Django REST框架 - 只写资源

bco*_*ins 0 python django python-2.7 django-rest-framework

我正在尝试创建一个简单的服务,允许匿名用户提交他们的名字和电子邮件.我希望AllowAny添加他们的信息,IsAuthenticated在其他一切.我无法获得这种粒度.

models.py

from django.db import models

class Invitee(models.Model):
    name = models.CharField(max_length=255)
    email = models.EmailField(max_length=70,blank=True)
    modified = models.DateTimeField(auto_now=True)
Run Code Online (Sandbox Code Playgroud)

serializers.py

class InviteeSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Invitee
        fields = ('name', 'email')

    def create(self, validated_data):
        return Invitee(**validated_data)
Run Code Online (Sandbox Code Playgroud)

views.py

class InviteeViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows groups to be viewed or edited.
    """
    queryset = Invitee.objects.all()
    serializer_class = InviteeSerializer
Run Code Online (Sandbox Code Playgroud)

我应该把它放在什么地方和哪里,以便用户可以提交他们的姓名和电子邮件,但只有管理员可以阅读,更新,删除?谢谢你的帮助.

Kev*_*own 5

最简单,最安全的方法是使用多个序列化程序,这是您需要的每个用户类之一.您还需要使用自定义权限来强制认证用户和匿名用户之间的读/写差异.

class InviteeSerializer(serializers.HyperlinkedModelSerializer):

    def create(self, validated_data):
        return Invitee(**validated_data)

class LimitedInviteeSerializer(InviteeSerializer):

    class Meta:
        model = Invitee
        fields = ('name', 'email', ) # a limited subset of the fields

class FullInviteeSerializer(InviteeSerializer):

    class Meta:
        model = Invitee
        fields = ('name', 'email', "modified", ) # all of the fields
Run Code Online (Sandbox Code Playgroud)

虽然现在它看起来只是你需要读/写,如果你需要完整的读/写/删除权限,我建议你阅读这个Stack Overflow问题.

您还需要控制视图级别上正在使用的序列化程序.这需要使用权限重写的视图方法的组合来完成.

class InviteeViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows groups to be viewed or edited.
    """
    queryset = Invitee.objects.all()
    serializer_class = LimitedInviteeSerializer

    def get_serializer_class(self):
        if self.request.user.is_active:
            return FullInviteeSerializer

        return super(InviteeViewSet, self).get_serializer_class()
Run Code Online (Sandbox Code Playgroud)

在视图上,您​​需要覆盖get_serializer_class以根据用户是否处于活动状态来确定应使用的序列化程序.永远不应将匿名用户标记为活动用户,因此这是在排除已停用帐户时检查的最佳方式.

您还需要创建一个与内置IsAuthenticatedOrReadOnly权限相反的自定义权限类.您正在寻找经过身份验证的用户来执行所有操作,而匿名用户只能是只写用户.我已将此类称为IsAuthenticatedOrWriteOnly与其他权限类匹配.

class IsAuthenticatedOrWriteOnly(BasePermission):
    """
    The request is authenticated as a user, or is a write-only request.
    """

    def has_permission(self, request, view):
        WRITE_METHODS = ["POST", ]

        return (
            request.method in WRITE_METHODS or
            request.user and
            request.user.is_authenticated()
        )
Run Code Online (Sandbox Code Playgroud)

您只需要将现有的权限类列表添加,或使用在视图上手动覆盖它permission_classes.