认证和权限
拿注册登陆来说,现在想实现的功能是:只有登陆的用户才能查看动物列表,没登陆的用户没有权限
- 在项目文件中创建authentication.py的文件
from django.core.cache import cachefrom rest_framework.authentication import BaseAuthenticationfrom App.models import Userclass 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 BasePermissionfrom App.models import Userclass 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
\d+)/', views.AnimalAPIView.as_view()),]