drf第三讲——筛选、视图

内容回顾

  • restful规范
- URL中一般用名词: 
	http://www.luffycity.com/article/ (面向资源编程,网络上东西都视为资源)
- 根据请求不同做不同操作:GET/POST/PUT/DELTE/PATCH
- 筛选条件,在URL参数中进行传递:
	http://www.luffycity.com/article/?page=1&category=1
	
一般传输的数据格式都是JSON
  • 分页的 两种方式
    • Page
    • Offset

今日概要

  • 作业:呼啦圈
  • 筛选
  • 试图(源码)

今日详细

1.作业:呼啦圈

1.1 表结构设计
  • 不会经常变化的值放在内存:choices形式,避免跨表性能低(这里的类型的保存就是把数据储存在内存)
  • 分表:如果表中列太多/大量内容可以选择水平分表(这里的内容拆分就是水平分表)
  • 表自关联
from django.db import models

class UserInfo(models.Model):
	"""
	用户表
	"""
	username = models.CharField(verbose_name="用户名",max_length=32)
	password = models.CharField(verbose_name="密码",max_length=128)

class Article(models.Model):
	"""
	文章详情表
	"""
	status = (
		(1,"发布"),
		(2,"删除"),
	)
	#因为hulaquan这种上面的标签分类一般是不变的,我们可以以这种方式放在我们的内存里面
	#如果还件一张表的话,可以,但是连表查询就很慢的
	category_choices = (
		(1,'咨询'),
		(2, '公司状态'),
		(3, '分享'),
		(4, '答疑'),
		(5, '其他'),
	)
	title = models.CharField(verbose_name="标题",max_length=128)
	create_at = models.DateTimeField(verbose_name="创建时间",auto_now_add=True,)
	read_count = models.IntegerField(verbose_name="浏览数量",default=0)
	comment_count = models.IntegerField(verbose_name="评论数",default=0)
	summary = models.CharField(verbose_name="内容简介",max_length=64)
	photo = models.ImageField(verbose_name="文章图片",upload_to=None,null=True,blank=True)
	article_status = models.IntegerField(verbose_name="文章状态",choices=status,default=1)
	category = models.IntegerField(verbose_name="标签分类",choices=category_choices)
	author = models.ForeignKey(verbose_name="作者",to="UserInfo")

class ArticleDetail(models.Model):
	"""
	文章详情表:这里为什么把文章内容表抽离出来新建一张表?因为内容的信息可能过大,我们在加载全部分
	#文章的时候,其实不需要文章的内容,这样就会降低用户访问的速度,所以在访问详情页的时候返回内容比较好
	"""
	article = models.OneToOneField(verbose_name="文章表",to="Article")
	content = models.TextField(verbose_name="文章内容")

class Comment(models.Model):
	"""
	文章评论
	"""
	content = models.TextField(verbose_name="评论内容")
	content_time = models.DateTimeField(verbose_name="评论时间",auto_now_add=True)
	zan = models.IntegerField(verbose_name="点赞数",default=0)
	article = models.ForeignKey(verbose_name="评论文章",to="Article")
	user = models.ForeignKey(verbose_name="评论用户", to='UserInfo')
	'''这里本来还可以建立一个自关联的字段,这样回复的内容就可以和进行多重回复'''
	#parent = models.ForeignKey(verbose_name='回复', to='self', null=True, blank=True)
1.32功能实现

1.2.1内容相关

serializer.py(为了数据更好的输出可以定义更多的serializer)

from rest_framework import serializers

from api import models


class ArticleSerializer(serializers.ModelSerializer):
	comment_count = serializers.SerializerMethodField()

	class Meta:
		model = models.Article
		# fields = "__all__"
		exclude = ['author']

	def get_comment_count(self, obj):
		# xx_set反向查表
		return obj.comment_set.count()


class ArticleDetailSerializer(serializers.ModelSerializer):
	class Meta:
		model = models.ArticleDetail
		# fields = "__all__"
		exclude = ['article']

class CommentSerializer(serializers.ModelSerializer):
	class Meta:
		model = models.Comment
		fields = "__all__"


class PostCommentSerializer(serializers.ModelSerializer):
	class Meta:
		model = models.Comment
		exclude = ['user']


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


