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

 

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