Rami_H
Rami_H

Reputation: 401

A help in concept and a database query question (Django/Python)

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)

Upvotes: 0

Views: 75

Answers (2)

Gary Chambers
Gary Chambers

Reputation: 25838

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()

Upvotes: 1

Dima Bildin
Dima Bildin

Reputation: 1553

You should learn about forms and model forms in django. It would be the best way for both adding and changing. Forms will do the most of job for you.

Upvotes: 0

Related Questions