class PageArticleSerializer(serializers.ModelSerializer):
    #反向查表
	content = serializers.CharField(source="articledetail.content")
	author = serializers.CharField(source="author.username")
    #choice选择
	category = serializers.CharField(source="get_category_display")
    #定义时间钩子,显示固定的格式
	date = serializers.SerializerMethodField()

	class Meta:
		model = models.Article
		fields = "__all__"

	def get_date(self, obj):
		return obj.create_at.strftime('%Y-%m-%d %H:%M')

views.py(有几个知识点)

from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
from api import models
from api import seriailzer


class ArticleView(APIView):
	"""文章表"""
	def get(self,request,*args,**kwargs):
		"""
		获取文章列表
		:param request:
		:param args:
		:param kwargs:
		:return:
		"""
		pk = kwargs.get('pk')
		if not pk:
			condition = {}
			#query_params == request.GET
			category = request.query_params.get('category')
			if category:
				condition['category'] = category
			#filter(None)获取所有的数据
			queryset= models.Article.objects.filter(**condition).order_by('-create_at')
			pager = PageNumberPagination()
			result = pager.paginate_queryset(queryset,request,self)
			ser = seriailzer.ArticleListSerializer(instance=result,many=True)
			return Response(ser.data)
		article_object = models.Article.objects.filter(pk=pk).first()
		ser = seriailzer.PageArticleSerializer(instance=article_object, many=False)
		return Response(ser.data)

	def post(self, request, *args, **kwargs):
		"""
		新增文章:这里面有两个知识点,一个是文章和内容可以同时实例化多个seializers,并且
				同时保存,第二个是保存的时候可以加一些字段,实现自定制。
		:param request:
		:param args:
		:param kwargs:
		:return:
		"""
		ser = seriailzer.ArticleSerializer(data=request.data)
		ser_detail = seriailzer.ArticleDetailSerializer(data=request.data)
		# 注意一点,我们post数据的时候一定要把两张表的该填的数据填上
		if ser.is_valid() and ser_detail.is_valid():
			# 文章表保存之后返回的是一个对象,它里面包含了ser的所有信息
			article_object = ser.save(author_id=1)
			# ser_detail.save(article.id=article_object.id)
			# 可以使用上面的方式给我们的文章内容表的article字段加内容,也可是使用下面的方式给我们的
			# 文章外键加内容,都是可以的
			ser_detail.save(article=article_object)
			return Response("保存成功")
		return Response("失败")


class CommentView(APIView):
	""" 评论接口 """
	def get(self, request, *args, **kwargs):
		""" 评论列表 """
		article_id = request.query_params.get('article')
		queryset = models.Comment.objects.filter(article_id=article_id)
		ser = seriailzer.CommentSerializer(instance=queryset, many=True)
		return Response(ser.data)

	def post(self, request, *args, **kwargs):
		""" 添加评论 """
		ser = seriailzer.PostCommentSerializer(data=request.data)
		if ser.is_valid():
			ser.save(user_id=2)
			return Response('成功')
		return Response('失败')

1.2.2评论列表

  • 查看评论列表
    访问时:http://127.0.0.1:8000/hg/comment/?article=2

  • 添加评论(两种方式:推荐使用第一种)

    http://127.0.0.1:8000/hg/comment/
    
    {
    	article:1,
    	content:'xxx'
    }
    
    http://127.0.0.1:8000/hg/comment/?article=1
    
    {
    	content:'xxx'
    }
    

2. 筛选

案例:在文章列表时候,添加筛选功能。

全部:http://127.0.0.1:8000/hg/article/
筛选:http://127.0.0.1:8000/hg/article/?category=2
class ArticleView(APIView):
    """ 文章视图类 """

    def get(self,request,*args,**kwargs):
        """ 获取文章列表 """
        pk = kwargs.get('pk')
        if not pk:
            condition = {}
            category = request.query_params.get('category')
            if category:
                condition['category'] = category
            queryset = models.Article.objects.filter(**condition).order_by('-date')
            
            pager = PageNumberPagination()
            result = pager.paginate_queryset(queryset,request,self)
            ser = ArticleListSerializer(instance=result,many=True)
            return Response(ser.data)
        article_object = models.Article.objects.filter(id=pk).first()
        ser = PageArticleSerializer(instance=article_object,many=False)
        return Response(ser.data)
