I am working on a project that involves a channel/post mechanism. I am currently implementing functionality to "delete" posts by setting a field named "deleted" to a timestamp of when it was deleted. It needs kept for historical significance (last activity) and to track people who are inflammatory (the service is a privilege based portion of the whole project).
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)
I have an endpoint which updates the "deleted" field of the "Post" object to be a timestamp from null. How do I then avoid returning all Posts which have a timestamp when queried at the "Channel" level, having the Posts be loaded through their relationship and a separate serializer? Basically, I need to be able to query "Channel" and get a list of channels I am a part of, then through their relationship of ManyToMany with "Post" load all related Posts excluding those that have a value in the "deleted" field. Is this possible without calling the ORM for each channel, subsequently filtering out the deleted posts? To be clear, the "Channel" should still come through if there's a deleted post, only the "Post" itself should be hidden.
If I didn't provide enough information, just let me know what you need to see.
If the answer is that this is not possible without repetitious ORM calls, suggesting other options would be appreciated, including weighing in on the option to "archive" the posts to a duplicate model, without hooks to be called during these situations and deleting the original.
Edit 1:
Add a property as noted in the chosen answer, however it can't see 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
Currently, as shown above it's an ORM call per channel, but printing self.channel_posts
or self.channel_users
returns an empty list, in all scenarios. The property is called as a part of Django Rest Framework's serializer as implemented below:
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