django中restframework中自己定制视图功能

需求:1,一个表内数据的增删改查

           2,指定用户的表内数据增删改查

           3,获取表内按时间排序最后一个对象

 

       restframework 中的 ModelViewSet 只能解决需求一,如果我每个表中的数据关联一个用户表,每次获取数据都要筛选获取某个用户的所有数据,那么就不能用了,所以要自己定制视图功能,满足2,3需求

一。models类

解释:每个用户有唯一一个token,并且有多个备忘录的数据

class Users(models.Model):								# 用户表
	user_type_choice = (
		(1, '普通用户'),
		(2, 'VIP'),
		(3, 'SVIP'),
	)
	userType = models.IntegerField(choices=user_type_choice, default=1)
	open_id = models.CharField(max_length=255, unique=True, verbose_name='用户名')
	nickName = models.CharField(max_length=64, null=True, verbose_name='暱称')
	createTime = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
	updateTime = models.DateTimeField(auto_now=True, verbose_name='更新时间')
	is_active = models.BooleanField(default=True, verbose_name='激活状态')
	class Meta:
		verbose_name = '用户表'
		verbose_name_plural = verbose_name

class UserToken(models.Model):						# token表
	user = models.OneToOneField('Users', on_delete=models.CASCADE)
	token = models.CharField(max_length=64, verbose_name='用户的token')
	session_key = models.CharField(max_length=64)
	createTime = models.DateTimeField(auto_now_add=True)
	editTime = models.DateTimeField(auto_now=True)

class Memory(models.Model):
	content = models.TextField()
	createTime = models.DateTimeField(auto_now_add=True)
	editTime = models.DateTimeField(auto_now=True)
	user = models.ForeignKey('Users', on_delete=models.CASCADE, default='1')

	class Meta:
		verbose_name = '备忘录'
		verbose_name_plural = verbose_name

二。序列化类

from rest_framework import serializers
from .. import models
class MemorySerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Memory
        fields = '__all__'

三。认证类

解释:通过获取请求头的认证 token ,去 token 表中去认证,返回认证后对应的 user 对象(因为 token 表和 user 表是一一对应的)

from rest_framework.authentication import BaseAuthentication
from ..models import UserToken
from rest_framework import exceptions

def md5(user):
    import hashlib
    import time
    ctime = str(time.time())

    m = hashlib.md5(bytes(user, encoding='utf-8'))
    m.update(bytes(ctime, encoding='utf-8'))
    return m.hexdigest()

class Authtication(BaseAuthentication):
    def authenticate(self, request):
        token = request._request.META.get('HTTP_AUTHORIZATION')     #前端通过请求头发送,所以通过请求头获取

        token_obj = UserToken.objects.filter(token=token).first()
        if not token_obj:
            raise exceptions.AuthenticationFailed("用户认证失败")
        return token_obj.user, token

    def authenticate_header(self, request):
        pass

四。url映射

解释:本来是两个,因为想增加一个按时间查询最近的数据,所以增加了一个

urlpatterns = [
	url('^api/v1/memorys/$', views.Memorys.as_view({'get':'list', 'post':'create'}), name='memorys'),
	url('^api/v1/memorys/last/$', views.Memorys.as_view({'get':'retrieve_last'}), name='memorys1'),
	url('^api/v1/memorys/(?P<pk>\d+)/$', views.Memorys.as_view({'get':'retrieve', 'delete':'destroy', 'put':'update', 'patch':'partial_update'}), name='memorys2'),
]

 

五。视图类

解释:

1. 这里继承并修改了增删改查的类,其中 request.user 对象是认证时候返回的,获取id,然后筛选 queryset,得到的 queryset 只包含认证后的用户, 然后把筛选后的 queryset 赋值给 self.queryset, 之后执行父类的 list 函数就行了。所以我们的任务是修改 self.queryset ,让它只包含当前用户的数据。

2. createView 类是要增加的 QueryDict 中没有用户id,所以要添加的话会出现错误。但是现在 QueryDict 是不能修改的,所以通过 request.data._mutable = True 让它变的可以修改,因为是个字典,所以用 request.data['user'] = request.user.id 直接赋值就好了,之后就调用父类的增加方法来增加。这里的任务主要是修改 QueryDict, 让它包含用户id。

