项目源码下载:https://github.com/Cherish-sun/NEWS/tree/master
实现新闻标签、广告的web API
一、serializers.py 添加
# 按serializers来序列化新闻标签
class TagSerializer(serializers.ModelSerializer):
# id = serializers.Field()
name = serializers.CharField(required=True, max_length=100)
slug = serializers.CharField(required=True, max_length=100)
class Meta:
model = Tag
fields = ('id', 'name', 'slug')
# 广告
class AdSerializer(serializers.ModelSerializer):
class Meta:
model = Ad
fields = "__all__"
二、views.py中设置新闻标签、广告的Viewset
class TagViewset(viewsets.ModelViewSet):
"""
list:
GET url: /tag/ 标签列表数据
create:
POST url: /tag/ 创建标签详情,返回新生成的标签对像
retrieve:
GET url: /tag/1/ 获取标签详情,返回标签对像
update:
PUT url: /tag/1/ 修改标签详情,返回标签对像
delete:
DELETE url: /tag/1/ 删除标签详情,返回空对像
"""
# 用于从此视图返回对象的查询器集。
queryset = Tag.objects.all()
# filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
# 查询
# filter_class =
# SearchFilter对应search_fields,对应模糊查询,也可用关连表的字段进行查询,但需要二个下划线连接,如categorys__title
search_fields = ('name')
# 用于验证和反序列化输入以及序列化输出的serializer类。通常,您必须设置此属性,或覆盖该 get_serializer_class()方法。
serializer_class = TagSerializer
# 应用于执行单个模型实例的对象查找的模型字段。默认为’pk’。
lookup_field = "id"
class AdViewset(viewsets.ModelViewSet):
"""
list:
GET url: /ad/ 广告列表数据
create:
POST url: /ad/ 创建广告详情,返回新生成的广告对像
retrieve:
GET url: /ad/1/ 获取广告详情,返回广告对像
update:
PUT url: /ad/1/ 修改广告详情,返回广告对像
delete:
DELETE url: /ad/1/ 删除广告详情,返回空对像
"""
# 用于从此视图返回对象的查询器集。
queryset = Ad.objects.all()
# filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
# 查询
# filter_class =
# SearchFilter对应search_fields,对应模糊查询,也可用关连表的字段进行查询,但需要二个下划线连接,如categorys__title
search_fields = ('title')
# 用于验证和反序列化输入以及序列化输出的serializer类。通常,您必须设置此属性,或覆盖该get_serializer_class()方法。
serializer_class = AdSerializer
# 应用于执行单个模型实例的对象查找的模型字段。默认为’pk’。
lookup_field = "id"
三、将两个类注册到urls.py里
router.register(r'tag', view.TagViewset, base_name='tag')
router.register(r'ad', view.AdViewset, base_name='ad')
四、实现文章的web API
1、serializers.py 添加
# 新闻文章
class ArticleSerializer(serializers.ModelSerializer):
# 外键相关对象
item = ItemSerializer()
author = UserSerializer()
tags = TagSerializer(many=True)
class Meta:
model = Article
fields = "__all__"
# 热门文章
class Hot_articleSerializer(serializers.ModelSerializer):
item = ItemSerializer()
author = UserSerializer()
tags = TagSerializer(many=True)
class Meta:
model = Article
fields = "__all__"
2、在article目录下新建myfilter.py
# -*- coding: utf-8 -*-
import django_filters
from django.db.models import Q
from .models import Article, Item
class ArticleFilter(django_filters.rest_framework.FilterSet):
"""
文章的过滤类
"""
author = django_filters.CharFilter(name='author', help_text="作者")
status = django_filters.ChoiceFilter(name='status', help_text="状态")
publish_date = django_filters.DateTimeFilter(name='publish_date', help_text="发布时间")
item = django_filters.CharFilter(name='item', help_text="分类")
tags = django_filters.CharFilter(name='tags', help_text="标签")
# 其中method指向自己定义的过滤函数,label用于标识在测试API界面中的过滤界面字段,categorys控制查询字段
categorys = django_filters.NumberFilter(method='item_categorys_filter', help_text="大类")
# top_category = django_filters.NumberFilter(method='item_categorys_filter')
def item_categorys_filter(self, queryset, name, value):
return queryset.filter(item__categorys=value)
class Meta:
model = Article
fields = ['author', 'status', 'publish_date', 'is_active', 'item', 'categorys', 'tags']
3、views.py 添加
from rest_framework.pagination import PageNumberPagination
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import filters
from .myfilter import ArticleFilter
from rest_framework.response import Response
class ArticlePagination(PageNumberPagination):
page_size = 5
page_size_query_param = 'page_size'
page_query_param = "page"
max_page_size = 20
class ArticleListViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
"""
文章列表页, 分页, 搜索, 过滤, 排序
可根据'author', 'status', 'publish_date', 'is_active', 'item', 'tags' 查询
"""
# throttle_classes = (UserRateThrottle, )
# 查询对象集
queryset = Article.objects.all()
# 序列化的类名
serializer_class = ArticleSerializer
# 分页,有分页列表结果时应使用的分页类。
pagination_class = ArticlePagination
# authentication_classes = (TokenAuthentication, )
# 过滤、查询类
filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
# DjangoFilterBackend对应filter_fields属性,做相等查询
# 过滤字段类
filter_class = ArticleFilter
# SearchFilter对应search_fields,对应模糊查询
search_fields = ('title', 'item__title', 'tags__name')
# 排序
ordering_fields = ('id', 'publish_date')
lookup_field = "id"
# 重写retrieve方法,取出数据后,将浏览数加一,重新取回数据
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
instance.read_num += 1
instance.save()
serializer = self.get_serializer(instance)
return Response(serializer.data)
class Hot_articleListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
"""
热门文章
"""
# throttle_classes = (UserRateThrottle, )
# 查询对象集
queryset = Article.objects.filter(is_active='True')[:10]
# 序列化的类名
serializer_class = ArticleSerializer
# 排序
ordering_fields = ('-id',)
lookup_field = "id"
五、实现用户相关的web API(实现注册、登录、重置密码功能)
1、views.py添加
from rest_framework.authtoken.models import Token
from rest_framework.authentication import TokenAuthentication, SessionAuthentication
from rest_framework import permissions
from rest_framework.status import HTTP_200_OK, HTTP_400_BAD_REQUEST, HTTP_201_CREATED
from rest_framework.decorators import action
from rest_framework.views import APIView
class UserViewset(viewsets.ModelViewSet):
"""
用户查询和注册
list:
GET url: /user/ 用户列表数据
creat:
POST url: /user/ 创建用户详情
retrieve:
GET url: /user/1/ 获取用户详情
update:
PUT url: /user/1/ 修改用户详情
delete:
DELETE url: /user/1/ 删除用户详情
"""
# queryset = User.objects.all()
# serializer_class = UserDetailSerializer
def get_serializer_class(self):
if self.action == "retrieve":
return UserDetailSerializer
elif self.action == "create":
return UserRegSerializer
return UserDetailSerializer
# 认证策略属性
authentication_classes = (TokenAuthentication, SessionAuthentication)
def get_queryset(self):
users = User.objects.filter(id=self.request.user.id)
if users:
for user in users:
issuperuser = user.is_superuser
if issuperuser:
queryset = User.objects.all()
else:
queryset = users
else:
queryset = users
return queryset
permission_classes = (permissions.IsAuthenticated,)
def get_permissions(self):
if self.action == "retrieve":
return [permissions.IsAuthenticated()]
elif self.action == "create":
return []
return []
# 重写create方法,给密码加密,并查询和创建token
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
passwd = request.data['password']
user = self.perform_create(serializer)
# 给密码加密
user.set_password(passwd)
user.save()
re_dict = serializer.data
# 查询和创建token
token = Token.objects.get_or_create(user=user)
serializer = UserRegSerializer({'id': user.id, 'username': user.username, 'token': token[0]})
serializer.data["status"] = HTTP_201_CREATED
# headers = self.get_success_headers(serializer.data)
return Response(serializer.data)
def perform_create(self, serializer):
return serializer.save()
class UserLoginViewset(mixins.CreateModelMixin, viewsets.GenericViewSet):
"""
实现用户登录
返回用户名、ID、token
"""
serializer_class = UserLoginSerializer
# 因登录只需post方法,可重写create方法,取消原有保存对象逻辑,加入登录逻辑
def create(self, request, *args, **kwargs):
serializer = self.serializer_class(data=request.data,
context={'request': request})
if serializer.is_valid(raise_exception=True):
user = serializer.validated_data['user']
# 登录时,创建新的token
tokenobj = Token.objects.update_or_create(user=user)
token = Token.objects.get(user=user)
# 重构返回数据
serializer = UserLoginSerializer(
{'username': user.username, 'id': user.id, 'password': '', 'token': token.key})
return Response(serializer.data, status=HTTP_200_OK)
return Response(serializer.errors, status=HTTP_400_BAD_REQUEST)
def get_object(self):
return self.request.user
class UserSetPasswordViewset(mixins.CreateModelMixin, viewsets.GenericViewSet):
"""
实现用户修改密码
输入username、password,验证正确返回password 修改成功,否则返回HTTP_400_BAD_REQUEST
"""
serializer_class = UserSetPasswordSerializer
# 设置对象集
queryset = User.objects.all()
# 因修改密码只需post方法,可重写create方法,取消原有保存对象逻辑,加入修改密码逻辑
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
if serializer.is_valid(raise_exception=True):
# 取出已验证的用户对象
instance = serializer.validated_data['user']
# 设置加密密码
instance.set_password(request.data['newpassword'])
# 保存
instance.save()
return Response({'status': 'password 修改成功'})
else:
return Response(serializer.errors,
status=HTTP_400_BAD_REQUEST)
六、实现用户收藏的web API
class UserFavViewset(mixins.CreateModelMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin,
mixins.DestroyModelMixin, viewsets.GenericViewSet):
"""
list:
获取用户收藏列表
retrieve:
判断某文章是否已经收藏
create:
收藏文章
"""
# permission_classes = (permissions.IsAuthenticated, )
# 加入认证
authentication_classes = (TokenAuthentication, SessionAuthentication)
lookup_field = "articles_id"
serializer_class = UserFavSerializer
# 重写get_queryset
def get_queryset(self):
if self.request.user:
queryset = UserFav.objects.filter(user=self.request.user)
else:
queryset = []
return queryset
# 重写create
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
articleid = request.data['articles']
userid = request.data['user']
userfav = UserFav.objects.get_or_create(articles_id=articleid, user_id=userid)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=HTTP_201_CREATED, headers=headers)
到此为止,新闻管理系统后端全部代码就写完了。。。。。运行newsapi项目,打开浏览器 http://0.0.0.0:8005/