Django Restframework.3

认证和权限

拿注册登陆来说,现在想实现的功能是:只有登陆的用户才能查看动物列表,没登陆的用户没有权限

  • 在项目文件中创建authentication.py的文件
from django.core.cache import cache
from rest_framework.authentication import BaseAuthentication

from App.models import User


class UserTokenAuthentication(BaseAuthentication): #继承自BaseAuthentication

    def authenticate(self, request):
        try:
            token = request.query_params.get("token")
            user_id = cache.get(token)

            user = User.objects.get(pk=user_id)
            return user, token    #将user和token存到request中
        except Exception as e:
            print(e)
  • 在对应的视图函数中添加认证
class AnimalsAPIView(ListCreateAPIView):

    queryset = Animal.objects.all()
    serializer_class = AnimalSerializer
    authentication_classes = UserTokenAuthentication,  #要加逗号,元组形式
  • 此时还并不可以实现功能,需要添加权限
  • 在项目文件中创建permission.py的文件
from rest_framework.permissions import BasePermission

from App.models import User


class LoginPermission(BasePermission):   #继承自BasePermission

    def has_permission(self, request, view):
        return isinstance(request.user, User)  #判断存储在request中的user是不是User的实例,如果是则返回True,有权限,反之没有权限
  • 如果想要实现哪个用户创建的动物就归属于哪个用户,则需要更该模型
class Animal(models.Model):

    a_name = models.CharField(max_length=16)
    # related_name 指定关联字段名字    默认 模型_set   指定之后就是我们的 related_name的值
    a_user = models.ForeignKey(User, related_name="u_animals")
  • 序列化
lass AnimalSerializer(serializers.ModelSerializer):
    a_user = serializers.ReadOnlyField(source="a_user.u_name")

    class Meta:
        model = Animal
        fields = ("id", "a_name", "a_user")


class UserSerializer(serializers.ModelSerializer):

    u_animals = AnimalSerializer(many=True, read_only=True)

    class Meta:
        model = User
        fields = ("id", "u_name", "u_password", "u_animals")
    • 当在视图类中调用create方法时,源代码是这样:
class CreateModelMixin(object):
    """
    Create a model instance.
    """
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def perform_create(self, serializer):
        serializer.save()

    def get_success_headers(self, data):
        try:
            return {'Location': str(data[api_settings.URL_FIELD_NAME])}
        except (TypeError, KeyError):
            return {}
      • 在执行保存的时候分发出来了一个perform_create函数,所以要重写这个函数
  • class AnimalsAPIView(ListCreateAPIView):
    
        queryset = Animal.objects.all()
        serializer_class = AnimalSerializer
        authentication_classes = UserTokenAuthentication,
        permission_classes = LoginPermission,
    
        def perform_create(self, serializer):
            serializer.save(a_user=self.request.user)

    这样在存储的时候a_user字段就会自动对应上request中存储的user的信息,即所登陆的用户

  • 如果只允许当前用户可以查看修改删除,仍然需要添加权限
  • class LoginPermission(BasePermission):
    
        def has_permission(self, request, view):
            return isinstance(request.user, User)
    
        def has_object_permission(self, request, view, obj):
            return request.user.u_animals.filter(pk=obj.id).exists()  #返回True或False

    obj.id为路由中的参数,/animals/1/ 即obj.id=1 

  • 路由形式为:

  • urlpatterns = [
        url(r'^animals/(?P<pk>\d+)/', views.AnimalAPIView.as_view()),
    ]

猜你喜欢

转载自www.cnblogs.com/zbcdamao/p/10990884.html
今日推荐