title: How can I have model field names (or operators) in a variable?
body: <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>