Note that there are some explanatory texts on larger screens.

plurals
  1. POHow can I have model field names (or operators) in a variable?
    primarykey
    data
    text
    <p>I'm trying to refactor my little voting functions. I've got two of them which do almost exactly the same thing, only to different model fields. Voters can add stars to a song if they like it, and they can add flags to a song if they dislike it. The voters are then associated with the song via a many2many relationship, so it can be determined if they already voted on that song. If so, a star (or a flag) is removed from the song and the relationship between voter and song is removed also.</p> <p>Here is the function that adds or removes stars:</p> <pre><code># models.py class UserProfile(models.Model): user = models.ForeignKey(User, unique = True, related_name = 'profile') liked_songs = models.ManyToManyField('Song', blank = True, null = True) disliked_songs = models.ManyToManyField('Song', blank = True, null = True) class Song(models.Model): song_id = models.CharField(max_length = 36, primary_key = True) last_accessed = models.DateTimeField() stars = models.IntegerField(max_length = 5, default = 0) flags = models.IntegerField(max_length = 5, default = 0) # views.py def vote(request, song_id, task): # 'task' should be either 'stars' or 'flags' song = Song.objects.get(song_id = song_id) voter = request.user.get_profile() # Voter does not already like the song if not voter.liked_songs.filter(song_id = song.song_id): # (*) try: # Increase vote, set 'last_accessed', add Song to UserProfile.liked_songs Song.objects.filter(song_id = song_id).update( stars = F('stars') + 1, # (*) last_accessed = datetime.datetime.now() ) voter.liked_songs.add(song) # (*) except: raise else: try: # Decrease vote, set 'last_accessed', remove Song from UserProfile.liked_songs Song.objects.filter(song_id = song_id).update( stars = F('stars') - 1, # (*) last_accessed = datetime.datetime.now() ) voter.liked_songs.remove(song) # (*) except: raise return "Done." </code></pre> <p>The function that adds or removes flags is exactly the same, except for the marked (*) lines:</p> <pre><code>if not voter.disliked_songs.filter(song_id = song.song_id) flags = F('flags') + 1, flags = F('flags') - 1, voter.disliked_songs.add(song) voter.disliked_songs.remove(song) </code></pre> <p>Now here's my first question: What do I have to do to use only one function for liking and disliking a song? I have already introduced the argument <code>task</code> but I can't seem to write <code>task = F('task') + 1,</code>, because there is no field name 'task' in the Song model.</p> <p>Bonus question: The only difference between <code>stars = F('stars') + 1,</code> and <code>stars = F('stars') - 1,</code> is the operator (<code>+</code> or <code>-</code>). Is there a way to have an operator in a variable, i.e. <code>task = F('task') myoperator 1,</code>?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload