Project source download: https://github.com/Cherish-sun/NEWS/tree/master
Implementation of web API for News Tags and advertisements
1. serializers.py additions
# serializers to serialize News Tags 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') # Advertisement class AdSerializer(serializers.ModelSerializer): class Meta: model = Ad fields = "__all__"
2. Viewset for news labels and advertisements in views.py
class TagViewset(viewsets.ModelViewSet): """ list: GET url: /tag/ Tag list data create: POST url: /tag/ Create tag details and return the newly generated tag objects retrieve: GET url: /tag/1/ Get label details and return label objects update: PUT url: /tag/1/ Modify label details and return label alignment delete: DELETE url: /tag/1/ Delete label details and return empty objects """ # Querier set for returning objects from this view. queryset = Tag.objects.all() # filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter) # query # filter_class = # SearchFilter corresponds to search_fields, fuzzy queries, and fields of related tables, but requires two underscored connections, such as categorys__title. search_fields = ('name') # Serializer classes for validating and deserializing inputs and serialized outputs. Typically, you must set this property or override the get_serializer_class() method. serializer_class = TagSerializer # Model fields applied to object lookups that perform a single model instance. The default is'pk'. lookup_field = "id" class AdViewset(viewsets.ModelViewSet): """ list: GET url: /ad/ Advertising List Data create: POST url: /ad/ Create advertising details and return to newly generated advertising counterparts retrieve: GET url: /ad/1/ Get the details of the advertisement and return to the target of the advertisement update: PUT url: /ad/1/ Modify the details of the advertisement and return to the target of the advertisement delete: DELETE url: /ad/1/ Delete the details of the advertisement and return to the empty object """ # Querier set for returning objects from this view. queryset = Ad.objects.all() # filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter) # query # filter_class = # SearchFilter corresponds to search_fields, fuzzy queries, and fields of related tables, but requires two underscored connections, such as categorys__title. search_fields = ('title') # Serializer classes for validating and deserializing inputs and serialized outputs. Typically, you must set this property or override the get_serializer_class() method. serializer_class = AdSerializer # Model fields applied to object lookups that perform a single model instance. The default is'pk'. lookup_field = "id"
3. Register two classes in urls.py
router.register(r'tag', view.TagViewset, base_name='tag') router.register(r'ad', view.AdViewset, base_name='ad')
4. Implementing the web API of the article
1. serializers.py additions
# News articles class ArticleSerializer(serializers.ModelSerializer): # Foreign key related objects item = ItemSerializer() author = UserSerializer() tags = TagSerializer(many=True) class Meta: model = Article fields = "__all__" # Hot articles class Hot_articleSerializer(serializers.ModelSerializer): item = ItemSerializer() author = UserSerializer() tags = TagSerializer(many=True) class Meta: model = Article fields = "__all__"
2. Create a new myfilter.py in the article directory
# -*- coding: utf-8 -*- import django_filters from django.db.models import Q from .models import Article, Item class ArticleFilter(django_filters.rest_framework.FilterSet): """ //The filtering class of articles """ author = django_filters.CharFilter(name='author', help_text="author") status = django_filters.ChoiceFilter(name='status', help_text="state") publish_date = django_filters.DateTimeFilter(name='publish_date', help_text="Release time") item = django_filters.CharFilter(name='item', help_text="classification") tags = django_filters.CharFilter(name='tags', help_text="Label") # The method points to the filter function defined by itself, the label is used to identify the filter interface field in the test API interface, and the categories control the query field. categorys = django_filters.NumberFilter(method='item_categorys_filter', help_text="Large class") # 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. View.py additions
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): """ //List Pages, Pagination, Search, Filtering, Sorting of Articles //Queries can be made according to'author','status','publish_date','is_active','item','tags'. """ # throttle_classes = (UserRateThrottle, ) # Query Object Set queryset = Article.objects.all() # Serialized class names serializer_class = ArticleSerializer # Paging, the type of paging that should be used when the results of the paging list are available. pagination_class = ArticlePagination # authentication_classes = (TokenAuthentication, ) # Filtering and query classes filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter) # DjangoFilterBackend corresponds to the filter_fields attribute, making an equal query # Filter field class filter_class = ArticleFilter # SearchFilter corresponds to search_fields and fuzzy queries search_fields = ('title', 'item__title', 'tags__name') # sort ordering_fields = ('id', 'publish_date') lookup_field = "id" # Rewrite the retrieve method. After retrieving the data, add the number of browses to one and retrieve the data. 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): """ //Hot articles """ # throttle_classes = (UserRateThrottle, ) # Query Object Set queryset = Article.objects.filter(is_active='True')[:10] # Serialized class names serializer_class = ArticleSerializer # sort ordering_fields = ('-id',) lookup_field = "id"
5. Implementing user-related web API (registration, login, password reset)
1. View.py additions
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): """ //User Inquiry and Registration list: GET url: /user/ User List Data creat: POST url: /user/ Create user details retrieve: GET url: /user/1/ Getting User Details update: PUT url: /user/1/ Modify user details delete: DELETE url: /user/1/ Delete user details """ # 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 policy attributes 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 [] # Rewrite the create method, encrypt the password, and query and 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) # Encryption of passwords user.set_password(passwd) user.save() re_dict = serializer.data # Query and create 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): """ //Implementing user login //Return username, ID, token """ serializer_class = UserLoginSerializer # Because only post method is needed for login, the create method can be rewritten, the original saving object logic can be cancelled, and login logic can be added. 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'] # When logged in, create a new token tokenobj = Token.objects.update_or_create(user=user) token = Token.objects.get(user=user) # Reconstructing returned data 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): """ //Implementing User Modification of Password //Enter username and password to verify that the password is correctly returned, or HTTP_400_BAD_REQUEST is returned. """ serializer_class = UserSetPasswordSerializer # Setting Object Set queryset = User.objects.all() # Because only post method is needed to modify the password, the create method can be rewritten, the original saving object logic can be cancelled, and the modified password logic can be added. def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) if serializer.is_valid(raise_exception=True): # Remove authenticated user objects instance = serializer.validated_data['user'] # Setting Encrypted Password instance.set_password(request.data['newpassword']) # Preservation instance.save() return Response({'status': 'password Modified success'}) else: return Response(serializer.errors, status=HTTP_400_BAD_REQUEST)
6. Implementing web API for User Collection
class UserFavViewset(mixins.CreateModelMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.DestroyModelMixin, viewsets.GenericViewSet): """ list: //Get a list of user favorites retrieve: //Judging whether an article has been collected create: //Collection articles """ # permission_classes = (permissions.IsAuthenticated, ) # Join certification authentication_classes = (TokenAuthentication, SessionAuthentication) lookup_field = "articles_id" serializer_class = UserFavSerializer # Rewrite get_queryset def get_queryset(self): if self.request.user: queryset = UserFav.objects.filter(user=self.request.user) else: queryset = [] return queryset # Rewrite 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)
So far, the whole code of the back end of the news management system has been written... Run the newsapi project and open the browser http://0.0.0.0:8005/