IordanouGiannis
IordanouGiannis

Reputation: 4357

How can I create a model property based on specific model fields?

Let's say I have the following model:

class DriverReview(models.Model):
    driver = models.ForeignKey(Driver, on_delete=models.CASCADE,)
    driving_score = models.PositiveIntegerField(default=1, validators=[MinValueValidator(1), MaxValueValidator(5)])
    communication_score = models.PositiveIntegerField(default=1, validators=[MinValueValidator(1), MaxValueValidator(5)])
    professionalism_score = models.PositiveIntegerField(default=1, validators=[MinValueValidator(1), MaxValueValidator(5)])
    review_text = models.TextField()
    created = models.DateTimeField(auto_now_add=True)
    created_by = models.ForeignKey(User, related_name="driver_review_created_by", on_delete=models.CASCADE, null=True, blank=True)
    last_updated = models.DateTimeField(auto_now=True)
    last_updated_by = models.ForeignKey(User, related_name="driver_review_last_updated_by", on_delete=models.CASCADE, null=True, blank=True)
    is_deleted = models.BooleanField(default=False)
    deleted = models.DateTimeField(null=True, blank=True)
    deleted_by = models.ForeignKey(User, related_name="driver_review_deleted_by", on_delete=models.CASCADE, null=True, blank=True)

    @property
    def review_average_score(self):
        review_average_score = round(np.mean([self.driving_score, self.communication_score, self.professionalism_score]), 2)
        return review_average_score

I have created a property to get the review average score. The issue is that I don't want to hardcode the _score fields. Is there a way to filter the fields that contain _score and use them in the average ?

Upvotes: 1

Views: 43

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476659

Yes, you can inspect the fields through the _meta, so:

    @property
    def review_average_score(self):
        data = [
            getattr(self, f.attname)
            for f in self._meta.get_fields()
            if '_score' in f.name
        ]
        review_average_score = np.mean(data), 2)
        return review_average_score

Upvotes: 1

Related Questions