Get minimum of related model date field (django)


Get minimum of related model date field (django)



I have the two following classes:


class Incident(models.Model):
iid = models.IntegerField(primary_key=True)
person = models.ForeignKey('Person', on_delete=models.SET_NULL, null=True)


class Source(models.Model):

sid = models.IntegerField(primary_key=True)
incident = models.ForeignKey('Incident', on_delete=models.SET_NULL, null=True)
url = models.TextField(validators=[URLValidator()])
datereported = models.DateField(null=True, blank=True)



I want to create a field within the Incident that will pull the minimum datereported of related sources. Is this best done in the model, or in the template? Unsure what best practice is, or how to execute in this case.





Do you mean the datereported itself, or the corresponding Source object?
– Willem Van Onsem
Jul 1 at 17:25


datereported


Source





the datereported itself! but i am curious about returning the source object too. is it the same process?
– NBC
Jul 1 at 17:28





2 Answers
2



Is this best done in the model, or in the template?



Well a template should - strictly speaking - not contain business logic. It should contain render logic. It should thus specify how something should be visible, not what should be visible. So it dos not really belong in the template layer, only in the model layer.



You can obtain the smallest datereported with:


datereported


from django.db.models import Min

class Incident(models.Model):
iid = models.IntegerField(primary_key=True)
person = models.ForeignKey('Person', on_delete=models.SET_NULL, null=True)

@property
def first_reporteddate(self):
return self.source_set.aggregate(first=Min('datereported'))['first']



This will ignore Sources with datereported set to None (so if there are multiple sources, it takes the smallest datereported that is not None). If there are no Source with a datereported not equal to None, or no related Sources at all, it will return None however, since the minimum of an empty set is considered to be NULL (in SQL, or None in Python/Django).


Source


datereported


None


datereported


None


Source


datereported


None


Source


None


NULL


None



You can then use this in the template like:


{{ some_incident.first_reporteddate }}



In case you want the entire object, you can use self.source_set.order_by('datereported').first() which will give you the earliest related Source instance. But this will have a (quite) small impact on performance (it will take a bit longer). In that case Django will fetch all columns into memory first. If you thus only need one column, this will result in the fact that you did some useless serialization (at the database end) and deserialization (at the Python end).


self.source_set.order_by('datereported').first()


Source



You can use model's property for this:


class Incident(models.Model):
iid = models.IntegerField(primary_key=True)
person = models.ForeignKey('Person', on_delete=models.SET_NULL, null=True)

@property
def first_datereported(self):
first_source = self.source_set.order_by('datereported').first()
if first_source:
return first_source.datereported



In template or in any other part of code you can use first_datereported as normal model's field:


first_datereported


{{ incident_instance.first_datereported }}





i think you need to add the check for None in last_source
– Bear Brown
Jul 1 at 17:27


None


last_source





@BearBrown you are right. Thanks!
– neverwalkaloner
Jul 1 at 17:31





Won't this return the first datereported? In that case first_datereported probably is a better name (or earliest_reporteddate).
– Willem Van Onsem
Jul 1 at 17:31


datereported


first_datereported


earliest_reporteddate





@WillemVanOnsem sure, thank you!
– neverwalkaloner
Jul 1 at 17:33






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Rothschild family

Cinema of Italy