Ich arbeite an einem Projekt mit einem Channel/Post-Mechanismus. Ich implementiere derzeit Funktionen zum "Löschen" von Beiträgen, indem ich ein Feld mit dem Namen "gelöscht" in einen Zeitstempel des Zeitpunkts des Löschens einstelle. Es muss für die historische Bedeutung (letzte Aktivität) aufbewahrt werden und Personen, die inflammatorisch sind, verfolgen (der Dienst ist ein privilegierter Teil des gesamten Projekts).Django ORM Filtern von Objekten nach Feldwerten?
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)
ich einen Endpunkt haben, die aktualisiert das „gelöschte“ -Feld der „Post“ Objekt ein Zeitstempel von null zu sein. Wie vermeide ich es dann, alle Posts zurückzugeben, die einen Timestamp haben, wenn sie auf der "Channel" -Ebene abgefragt werden, die Posts durch ihre Beziehung geladen werden und einen separaten Serializer? Grundsätzlich muss ich in der Lage sein, "Channel" abzufragen und eine Liste der Kanäle zu erhalten, in denen ich ein Teil bin, und dann durch ihre Beziehung von ManyToMany mit "Post" alle zugehörigen Posts mit Ausnahme derjenigen, die einen Wert im Feld "deleted" haben . Ist dies möglich, ohne das ORM für jeden Kanal aufzurufen und anschließend die gelöschten Beiträge herauszufiltern? Um klar zu sein, der "Channel" sollte immer noch durchkommen, wenn es einen gelöschten Post gibt, nur der "Post" selbst sollte ausgeblendet werden.
Wenn ich nicht genug Informationen zur Verfügung gestellt habe, lassen Sie mich wissen, was Sie sehen müssen. Wenn die Antwort lautet, dass dies ohne wiederholte ORM-Aufrufe nicht möglich ist, würden andere Optionen empfohlen, einschließlich der Möglichkeit, die Posts auf ein Duplikatmodell zu "archivieren", ohne dass in diesen Situationen Hooks aufgerufen werden müssen und Löschen des Originals.
Edit 1: eine Eigenschaft hinzufügen, wie in der gewählten Antwort erwähnt, aber es kann nicht self.channel_posts
sehen. 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
Derzeit wie oben gezeigt, es ist ein ORM Anruf pro Kanal, aber das Drucken self.channel_posts
oder self.channel_users
gibt eine leere Liste, in allen Szenarien.
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
verwenden lief in ein Problem versucht, diese zu verwenden, wie sie ist, aus irgendeinem Grund 'Selbst .channel_posts' ist ein leeres Array, das am Punkt der Eigenschaft (über einen Druck) gefiltert wird. Am Ende musste ich es in ein gefiltertes Abfrageset aller Posts überarbeiten, aber das wird aufgrund von so vielen DB-Aufrufen nicht gut im Maßstab funktionieren, irgendwelche Ideen, warum es leer angezeigt würde? Deine Antwort ist immer noch die sauberste, ich hoffe nur, dass es funktionieren kann, wie du es geschrieben hast, anstatt meiner improvisierten Version. So oder so, danke für Ihre Hilfe und Zeit! – AntonMiles
Wenn Sie den Code genau so ausführen, wie er ist, würden Sie natürlich active_posts für den "ersten" Kanal in Ihrer Datenbank bekommen. seit Channel.objects.first() gibt ersten Kanal in DB zurück. Könnte es sein, dass der erste Kanal keine Beiträge hat? – Ramast
Ich habe es so angepasst, dass es 'active_posts' als Quelle für die Repräsentation der ManyToMany-Beziehung des Serialisierers verwenden kann. Ich werde die Frage bearbeiten, um dies zu verdeutlichen, aber es sieht in keinem der Kanäle etwas für meinen Standardbenutzer. Wer hatte Beiträge verfügbar, bevor er die Löschfunktion startete, und wer hat seitdem gepostet (was funktioniert und über einen anderen Endpunkt sichtbar ist). Es ist immer noch die beste Antwort, und es für ein Queryset zu tauschen funktioniert, nur in der Hoffnung, den DB IO-Belastung zu reduzieren. * zur besseren Übersicht bearbeitet. – AntonMiles