我有一个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
这里的文章没有定义。
1条答案
按热度按时间332nm8kg1#
请看我对上一个问题的回答,这几乎是相同的。
您可以创建一个额外的表。
然后,在文章视图中,为与已验证用户相结合的文章创建一个新记录(如果不存在)。
我在这里添加了额外的函数。
有关如何使用和注册自定义模板标记的进一步指导,请参阅文档的以下页面:
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
字段不能正确序列化的问题,然后你可以在序列化器上定义一个函数,例如:最后,您可以将请求添加到序列化程序上下文中,如下所示: