A help in concept and a database query question (Django/Python)
Question: I am trying to build a kind of news website for learning purposes.

    
    
    class NewsCategory(models.Model):
        category = models.CharField(max_length=50)
    

Note: A category can be Soccer, Tennis, business ... User can register to
different news category. This choice will be saved in their preferences.

    
    
    class Profile(models.Model):
        user = models.ForeignKey(User, unique=True)
        gender = models.CharField(max_length=1,blank=True)
        preference = models.ManyToManyField(NewsCategory)
    

I am currently stuck on how to update the preference list of each user (the
list that specifies in which categories he is interested in.)

**View:**

    
    
    category = [(item.category) for item in NewsCategory.objects.all()]
    

and then I am sending the `category` to the template below

**template:**

    
    
    <div id="c_b">
        {% for c in category %}
            <input type="checkbox" name="category[]" value="{{c}}">
            <label for="{{c}}">{{c}}</label>
        {% endfor %}
    </div>
    

**Questions:**

  1. What is the best way to add the checked tag next to the checkboxes that are already saved in the user's preference when I display the template. 

I though of getting all the preferences users are registered for:
`saved_preference = user.preference.all()` and then checking for each item in
`category` if it is in `saved_preference`

I am also blanking out on the way to actually write that into code, and
whether this should be done in the view or the template.

  2. What is a good way to update the user preference list?

I was planning on running `user.preference.clear()` and then going through
every item in the submitted form and running
`user.preference.add(the_new_preference)`


Answer: You'll need to pass the complete list of categories and also an index of user-
selected categories to your template. You don't need to convert the
`NewsCategory` queryset into a list in your view, by the way:

**View**

    
    
    categories = NewsCategory.objects.all()
    user_preferences = [item.id for item in Profile.preference.all()]
    

The `user_preferences` variable will act as a lookup index for our template.

Then you loop through all the categories in the template, and check to see if
it exists in the list of user preferences:

**Template**

    
    
    <div id="c_b">
    {% for c in categories %}
        <input type="checkbox" name="category[]" id="id_{{ c.category }}" value="{{ c.id }}" {% if c.id in user_preferences %}checked="checked"{% endif %} />
        <label for="id_{{ c.id }}">{{ c.category }}</label>
    {% endfor %}
    </div>
    

**Update - saving user preferences**

There is no hard and fast rule here. The main consideration, as far as I am
concerned, would be minimising database hits. You can just clear the user
preferences, like you say, and add the new ones - in fact, this is how
Django's admin handles it. Just make use of Django's transaction management:

    
    
    from django.db import transaction
    
    @transaction.commit_manually
    def add_preferences(user, preferences):
      user.preference.clear()
      for pref in preferences:
        user.preference.add(pref)
      transaction.commit()
    

