多對多表的增刪改查與drf的分頁


類的約束

繼承 必須繼續 定義 不然報錯

# 約束子類中必須實現f1 class Base(object):
def f1(self):
	raise NotImplementedError('必須要定義此規則')

class Foo(Base):

    def f1(self):
    print(123)

obj = Foo() 
obj.f1()

面向對象的繼承

class Base(object): 
	def f1(self):
		print('base.f1') 
		self.f2()
	def f2(self):
		print('base.f2')
class Foo(Base):
	def f2(self):
	print('foo.f2')

obj = Foo() 
obj.f1()
class Base(object): 
	x1 = 123

def f1(self):
	print(self.x1)

class Foo(Base): 
	x1 = 456

obj = Foo() 
obj.f1()
class APIView(object): 
	version_class = 123
    
    def get_version(self): 
        print(self.version_class)

class UserView(APIView): 
	version_class = 666

obj = UserView() 
obj.get_version()
class APIView(object): 
    version_class = 123

    def dispatch(self,method):
        self.initial() 
        getattr(self,method)()#反射

    def initial(self):
        print(self.version_class)

class UserView(APIView): 
    version_class = 666

    def get(self): 
        print('userview.get')

obj = UserView() 
obj.dispatch('get')

結果
print(self.version_class)
print('userview.get')
class URLPathVersion(object):

	def determin_version(self): 
        return 'v1'
class APIView(object): 
    version_class = None

    def dispatch(self,method): 
        version = self.initial() 
        print(version) 
        getattr(self,method)()

    def initial(self): 
        self.process_version()

    def process_version():
        obj = self.version_class() 
        return obj.determine_version()

class UserView(APIView): 
    version_class = URLPathVersion
    
	def get(self): 
    	print('userview.get')

obj = UserView() 
obj.dispatch('get')

處理 多對多實列

查詢 單條或多條

modul

from django.db import models

class Category(models.Model):
    """
    文章分類
    """
    name = models.CharField(verbose_name='分類',max_length=32)


class Article(models.Model):
    """
    文章表
    """
    status_choices = (
        (1,'發布'),
        (2,'刪除'),
    )
    status = models.IntegerField(verbose_name='狀態',choices=status_choices,default=1)
    title = models.CharField(verbose_name='標題',max_length=32)
    summary = models.CharField(verbose_name='簡介',max_length=255)
    content = models.TextField(verbose_name='文章內容')
    category = models.ForeignKey(verbose_name='分類',to='Category')

    tag = models.ManyToManyField(verbose_name='標簽',to='Tag',null=True,blank=True)

class Tag(models.Model):
    """標簽"""
    title = models.CharField(verbose_name='標簽',max_length=32)


url

from django.conf.urls import url
from django.contrib import admin
from api import views
urlpatterns = [
    url(r'^new/article/$', views.NewArticleView.as_view()),
    url(r'^new/article/(?P<pk>\d+)/$', views.NewArticleView.as_view()),

]

約束 展示

class NewArticleSerializer(serializers.ModelSerializer):
    tag_info = serializers.SerializerMethodField()
    
    class Meta:
        model = models.Article
        # fields = '__all__' #會自動展示
        fields = ['title','summary','tag_info']#自定義顯示 必須自己加 tag_info

    def get_tag_info(self,obj):#展示的第3種方法 obj對象
        return [row for row in obj.tag.all().values('id','title')]#字典加列表的形式

    
obj.字段.all().values('要顯示的字段1','要顯示的字段2')

view

