/ / Modelli Django: aggregati su modelli non direttamente correlati - django, modelli django

Modelli Django: aggregati su modelli non direttamente correlati - django, modelli django

Ho i seguenti modelli:

class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
some_field = models.CharField(max_length=100)


class UserRating(models.Model):
subject_user = models.ForeignKey(User, related_name="rated_user", on_delete=models.CASCADE)
rating_user = models.ForeignKey(User, related_name="rating_user", on_delete=models.CASCADE)
rating = models.IntegerField()

class Meta:
unique_together = ("subject_user", "rating_user")

Sto cercando di ottenere un queryset di tutti i profili utente con valore medio annotato della valutazione nel modello UserRating.

Ho provato a fare quanto segue:

    queryset = UserProfile.objects.all()
for profile in queryset:
user = profile.user
ratingset = UserRating.objects.filter(subject_user = user).values_list("rating")
if len(ratingset) == 0:
profile.rating = 0
else:
profile.rating = sum(ratingset) / float(len(ratingset))

Tuttavia questo genera il seguente errore:

TypeError: unsupported operand type(s) for +: "int" and "tuple"

Ho pensato di calcolare la somma ripetendo il classificatore, ma il mio approccio sembra eccessivo. C'è un modo più semplice per raggiungere questo obiettivo?

risposte:

0 per risposta № 1

Django offre in realtà vari metodi per aggregare direttamente tramite SQL, che è molto più efficiente. Questo dovrebbe portare a termine il lavoro:

profiles_with_ratings = UserProfile.objects.annotate(rating=Avg("user__rated_user__rating"))

documenti qui: https://docs.djangoproject.com/en/2.0/topics/db/aggregation/

Nota a margine: ciò che effettivamente hai è una relazione molti a molti tra utenti che stai costruendo manualmente per qualche motivo.