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:
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 incategoryif it is insaved_preferenceI 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.
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 runninguser.preference.add(the_new_preference)
2 Answers 2
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()
2 Comments
for="id_{{ c.id }}"? Do you think it is a good approach to clear the list and then update it all every time the form is submitted? I am suggesting this because I don't think there a straightforward way to know if a user removed/added a preference (or did both).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.