在日常开发中,我比较喜欢用restframework中的APIView来做开发,现有接口过滤的功能,周转google和百度,终于找到适合自己的用法,以此记录一下
model.py
class Article(Base):
"""文章模型"""
COMMENT_STATUS = (
(0, "禁止评论"),
(1, "允许评论"),
)
PUBLIC_STATUS = (
(0, "私人访问"),
(1, "粉丝访问"),
(2, "开放访问"),
)
CHECK_STATUS = (
(-1, "审核不通过"),
(0, "审核中"),
(1, "审核通过"),
)
id = models.AutoField(primary_key=True, verbose_name="唯一主键")
uid = models.ForeignKey(Account, on_delete=models.DO_NOTHING, verbose_name="用户", db_column='uid',
related_name='for_article_uid')
title = models.CharField(max_length=128, default='', verbose_name='文章标题', db_column='title')
content = models.TextField(verbose_name='文章内容', db_column='content')
comment_status = models.IntegerField(verbose_name='评论区状态', choices=COMMENT_STATUS, default=1,
db_column='comment_status')
is_public = models.IntegerField(verbose_name="公开状态", choices=COMMENT_STATUS, default=2, db_column='is_public')
is_check = models.IntegerField(verbose_name="审核状态", choices=CHECK_STATUS, default=0, db_column='is_check')
class Meta:
db_table = 'article_db'
verbose_name = verbose_name_plural = '文章'
def __str__(self):
return self.title
views.py
class ArticleView(APIView):
"""文章视图"""
filter_class = ArticleFilter # 指定你的过滤器
filter_backends = [DjangoFilterBackend, OrderingFilter, ]
ordering = ('-add_date', '-title', ) # 排序 优先级 左->右依次减小
def filter_queryset(self, queryset):
"""过滤"""
for backend in list(self.filter_backends):
# 这里的backend().filter_queryset会自动调用内部方法
# 一步步追踪下去,会发现它反射了filter_class方法 注意,其中取值的办法为.qs
queryset = backend().filter_queryset(self.request, queryset, self)
return queryset
@cache_page_middleware() # 自定义的缓存页面的组件 可去掉
def get(self, request, pk=None):
"""展示所有文章"""
if pk:
queryset = get_instance_or_not_found(Article, pk, '没有对应的文章') # 自定义的根据id值获取对象的函数,它会返回一个查询对象或者raise一个错误的response
serializer = ArticleSerializer(queryset)
return SuccessResponse({"data": serializer.data}) # 自定义的成功响应体
else:
queryset = Article.objects.select_related('uid').all() # 查询所有文章 并且关联查询外键
queryset = self.filter_queryset(queryset=queryset) # 调用过滤类
page_info = build_cursor_pagination_response(self, queryset, ArticleSimpleSerializer, request) # 自定义的分页函数 (基于游标分类) 返回一个字典
return SuccessResponse(page_info)
@login_and_auth_middleware
def post(self, request):
"""新增文章"""
reshape_data = copy(request.data) # 在执行函数期间 request是不允许修改的,想要修改 请先copy
reshape_data.update({"mini_uid": request.META['mini_uid'].id}) # 新增一个参数
serializer = ArticleSerializer(data=reshape_data)
serializer.is_valid(raise_exception=True)
serializer.save()
return SuccessResponse({"msg": "创建成功"})
urls.py
from django.contrib import admin
from django.urls import path, re_path
from api.article import views
urlpatterns = [
# 后面的http_method_names限定接口的请求方式 默认是反射你重写的所有方法
path('articles/', views.ArticleView.as_view(http_method_names=['get', 'post'])),
re_path(r'articles/(?P<pk>\d+)/', views.ArticleView.as_view(http_method_names=['get', ])),
]
settings.py
REST_FRAMEWORK = {
# 过滤
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',),
}
filters.py
from api.article.models import Article
from django_filters import rest_framework as filters
class ArticleFilter(filters.FilterSet):
# method后跟的函数表示自定义筛选
title = filters.CharFilter(method='title_filter', label="title")
content = filters.CharFilter(method='content_filter', label="content")
def title_filter(self, queryset, name, value):
return queryset.filter(title__icontains=value)
def content_filter(self, queryset, name, value):
return queryset.filter(text__icontains=value)
class Meta:
model = Article
fields = ("title", "content", ) # 可选字段
更多filter内部的用法
class ArticleFilter(filters.FilterSet):
"""
参数说明
field_name: 过滤字段名,一般应该对应模型中字段名
lookup_expr: 查询时所要进行的操作,和ORM中运算符一致
"""
title = filters.CharFilter(field_name='title',lookup_expr='icontains') # 含有关系
pub_time_year = filters.CharFilter(field_name='pub_time',lookup_expr='year') # 年份等于
pub_time_year__gt = filters.CharFilter(field_name='pub_time',lookup_expr='year__gt') # 年份大于
view__gt = filters.NumberFilter(field_name='view_no',lookup_expr="gt") # 查看数量大于
view__lt = filters.NumberFilter(field_name='view_no',lookup_expr="lt") # 查看数量小于
class Meta:
model = Article
fields = ['title','content','pub_time'] # 这些都限制于数据库的字段
# 持续更新...
版权声明:本文为weixin_45111060原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。