我正在开发一个涉及频道/邮政机制的项目。我目前正在实施"删除"通过设置名为"删除"的字段来发布帖子到它被删除的时间戳。它需要保持历史意义(最后的活动)并跟踪煽动的人(服务是整个项目的特权部分)。
models.py
class Post(models.Model):
deleted = models.DateTimeField(null=True, blank=True)
created_date = models.DateTimeField(auto_now_add=True)
updated_date = models.DateTimeField(auto_now_add=True)
post_text = models.CharField(max_length=1000)
post_to = models.ForeignKey('Channel', related_name='post_to_channel')
post_from = models.ForeignKey(User, related_name='user_from_post')
class Channel(models.Model):
created_date = models.DateTimeField(auto_now_add=True)
channel_title = models.CharField(max_length=50, unique=True)
channel_description = models.CharField(max_length=100)
channel_creator = models.ForeignKey(User)
channel_private = models.BooleanField(default=False)
channel_users = models.ManyToManyField(User, through='Membership', related_name='channels', blank=True)
channel_posts = models.ManyToManyField(Post, related_name='channel_post', blank=True)
initial_invites = models.ForeignKey(User, null=True, blank=True, related_name='initial_invites')
objects = models.Manager()
class Membership(models.Model):
channel = models.ForeignKey(Channel)
channel_user = models.ForeignKey(User, related_name='channel_membership')
join_date = models.DateTimeField(auto_now_add=True)
我有一个更新"删除" " Post" object是null的时间戳。然后,如何在"频道"中查询时,如何避免返回所有具有时间戳的帖子?级别,通过他们的关系和单独的序列化程序加载帖子?基本上,我需要能够查询"频道"并获得我所参与的频道列表,然后通过他们与ManyToMany的关系" Post"加载所有相关帖子,不包括那些在"删除"领域。如果没有为每个频道调用ORM,然后过滤掉已删除的帖子,这是否可行?要清楚,"频道"如果有删除的帖子,只有" Post"本身应该被隐藏。
如果我没有提供足够的信息,请告诉我您需要查看的内容。
如果答案是在没有重复的ORM呼叫的情况下这是不可能的,建议其他选项将被赞赏,包括权衡选项" archive"将帖子发送到重复的模型,在这些情况下不要调用钩子并删除原始模型。
编辑1:
添加所选答案中所述的属性,但无法查看self.channel_posts
。
models.py
class Channel(models.Model):
created_date = models.DateTimeField(auto_now_add=True)
channel_title = models.CharField(max_length=50, unique=True)
channel_description = models.CharField(max_length=100)
channel_creator = models.ForeignKey(User)
channel_private = models.BooleanField(default=False)
channel_users = models.ManyToManyField(User, through='Membership', related_name='channels', blank=True)
channel_posts = models.ManyToManyField(Post, related_name='channel_post', blank=True)
initial_invites = models.ForeignKey(User, null=True, blank=True, related_name='initial_invites')
objects = models.Manager()
@property
def get_viewable_posts(self):
print (self.channel_users) # prints []
print (self.channel_posts) # prints []
return CourtyardPost.objects.filter(deleted__isnull=True, courtyard_post_to=self.pk) #works, but adds IO strain
目前,如上所示,它是每个频道的ORM呼叫,但在所有情况下,打印self.channel_posts
或self.channel_users
都会返回一个空列表。该属性被称为Django Rest Framework的序列化程序的一部分,如下所示:
class CourtyardChannelSerializer(serializers.ModelSerializer):
current_user = serializers.SerializerMethodField('_user')
post_to_channel = CourtyardPostSerializer(many=True, source='get_viewable_posts', read_only=True)
most_recent = CourtyardPostSerializer(many=True, source='latest_post', read_only=True)
channel_users = CourtyardUserSerializer(many=True, read_only=True)
)
invite_list = serializers.ReadOnlyField(source='get_invitation_set', required=False)
def _user(self, obj):
user = self.context['request'].user.username
return user
答案 0 :(得分:1)
class Channel(models.Model):
created_date = models.DateTimeField(auto_now_add=True)
channel_title = models.CharField(max_length=50, unique=True)
channel_description = models.CharField(max_length=100)
channel_creator = models.ForeignKey(User)
channel_private = models.BooleanField(default=False)
channel_users = models.ManyToManyField(User, through='Membership', related_name='channels', blank=True)
channel_posts = models.ManyToManyField(Post, related_name='channel_post', blank=True)
initial_invites = models.ForeignKey(User, null=True, blank=True, related_name='initial_invites')
objects = models.Manager()
@property
def active_posts(self):
return self.channel_posts.filter(deleted=None)
非常简单,只需添加一个额外的属性,现在就可以像这样使用它了
channel = Channel.objects.first()
print(channel.active_posts.count())
答案 1 :(得分:0)
我猜这一刻,你正在做类似的事情:
def channels_and_posts_for_user(user):
for channel in user.channel_membership:
posts = channel.channel_posts.all().filter(deleted__isnull=True)
channels_and_posts.append(channel, posts)
return channels_and_posts
并且您想在每次通话时摆脱过滤器?
这是一种痛苦,我同意,我一直试图做一些类似于存档的'我的webapp的一些模型中的变量。
我不相信可以解决这个问题。您可以像这样创建一个自定义管理器:
class ChannelManagerWithUndeleted(models.Manager):
def get_queryset(self):
return super(ChannelManagerWithUndeleted, self).get_queryset().filter(deleted__isnull=True)
class Channel(models.Model):
#...
objects = models.Manager() # Default Manager
undeleted = EntryManager() # Custom Manager
然后通过Channel.undeleted.all()
而不是Channel.objects.all
直接访问对象,但您仍然需要在related calls anyway上指定这个新的管理器,并且它最终会变得冗长(如果有的话)更多DRY):
channels_and_posts = []
for channel in user.channel_membership:
posts = channel.channel_posts.all(manager='undeleted').all()
channels_and_posts.append(channel, posts)
这也是一个相关的帖子:How to use custom manager with related objects?。
我觉得它很复杂,因为每个人都希望在不同情况下略有不同的行为。例如我想要归档的' Events'仍然能够运行报告,但不会显示给最终用户选择,所以我在面向消费者的地方使用自定义管理器。
如果你想要做的只是稍后计算报告,可能选择添加channel_deleted_posts
ManyToManyField并将帖子(不删除它)从channel_posts
移到channel_deleted_posts
。必要的钩子,我很害怕。
我真的希望有更好的答案,你想要的是微不足道的。我很想被证明是错的! :)