python – Structuring Django Many-to-Many Relation – Education Career Blog

In writing an application for my school’s yearbook committee, I’ve hit a bit of a dead end with modeling a specific relation. Currently I have a photo class

class Photo(models.Model):
 photo = models.ImageField(upload_to="user_photos/")
 name = models.CharField(blank=True, max_length=50)

 rating = models.IntegerField(default=1000)

 wins = models.IntegerField(default=0)
 matches = models.IntegerField(default=0)

and a user class

class UserProfile(models.Model):
 user = models.ForeignKey(User, unique=True)
 group = models.CharField(max_length=50)

both of which are working swimmingly. What I’d like to do is break it up so that a Photo will have global rating derived from votes of the entire userbase as well as a rating based only on the users votes on that photo. Unfortunately, I’m at a loss on how to structure this. My first thought was a ManyToMany field, but I was also thinking that something like breaking rating into its own model like this:

class Rating(models.Model)
     photo = models.ManyToOne(Photo)
     rating = models.IntegerField(default=1500)

could work.

Could a Django (or really, anyone who’s slightly competent, because I know I’m not) guru point me in the proper direction on approaching this simple conundrum?

,

You want a through table.

,

you want to have a many-to-many field, but custom defined.

class Rating(models.Model):
    photo = models.ForeignKey(Photo)
    user = models.ForeignKey(User)
    rating = models.IntegerField(default=1500)

class Photo(models.Model):
    photo = models.ImageField(upload_to="user_photos/")
    name = models.CharField(blank=True, max_length=50)

    rating = models.ManyToManyField(User, through='Rating')

    wins = models.IntegerField(default=0)
    matches = models.IntegerField(default=0)

you can then query it either having a photo object or a user object.

This approach is naive and won’t scale well. On a very popular website the Ratings model would be overloaded with requests. What would a more professional website do is denormalise the dependency by introducing a redundant integer field such as rating_total and set up a cron job to update it periodically so that you don’t need to construct a query through a many-to-many relationship, but get the result from a field straight away.

,

I do not exactly understand your question, but for represeting a many-to-one-relation in django you use a ForeignKey-field! But as Ignacio already pointed out a many-to-many relation with an intermediary model might also be useful for you!

,

I don’t understand well this sentence : “Photo will have global rating derived from votes of the entire userbase as well as a rating based only on the users votes on that photo.”

But if you mean that you want to create a field rating for where you have the sum of all users rate and also saving another one that contain user photo rate ; you should first make a think is it worth it because for calculated fields you have the choice between physically storing (global rate) such values in the database or calculating them as needed. you should make the decision based on how often the computed value is needed and how much information is needed to calculate it.

Note that storing the computed value means computing it each time you do a change in the users rate.

Leave a Comment