3. 第二个需求在 RetrieveView 类中,通过 instance = queryset.filter(user_id=userid).latest('editTime') 获取最后一个数据,然后让它序列化,返回就行了,这里不需要调用父类,因为没有多少操作。

class ListView(ListModelMixin):
    def list(self, request, *args, **kwargs):
        try:
            # 这里改变的是self.queryset,让他按照我们的意思去筛选
            userid = request.user.id
            queryset = self.filter_queryset(self.get_queryset())
            self.queryset = queryset.filter(user_id=userid)

            response = super().list(request, *args, **kwargs)
            return Response({'code':200, 'data': response.data, 'msg':'获取成功'})
        except:
            return Response({'code':500, 'msg':'获取失败'})

class createView(CreateModelMixin):
    def create(self, request, *args, **kwargs):
        try:
            # 添加的数据里面要加入用户的id
            request.data._mutable = True                            # 把 QueryDict 变为可以变的
            request.data['user'] = request.user.id     # 添加当前验证的用户id
            response = super().create(request, *args, **kwargs)
            return Response({'code':200, 'data': response.data, 'msg':'创建成功'})
        except Exception as e:
            print(e)
            return Response({'code':500, 'msg':'创建失败', 'data':str(e)})

class RetrieveView(RetrieveModelMixin):
    def retrieve(self, request, *args, **kwargs):
        try:
            # 这里改变的是self.queryset,让他按照我们的意思去筛选
            userid = request.user.id
            queryset = self.filter_queryset(self.get_queryset())
            self.queryset = queryset.filter(user_id=userid)

            response = super().retrieve(request, *args, **kwargs)
            return Response({'code':200, 'data': response.data, 'msg':'获取成功'})
        except Exception as e:
            print(e)
            return Response({'code':500, 'msg':'获取失败', 'data':str(e)})

    def retrieve_last(self, request, *args, **kwargs):
        try:
            # 这里改变的是self.queryset,让他按照我们的意思去筛选
            userid = request.user.id
            queryset = self.filter_queryset(self.get_queryset())
            instance = queryset.filter(user_id=userid).latest('editTime')
            serializer = self.get_serializer(instance)
            return Response({'code':200, 'data': serializer.data, 'msg':'获取成功'})
        except Exception as e:
            print(e)
        return Response({'code': 500, 'msg': '获取失败', 'data': str(e)})

class UpdateView(UpdateModelMixin):
    def update(self, request, *args, **kwargs):
        try:
            # 这里改变的是self.queryset,让他按照我们的意思去筛选
            userid = request.user.id
            queryset = self.filter_queryset(self.get_queryset())
            self.queryset = queryset.filter(user_id=userid)

            response = super().update(request, *args, **kwargs)
            return Response({'code':200, 'data': response.data, 'msg':'修改成功'})
        except Exception as e:
            print(e)
            return Response({'code':500, 'msg':'修改失败', 'data':str(e)})

class DestroyView(DestroyModelMixin):
    def destroy(self, request, *args, **kwargs):
        try:
            # 这里改变的是self.queryset,让他按照我们的意思去筛选
            userid = request.user.id
            queryset = self.filter_queryset(self.get_queryset())
            self.queryset = queryset.filter(user_id=userid)

            response = super().destroy(request, *args, **kwargs)
            return Response({'code':200, 'data': response.data, 'msg': '删除成功'})
        except Exception as e:
            print(e)
            return Response({'code':500, 'msg':'删除失败', 'data':str(e)})

class myViewSet(ListView,
                createView,
                RetrieveView,
                UpdateView,
                DestroyView,
                GenericViewSet):
    pass

六。使用

解释:在视图函数中,继承我们定制的类,然后只添加这行代码,就可以实现开头那三个需求了

from .utils.myAppViewSet import myViewSet
class Memorys(myViewSet):
	"""
	备忘录
	"""
	queryset = models.Memory.objects.all().order_by("-editTime")
	serializer_class = myAppSerializer.MemorySerializer

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章