Django开发博客——生成RESTful接口

1.针对列表页和详情页接口定义不同的Serializer类,根据需求展示对应的字段
对应app下 serializers.py

from rest_framework import serializers, pagination
from .models import Post, Category

# 定义serializer序列化列表页的数据,类似于form表单,form表单继承自forms.ModelForm
class PostSerializer(serializers.ModelSerializer):
	# 类似form表单,对某些特殊的字段进行处理
    # 外键需要如下配置
    category = serializers.SlugRelatedField(
        read_only=True,
        slug_field='name',
    )
    tag = serializers.SlugRelatedField(
        many=True,            # 多对多
        read_only=True,       # 定义外键是否可写
        slug_field='name',    # 定义外键展示对应主表中的字段
    )
    owner = serializers.SlugRelatedField(read_only=True, slug_field='username',)
    # 设置日期时间的格式
    created_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
	
	# 类似form表单,定义关联的模型以及列表页展示的字段
    class Meta:
        model = Post
        # id用来获取详情页
        fields = ['id', 'title', 'category', 'tag', 'owner', 'created_time']


# 定义详情页接口需要的Serializer类
# 继承自列表页的序列化器,然后重新定义展示的字段即可
class PostDetailSerializer(PostSerializer):
    class Meta:
        model = Post
        fields = ['id', 'title', 'category', 'tag', 'owner', 'content_html', 'created_time']

class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = ('id', 'name', 'created_time')

# 获取某个分类下的文章列表,从资源的角度看,相当于分类的详情页数据
class CategoryDetailSerializer(CategorySerializer):
    # 将posts字段获取的内容映射到paginated_posts方法上
    # 即最终返回数据时,posts对应的数据从paginated_posts方法中获取
    posts = serializers.SerializerMethodField('paginated_posts')

    # http://127.0.0.1:8000/api/category/2/?page=3
    def paginated_posts(self, obj):
        posts = obj.post_set.filter(status=Post.STATUS_NORMAL)
        paginator = pagination.PageNumberPagination()
        page = paginator.paginate_queryset(posts, self.context['request'])
        serializer = PostSerializer(page, many=True, context={'request': self.context['request']})
        return {
            'count': posts.count(),
            'results': serializer.data,
            'previous': paginator.get_previous_link(),
            'next': paginator.get_next_link(),
        }

    class Meta:
        model = Category
        fields = ('id', 'name', 'created_time', 'posts')

2.重写详情页获取数据的接口,指定serializer_class;根据分类获取对应的文章列表
对应app下 apis.py

from rest_framework import viewsets
from .models import Post, Category
from .serializers import PostSerializer, PostDetailSerializer, CategorySerializer, CategoryDetailSerializer

# 定义视图层的逻辑
class PostViewSet(viewsets.ReadOnlyModelViewSet):
    """文档说明,这里的内容可以在接口文档中看到"""
    # 指定序列化的类和数据
    serializer_class = PostSerializer
    queryset = Post.objects.filter(status=Post.STATUS_NORMAL)

    # 重写获取详情页数据的接口
    def retrieve(self, request, *args, **kwargs):
        # 重新赋值给serializer_class,以区分列表页和详情页的Serializer
        self.serializer_class = PostDetailSerializer
        return super().retrieve(request, *args, **kwargs)

    # 获取某个分类下的文章列表
    # http://127.0.0.1:8000/api/post/?category=2
    def filter_queryset(self, queryset):
        # 获取URL中category参数,然后进行过滤
        category_id = self.request.query_params.get('category')
        if category_id:
            return queryset.filter(category_id=category_id)
        return queryset

class CategoryViewSet(viewsets.ReadOnlyModelViewSet):
    serializer_class = CategorySerializer
    queryset = Category.objects.filter(status=Category.STATUS_NORMAL)

    # 重写分类的详情页接口,展示分类下的所有文章列表
    def retrieve(self, request, *args, **kwargs):
        self.serializer_class = CategoryDetailSerializer
        return super().retrieve(request, *args, **kwargs)

3.实现分页,解决报错:‘AutoSchema’ object has no attribute ‘get_link’ settings.py

# 配置RESTful接口的分页
REST_FRAMEWORK = {
	# 解决报错问题:'AutoSchema' object has no attribute 'get_link'
    'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.AutoSchema',
    # 其他分页选项
    # rest_framework.pagination.PageNumberPagination:常用,当前是第几页,每页多少条数据
    # rest_framework.pagination.CursorPagination:不能自己输入分页参数,防止用户填写任意页码和数据量来获取数据
    # Cursor分页默认以created字段来排序,如果表中没有该字段,可通过继承CursorPagination自定义ordering属性为id或其他字段
    # 这个是基于偏移量和limit的分页,即当前是第几条,还要获取多少条
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 2,
}

4.关于获取某个分类下的文章列表:
1.在PostViewSet中通过获取URL上的查询参数,重写类似get_queryset的方法大来实现过滤(简单)
2.以资源的角度来看,获取分类下的文章列表,其实就相当于获取分类的详情页
5.url的配置

from rest_framework.routers import DefaultRouter
from finance.apis import FinanceViewSet
from rest_framework.documentation import include_docs_urls

# 创建router代理一整套的restful接口
router = DefaultRouter()
router.register(r'finance', FinanceViewSet, base_name='api-finance')

urlpatterns = [
    path('api/', include(router.urls)),
    path('api/docs/', include_docs_urls(title='finance_restful_doc')),

参考:《Django企业开发实战》

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值