Django front-end and back-end separate development-news management system

Keywords: github Django Attribute

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/

Posted by KrisNz on Fri, 04 Oct 2019 09:42:19 -0700