drf的组件:内置了筛选的功能
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from . import models

from rest_framework.filters import BaseFilterBackend

class MyFilterBackend(BaseFilterBackend):

    def filter_queryset(self, request, queryset, view):
        val = request.query_params.get('cagetory')
        return queryset.filter(category_id=val)
    

class IndexView(APIView):

    def get(self,request,*args,**kwargs):
        # http://www.xx.com/cx/index/
        # models.News.objects.all()

        # http://www.xx.com/cx/index/?category=1
        # models.News.objects.filter(category=1)

        # http://www.xx.com/cx/index/?category=1
        # queryset = models.News.objects.all()
        # obj = MyFilterBackend()
        # result = obj.filter_queryset(request,queryset,self)
        # print(result)
        
        return Response('...')

3.视图(***)

  • APIView,感觉没提供功能。
  • GenericAPIView,桥梁,内部定义:get_queryset/get_serilizer/get_page…
ListAPIView(展示所有),CreateAPIView(创建),RetrieveAPIView(单条数据展示),UpdateAPIView(更新),DestroyAPIView(删除)
class TagSer(serializers.ModelSerializer):
    class Meta:
        model = models.Tag
        fields = "__all__"

class TagView(ListAPIView,CreateAPIView):
	"""
	展示所有的数据和添加数据
	"""
    queryset = models.Tag.objects.all()
    serializer_class = TagSer

    def get_serializer_class(self):
        """
        重写父类的方法,定制展示和提交数据时的serializer
        """
        if self.request.method == 'GET':
            return TagSer
        elif self.request.method == 'POST':
            return OtherTagSer
    def perform_create(self,serializer):
        """
        重写父类里面的方式,自定制保存的数据
        """
        serializer.save(author=1)

class TagDetailView(RetrieveAPIView,UpdateAPIView,DestroyAPIView):
    """
    展示单条信息,更新个删除数据:为什么和上面的分开?因为单条的展示和多条数据的展示是有冲突的
    因为,他们里面都定义了get方法,所以我们在使用的时候把他们分开并且可定制不同的serializer
    """
    queryset = models.Tag.objects.all()
    serializer_class = TagSer

扩展

GenericAPIView(APIVIew)

支持定义的属性
  • 列表视图与详情视图通用:
    • queryset 列表视图的查询集
    • serializer_class 视图使用的序列化器
  • 列表视图使用:
    • pagination_class 分页控制类
    • filter_backends 过滤控制后端
  • 详情页视图使用:
    • lookup_field 查询单一数据库对象时使用的条件字段,默认为’pk
    • lookup_url_kwarg 查询单一数据时URL中的参数关键字名称,默认与look_field相同
提供的方法

get_queryset(self)

返回视图使用的查询集,是列表视图与详情视图获取数据的基础,默认返回queryset属性,可以重写

get_serializer_class(self)

返回序列化器类,默认返回serializer_class,可以重写,

*get_serializer(self, args, kwargs)

返回序列化器对象,被其他视图或扩展类使用,如果我们在视图中想要获取序列化器对象,可以直接调用此方法。

get_object(self)

返回详情视图所需的模型类数据对象,默认使用lookup_field参数来过滤queryset。 在试图中可以调用该方法获取详情信息的模型类对象。

五个扩展类

ListModelMixin

CreateModelMixin

RetrieveModelMixin

UpdateModelMixin

DestroyModelMixin

几个子类视图

CreateAPIView

提供 post 方法

继承自: GenericAPIView、CreateModelMixin

ListAPIView

提供 get 方法

继承自:GenericAPIView、ListModelMixin

RetireveAPIView

提供 get 方法

继承自: GenericAPIView、RetrieveModelMixin

DestoryAPIView

提供 delete 方法

继承自:GenericAPIView、DestoryModelMixin

UpdateAPIView

提供 put 和 patch 方法

继承自:GenericAPIView、UpdateModelMixin

RetrieveUpdateAPIView

提供 get、put、patch方法

继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin

RetrieveUpdateDestoryAPIView

提供 get、put、patch、delete方法

继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值