2👍
✅
I’m going to recommend and give a rough example of implementing this using a through model on the M2M relation.
class Alert(models.Model):
datetime_alert = models.DateTimeField()
dismissed = models.BooleanField(default=False)
datetime_dismissed = models.DateTimeField(null=True)
auid = models.CharField(max_length=64, unique=True)
entities = models.ManyToManyField(to='Entity', through='AlertEntity')
class Entity(models.Model):
label = models.CharField(max_length=255, unique=True)
class AlertEntityRelationship(models.Model):
permission_label = models.CharField(max_length=45, unique=True)
class AlertEntity(models.Model):
entity = models.ForeignKey(Entity)
alert = models.ForeignKey(Alert)
alertentityrelationship = models.ForeignKey(AlertEntityRelationship, on_delete=models.CASCADE)
And for what you’re trying to recreate I guess it’s fairly close, but I don’t think you are getting any improvement out of your prefetch_related call, here’s a naive example:
for alert in Alert.objects.filter(dismissed=False):
alert_d = {}
alert_d['datetime'] = str(alert.datetime_alert)
alert_d['entities'] = []
for related_entity in alert.alertalertentity_set.filter().select_related('alert', 'entity'):
entity = {}
entity['type'] = related_entity.entity.entity_type.entity_type_label # Don't know where you're getting entity_type from
entity['label'] = related_entity.entity.label
alert_d['entities'].append(entity)
response_data['alerts'].append(alert_d)
Here is a much better solution using the django.db.models.Prefetch
class to do it all one line, though it is a bit more complicated to understand. I recommend reading the django.db.models.Prefetch
and prefetch_related(...)
to understand how it works.
for alert in Alert.objects.filter(dismissed=False).prefetch_related(Prefetch(lookup='alertentity_set', queryset=AlertEntity.objects.filter().select_related('entity'), to_attr='prefetched_alertentity_list'):
alert_d = {}
alert_d['datetime'] = str(alert.datetime_alert)
alert_d['entities'] = []
for related_entity in alert.prefetched_alertentity_list:
entity = {}
entity['type'] = related_entity.entity.entity_type.entity_type_label # Don't know where you're getting entity_type from
entity['label'] = related_entity.entity.label
alert_d['entities'].append(entity)
response_data['alerts'].append(alert_d)
I think this last example is the most optimized version I can come up with.
Source:stackexchange.com