python-3.x - Django Queryset 而不是 view.py 中的 for 循环和 if 语句
问题描述
我有以下型号:
class Post(models.Model):
description = models.TextField()
post_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
created_on = models.DateField(auto_now_add=True, verbose_name=_("created on"))
liked_users = models.ManyToManyField(User, blank=True, related_name='liked_post')
disliked_users = models.ManyToManyField(User, blank=True, related_name='disliked_post')
`def get_tag_weight(self):
tag_set = Tag.objects.filter(post=self)
tag_weight = 0
for tag in tag_set:
tag_weight += tag.weight
return tag_weight`
class Image(models.Model):
post = models.ForeignKey(Post, null=True, default=None, on_delete=models.CASCADE, related_name='parent_post')
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
images = models.ImageField(upload_to = 'images/')
class Tag(models.Model):
name = models.CharField(max_length=100)
weight = models.IntegerField(default=0)
post = models.ForeignKey(Post, null=True, default=None, on_delete=models.CASCADE,related_name='post')
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
并在帐户中
class User(AbstractUser):
user_id = models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
liked_posts = models.ManyToManyField('post.Post', blank=True, related_name='user_liked')
disliked_posts = models.ManyToManyField('post.Post', blank=True, related_name='user_disliked')
liked_tags = models.ManyToManyField('post.Tag' , blank=True, related_name='user_liked')
disliked_tags = models.ManyToManyField('post.Tag', blank=True, related_name='user_disliked')
这是我在views.py 中的get_queryset 方法
class PostListView(generics.ListCreateAPIView):
serializer_class = GetUserIDSerializer
serializer_class_post = PostSerializer
permission_classes = [IsAuthenticated]
queryset = ''
context_object_name = "post_list"
def get_queryset_Post(self, user):
liked_tags = user.liked_tags.all()
disliked_tags = user.disliked_tags.all()
posts = Post.objects.all()
sorted_posts = []
liked_posts = []
disliked_posts = []
normal_posts = []
for post in posts:
is_break = False
is_added = False
post_tags = Tag.objects.filter(post=post)
for tag in post_tags:
if is_break:
break
for liked_tag in liked_tags:
if tag.name == liked_tag.name:
liked_posts.append(post)
is_break = True
is_added = True
break
else:
for disliked_tag in disliked_tags:
if tag.name == disliked_tag.name:
disliked_posts.append(post)
is_added = True
is_break = True
break
if is_added == False:
normal_posts.append(post)
continue
for i in range(len(liked_posts)):
for j in range(i + 1, len(liked_posts)):
if liked_posts[i].get_tag_weight() < liked_posts[j].get_tag_weight():
liked_posts[i], liked_posts[j] = liked_posts[j], liked_posts[i]
for i in range(len(disliked_posts)):
for j in range(i + 1, len(disliked_posts)):
if disliked_posts[i].get_tag_weight() > disliked_posts[j].get_tag_weight():
disliked_posts[i], disliked_posts[j] = disliked_posts[j], disliked_posts[i]
sorted_posts = liked_posts + normal_posts + disliked_posts
return sorted_posts
我想从视图中删除循环(所有 for 循环和 if 语句)并希望 queryset 进行计算。我想编写查询来过滤标签类似于用户喜欢的标签的帖子。我知道这很长。看看有没有人可以帮忙谢谢
解决方案
首先,您ForeignKey
从标签到帖子的方法是有问题的。据我了解,帖子可以有类似的标签。AManyToManyField
更适合这种情况:
class Tag(models.Model):
# Other fields
post = models.ManyToManyField(Post, related_name='tags')
# Other fields
现在转到视图,我们将使用标签过滤并按最大重量排序:
from django.db.models import Max
liked_posts = Post.objects.filter(tags__in=user.liked_tags.all()).annotate(max_weight=Max('tags__weight')).order_by('-max_weight')
normal_posts = Post.objects.exclude(tags__in=user.liked_tags.all()).exclude(tags__in=user.disliked_tags.all()).annotate(max_weight=Max('tags__weight')) # Might just need to annotate for union to work.
disliked_posts = Post.objects.filter(tags__in=user.disliked_tags.all()).annotate(max_weight=Max('tags__weight')).order_by('max_weight')
sorted_posts = liked_posts | normal_posts | disliked_posts
推荐阅读
- matlab - 从纬度和经度点创建位置网格
- c# - ListBox 项目在 OwnerDrawFixed 模式下不显示
- authentication - 使用 Google 作为身份提供者的 Salesforce 的 Api 身份验证
- tsql - 什么是运算符 | 在 sql 中以及它是如何工作的
- google-apps-script - 将 Google 表格中的数字转换为文本/单词
- rust - 当闭包包含复杂的生命周期关系时,无法为函数构建等效闭包
- node.js - 如何在 nw.js 中使用 npm 包而不安装 Node JS
- verilog - 为什么我不能将寄存器连接到 Verilog 中的输出?
- powershell - PowerShell完成命令时的事件?
- vb.net - VB.NET - 替换以空格分隔的文本文件中的列值