class NewArticleView(APIView):

    def get(self,request,*args,**kwargs):
        pk = kwargs.get('pk')
        if not pk:
            queryset = models.Article.objects.all()
            ser = serializer.NewArticleSerializer(instance=queryset,many=True)
            return Response(ser.data)
        
        article_object = models.Article.objects.filter(id=pk).first()
        ser = serializer.NewArticleSerializer(instance=article_object, many=False)
        return Response(ser.data)

    def post(self,request,*args,**kwargs):
        ser = serializer.FormNewArticleSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        return Response(ser.errors)

    def put(self, request, *args, **kwargs):
        """全部更新"""
        pk = kwargs.get('pk')
        article_object = models.Article.objects.filter(id=pk).first()
        ser = serializer.FormNewArticleSerializer(instance=article_object, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        return Response(ser.errors)

    def patch(self,request,*args,**kwargs):
        """局部"""
        pk = kwargs.get('pk')
        article_object = models.Article.objects.filter(id=pk).first()
        ser = serializer.FormNewArticleSerializer(instance=article_object, data=request.data,partial=True)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        return Response(ser.errors)

    def delete(self,request,*args,**kwargs):
        pk = kwargs.get('pk')
        models.Article.objects.filter(id=pk).delete()
        return Response('刪除成功')

增加 編輯 更新

要注意的是 約束 可以用不一樣的 為了避免展示與增加不一樣

約束

class FormNewArticleSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Article
        fields = '__all__'
        
增加 編輯必須為 __all__

view

class NewArticleView(APIView):


    def post(self,request,*args,**kwargs):
        """增加"""
        ser = serializer.FormNewArticleSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        return Response(ser.errors)

    def put(self, request, *args, **kwargs):
        """全部更新"""
        pk = kwargs.get('pk')
        article_object = models.Article.objects.filter(id=pk).first()
        ser = serializer.FormNewArticleSerializer(instance=article_object, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        return Response(ser.errors)

    def patch(self,request,*args,**kwargs):
        """局部"""
        pk = kwargs.get('pk')
        article_object = models.Article.objects.filter(id=pk).first()
        ser = serializer.FormNewArticleSerializer(instance=article_object, data=request.data,partial=True)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        return Response(ser.errors)

    def delete(self,request,*args,**kwargs):
        pk = kwargs.get('pk')
        models.Article.objects.filter(id=pk).delete()
        return Response('刪除成功')

總結

根據業務需求不同 所以 serializers可以寫多個 來應對

分頁器

為什么要使用分頁

其實這個不說大家都知道,大家寫項目的時候也是一定會用的,

我們數據庫有幾千萬條數據,這些數據需要展示,我們不可能直接從數據庫把數據全部讀取出來,

這樣會給內存造成特別大的壓力,有可能還會內存溢出,所以我們希望一點一點的取,

那展示的時候也是一樣的,總是要進行分頁顯示,我們之前自己都寫過分頁。

那么大家想一個問題,在數據量特別大的時候,我們的分頁會越往后讀取速度越慢,

當有一千萬條數據,我要看最后一頁的內容的時候,怎么能讓我的查詢速度變快。

DRF給我們提供了三種分頁方式,我們看下他們都是什么樣的~~

分頁組件的使用

DRF提供的三種分頁

drf 內置分頁器 有幾種方式 只有獲取多條數據時才有用

方式1

定義配置文件settings

REST_FRAMEWORK = {
    "PAGE_SIZE":2,#代表2
}

modul

原來的

url

from django.conf.urls import url
from django.contrib import admin
from api import views
urlpatterns = [
    # 分頁
    url(r'^page/article/$', views.PageArticleView.as_view()),

    url(r'^page/view/article/$', views.PageViewArticleView.as_view()),
]

view

from rest_framework.pagination import PageNumberPagination
from rest_framework.pagination import LimitOffsetPagination
from rest_framework import serializers

class PageArticleSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Article
        fields = "__all__"

class PageArticleView(APIView):
    def get(self,request,*args,**kwargs):
        queryset = models.Article.objects.all()

        # 方式一:僅數據
        #分頁對象
        page_object = PageNumberPagination()
        # 調用 分頁對象.paginate_queryset方法進行分頁,得到的結果是分頁之后的數據
		# result就是分完頁的一部分數據
        result = page_object.paginate_queryset(queryset,request,self)
        
        # 序列化分頁之后的數據
        ser = PageArticleSerializer(instance=result,many=True)
        return Response(ser.data)

方式2

from rest_framework.pagination import PageNumberPagination
from rest_framework.pagination import LimitOffsetPagination
from rest_framework import serializers

class PageArticleSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Article
        fields = "__all__"

class PageArticleView(APIView):
    def get(self,request,*args,**kwargs):
        queryset = models.Article.objects.all()

        # 方式二:數據 + 分頁信息
        page_object = PageNumberPagination()
        result = page_object.paginate_queryset(queryset, request, self)
        ser = PageArticleSerializer(instance=result, many=True)
        return page_object.get_paginated_response(ser.data)

方式3

from rest_framework.pagination import PageNumberPagination#第1種方式
from rest_framework.pagination import LimitOffsetPagination
#第2種方式
from rest_framework import serializers

class PageArticleSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Article
        fields = "__all__"

class PageArticleView(APIView):
    def get(self,request,*args,**kwargs):
        queryset = models.Article.objects.all()

     # 方式三:數據 + 部分分頁信息
        page_object = PageNumberPagination()
        result = page_object.paginate_queryset(queryset, request, self)
        ser = PageArticleSerializer(instance=result, many=True)
        return Response({'count':page_object.page.paginator.count,'result':ser.data})

分頁的另一種方式

from rest_framework.pagination import PageNumberPagination
from rest_framework.pagination import LimitOffsetPagination
from rest_framework import serializers

class PageArticleSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Article
        fields = "__all__"
        
#重 定義  防止 一次取過多    
class HulaLimitOffsetPagination(LimitOffsetPagination):
    max_limit = 20
        
        
class PageArticleView(APIView):
    def get(self,request,*args,**kwargs):
        queryset = models.Article.objects.all()
        
#就是類不同
        page_object = HulaLimitOffsetPagination()
        result = page_object.paginate_queryset(queryset, request, self)
        ser = PageArticleSerializer(instance=result, many=True)
        return Response(ser.data)

分頁出現的警告問題 了解

url

from django.conf.urls import url
from django.contrib import admin
from api import views
urlpatterns = [
    url(r'^page/view/article/$', views.PageViewArticleView.as_view()),
]

seting

REST_FRAMEWORK = {
    "PAGE_SIZE":2,#代表2
	"DEFAULT_PAGINATION_CLASS":"rest_framework.pagination.PageNumberPagination"#為什么要配置
}

view

from rest_framework.generics import ListAPIView 
class PageViewArticleSerializer(serializers.ModelSerializer):
    
    class Meta: model = models.Article 
        fields = "__all__" 
class PageViewArticleView(ListAPIView): 
    queryset = models.Article.objects.all() 
    serializer_class = PageViewArticleSerializer

總結

drf 有分頁功能  對查詢的數據自動分頁  有3種方法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM