在Django中保存文章时如何使用序列化程序存储标签?

时间:2018-10-10 19:39:52

标签: django

我想实现标记功能,以便使用文章创建标记。我建立了两个模型,即Article和Tag。在Article模型上,我定义了一个引用该标签的标签字段(ManyToMany Field)。

我现在拥有的代码可以很好地创建带有标签的文章。我觉得可以改善。有人告诉我,我正在硬编码很多东西(重复自己)。例如,他指出我不应该定义用于创建标签的自定义方法。所以,现在我想也许有一种方法可以在post方法内调用TagSerializer,以将标签保存在文章中。我真的不确定如何解决这个问题。

是否可以通过更多利用内置的Django原理来改进标记代码? (特别是保存标签的部分)。

Models.py

from django.db import models
from django.utils import timezone
from authors.apps.authentication.models import User
from .utils import get_unique_slug



class Tag(models.Model):
    """ Model for Tag """

    tag = models.CharField(max_length=30, unique=True)
    slug = models.SlugField(max_length=100, unique=True)
    author = models.ForeignKey('authentication.User', on_delete=models.CASCADE)

    def __str__(self):
        return self.tag

class Article(models.Model):
    """
    Model for Article
    """

    author = models.ForeignKey(User, on_delete=models.CASCADE)

    title = models.CharField(max_length=255, null=False, blank=False)

    description = models.TextField(null=False, blank=False)

    body = models.TextField(null=False, blank=False,)

    tags = models.ManyToManyField(
        'Tag', related_name='articles')

    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = get_unique_slug(self, 'title', 'slug')
        return super().save(*args, **kwargs)

Serializers.py

from rest_framework import serializers
from authors.apps.articles.models import Article
from authors.apps.articles.models import Tag

class ArticleSerializer(serializers.ModelSerializer):
    """Serializer for articles."""
    author = serializers.ReadOnlyField(source='author.username')
    tag_list = serializers.StringRelatedField(many=True, required=False, source='tags')

    class Meta:
        model = Article

        fields = ('author','title','slug','description','body','created_at','updated_at','tag_list')

class TagSerializer(serializers.ModelSerializer):
    author = serializers.CharField(source='author.username')

    class Meta:
        model = Tag
        fields = '__all__'

Views.py

from rest_framework import generics
from rest_framework import status
from rest_framework.permissions import IsAuthenticated,IsAuthenticatedOrReadOnly,AllowAny
from rest_framework.response import Response
from authors.apps.articles.serializers import ArticleSerializer, TagSerializer
from .models import Article, Tag
from rest_framework import serializers


def create_tag(tags, article):
    """
    This method checks whether a tag with tag provided exists in the 
    database and creates it if it does not exist.

    """


    for tag in tags.split(','):
        article_tag = Tag.objects.filter(tag__icontains=tag.strip())
        if not article_tag:
            data = {'tag': tag.strip()}
            serializer = TagSerializer(data=data)
            serializer.is_valid(raise_exception=True)
            article_tag = serializer.save()
            article.article_tags.add(article_tag)
        else:
            article.article_tags.add(article_tag.first())
    article.save()
    return None

class ArticleAPIView(generics.ListCreateAPIView):
    """
    get:
    Retrieve all articles
    post:
    Create a new article
    """
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
    renderer_classes = (ArticleJSONRenderer,)
    permission_classes = (IsAuthenticatedOrReadOnly,)

    def post(self, request):
        """
        Creates an article

        """


        article = {
            'title': request.data.get('title', None),
            'body': request.data.get('body', None),
            'description': request.data.get('description', None),
            'author': request.user.id
        }
        # pass article data to the serializer class, check whether the data is
        # valid and if valid, save it.
        serializer = self.serializer_class(data=article)
        serializer.is_valid(raise_exception=True)
        article = serializer.save()
        # retrieve the tags as passed on in the article data
        tags = request.data.get('tags', None)
        if tags:
            create_tag(tags, article)
        return Response(serializer.data, status.HTTP_201_CREATED)

0 个答案:

没有答案