如何在django rest framework中实现文章的上次访问功能

jyztefdp  于 2022-11-18  发布在  Go
关注(0)|答案(1)|浏览(128)

我有一个Article模型,用户可以在其中发布文章、添加评论等。我想添加一个过滤器,它可以根据访问过最后一个Article的用户对最后一个Article发表评论的用户来过滤Articles
请指导我如何在 Django/DRF 中实现这个功能。
这是我的模特:

class Article(models.Model):
    id=models.AutoField(primary_key=True, auto_created=True, verbose_name="ARTICLE_ID")
    headline=models.CharField(max_length=250)
    abstract=models.TextField(max_length=1500, blank=True)
    content=models.TextField(max_length=10000, blank=True)
    files=models.ManyToManyField('DocumentModel', related_name='file_documents',related_query_name='select_files', blank=True)
    published=models.DateField(auto_now_add=True, null=True)
    tags=models.ManyToManyField('Tags', related_name='tags', blank=True)
    isDraft=models.BooleanField(blank=True, default=False)
    isFavourite=models.ManyToManyField(User, related_name="favourite", blank=True)
    created_by=models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, related_name="articles")
    
   
    def get_id(self):
        return self.headline + ' belongs to ' + 'id ' + str(self.id)

    
    class Meta:
        verbose_name_plural= "Articles"
        ordering=("id", "headline", "abstract", "content",  "published", "isDraft", "created_by")

    def __str__(self):
        return f'{self.headline}'

已编辑

这是我实现的以下内容

文章.py

class Article(models.Model):
    id=models.AutoField(primary_key=True, auto_created=True, verbose_name="ARTICLE_ID")
    headline=models.CharField(max_length=250)
    abstract=models.TextField(max_length=1500, blank=True)
    content=models.TextField(max_length=10000, blank=True)
    files=models.ManyToManyField('DocumentModel', related_name='file_documents',related_query_name='select_files', blank=True)
    published=models.DateField(auto_now_add=True, null=True)
    tags=models.ManyToManyField('Tags', related_name='tags', blank=True)
    isDraft=models.BooleanField(blank=True, default=False)
    isFavourite=models.ManyToManyField(User, related_name="favourite", blank=True)
    created_by=models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, related_name="articles")
    
    
   
    def get_id(self):
        return self.headline + ' belongs to ' + 'id ' + str(self.id)

    def seen_by_user(self, user):
        return self.articleseenrecord_set.objects.filter(user=user).exists()

    @register.simple_tag
    def article_seen_by_user(article, user):
        return article.seen_by_user(user)
    

    
    class Meta:
        verbose_name_plural= "Articles"
        ordering=("id", "headline", "abstract", "content",  "published", "isDraft", "created_by")

    def __str__(self):
        return f'{self.headline}'

这是我创建的ArticleSeenRecord

