Django: Retrieve a list of one model property for all distinct values of another property

Question:

I’d like to use the Django ORM to give me a list values of a model property for the subset of objects that have a distinct value of another property. Consider a simple model like:

class Result(models.Model):
    color = models.CharField()
    score = models.IntegerField()

And imagine that I have four results:

results = [
    Result(color="blue", score=5), 
    Result(color="blue", score=3), 
    Result(color="red", score=10), 
    Result(color="red", score=8),
]

What I’d like to get is something like the following:

{
    {"color”: "blue", "scores": [5, 3]}, 
    {"color": "red", "scores": [10, 8]},
}

I think it’s possible to get there in one shot using Django’s aggregation and annotation features, but I’m struggling to figure it out. I know I can get the average score with the following:

results.values("color").annotate(avg_score=Avg("score"))

If that’s possible, then getting the list used to generate the average must also be possible, right?

Asked By: Patrick

||

Answers:

Unfortunatly, this will depend on you DB.
If you’re using Postgresql you have access to ArrayAgg,
so the following will work :

results.values("color").annotate(scores=ArrayAgg("score"))

You’re using MySQL or MariaDB you can use GroupConcat.
But this won’t yield an array, it will yield a string with values separated by commas.
If this field will be manipulated using Python, you can do the following to get an array:

my_result.scores.split(",")
Answered By: Alombaros
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.