class ArticleSeenRecord(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    article = models.ForeignKey(Article, on_delete=models.CASCADE)

下面是我尝试序列化的方法:

序列化程序.py

class ArticleSerializer(serializers.ModelSerializer): 

   #serializer for getting username of User
    created_by=serializers.CharField(source='created_by.username', read_only=True)
    files=DocumentSerializer(many=True, read_only=True)
    isFavourite=serializers.PrimaryKeyRelatedField(many=True, read_only=True)
    tags=serializers.SlugRelatedField(many=True, queryset=Tags.objects.all(), slug_field="tag")
    seen_by_user=serializers.CharField(read_only=True)
    
    class Meta:
        model= Article
        fields = ["id", "headline", "abstract", "seen_by_user", "content",   "published",  "isDraft", "isFavourite", "tags", 'files', 'created_by' ]

检查后,我得到以下错误响应:

{
            "id": 1,
            "headline": "Article 1",
            "abstract": "Abstract 1",
            "seen_by_user": "<bound method Article.seen_by_user of <Article: Article 1>>",
            "content": "content 1",
            "published": "2022-10-20",
            "isDraft": true,
            "isFavourite": [
                1
            ],
            "tags": [
                "Python",
                "C++"
            ],
            "files": [
                {
                    "id": 1,
                    "document": "http://127.0.0.1:8000/uploaded_files/6Dp4gG4pi8Wm4ficssTD6o.pdf",
                    "filesize": "122 KB",
                    "filename": "resume.pdf",
                    "mimetype": "application/pdf",
                    "created_at": "2022-10-20"
                }
            ],
            "created_by": "abdullahroshan"
        },

我得到"seen_by_user": "<bound method Article.seen_by_user of <Article: Article 1>>"错误响应。
此外,我不知道如何使用这个模板标记,并检查用户是否查看了一篇文章。
这是Articles视图集:

class ArticleViewSet(viewsets.ModelViewSet):


    serializer_class=ArticleSerializer
    permission_classes=[permissions.IsAuthenticated]
    authentication_classes = [authentication.TokenAuthentication]

    pagination_class=StandardResultSetPagination
    filter_backends= (DjangoFilterBackend, filters.OrderingFilter, filters.SearchFilter)
    filterset_fields= ['headline', 'isDraft']
    search_fields=['headline']
    ordering_fields = ['id']

 def get_object(self, queryset=None):
        obj=super().get_object(queryset)
        record, created = ArticleSeenRecord.objects.get_or_create(user=self.request.user, article=obj)
        return obj

已更新

嗨,谢谢你的更新,我已经实现了每一个步骤,目前有一个错误是弹出
实现这样的序列化程序后

一个月七个月一个月

class ArticleSerializer(serializers.ModelSerializer):

   #serializer for getting username of User
    created_by=serializers.CharField(source='created_by.username', read_only=True)
    files=DocumentSerializer(many=True, read_only=True)
    isFavourite=serializers.PrimaryKeyRelatedField(many=True, read_only=True)
    tags=serializers.SlugRelatedField(many=True, queryset=Tags.objects.all(), slug_field="tag")
    seen_by_user=serializers.SerializerMethodField()

    class Meta:
        model= Article
        fields = ["id", "headline", "seen_by_user", "abstract", "content",  "published",  "isDraft", "isFavourite", "tags", 'files',  'created_by'  ]  
        
       
    def get_seen_by_user(self, instance):
        return instance.seen_by_user(article, self.context['request'].user)

而在这样的视图addling:

class ArticleViewSet(viewsets.ModelViewSet):

    serializer_class=ArticleSerializer
    permission_classes=[permissions.IsAuthenticated]
    authentication_classes = [authentication.TokenAuthentication]

    pagination_class=StandardResultSetPagination
    filter_backends= (DjangoFilterBackend, filters.OrderingFilter, filters.SearchFilter)
    filterset_fields= ['headline', 'isDraft']
    search_fields=['headline']
    ordering_fields = ['id']

def get_object(self, queryset=None):
        obj = super().get_object(queryset)
        record, created=ArticleSeenRecord.objects.get_or_create(user=self.request.user, article=obj)
        return obj    
   
    def get_serializer_context(self):
        context = super().get_serializer_context()
        context.update({"request": self.request})
        return context

我得到以下错误:

return instance.seen_by_user(article, self.context['request'].user)
NameError: name 'article' is not defined

这里的文章没有定义。

332nm8kg

332nm8kg1#

请看我对上一个问题的回答,这几乎是相同的。
您可以创建一个额外的表。

class ArticleSeenRecord(models.Model):
    user = models.ForeignKey("django.contrib.auth.models.User", on_delete=models.CASCADE)
    article = models.ForeignKey(Article, on_delete=models.CASCADE)

然后,在文章视图中,为与已验证用户相结合的文章创建一个新记录(如果不存在)。

class ArticleDetail(LoginRequiredMixin, DetailView):
    model = Article
    context_object_name = 'articles'
    template_name = 'home/article_detail.html'

    def get_object(self, queryset=None):
        obj =  super().get_object(queryset)
        record, created =  ArticleSeenRecord.objects.get_or_create(user=self.request.user, article=obj)
        return obj
   

class Article(models.Model):
    ...
    def seen_by_user(self, user):
         return self.atricleseenrecord_set.objects.filter(user=user).exists()

我在这里添加了额外的函数。

@register.simple_tag
def article_seen_by_user(article, user):
    return article.seen_by_user(user)

有关如何使用和注册自定义模板标记的进一步指导,请参阅文档的以下页面:
https://docs.djangoproject.com/en/4.0/howto/custom-template-tags/
特别是本节:
https://docs.djangoproject.com/en/4.0/howto/custom-template-tags/#django.template.Library.simple_tag

编辑感谢您的回答并更新了您的答案,我理解您的观点,并将根据扩展的问题进行回答。

您的实现非常完美,唯一的区别在于您的串行器-您应该将seen_by_user字段从CharField更改为:

seen_by_user = serialisers.SerializerMethodField()

这样就可以解决seen_by_user字段不能正确序列化的问题,然后你可以在序列化器上定义一个函数,例如:

def get_seen_by_user(self, instance):
    return instance.seen_by_user(article, self.context['request'].user)

最后,您可以将请求添加到序列化程序上下文中,如下所示:

class MyModelViewSet(ModelViewSet):
    queryset = MyModel.objects.all()
    permission_classes = [DjangoModelPermissions]
    serializer_class = MyModelSerializer

    def get_serializer_context(self):
        context = super().get_serializer_context()
        context.update({"request": self.request})
        return context

相关问题