[Answered ]-Django โ€“ Prepare objects from a view for Current User



What Iโ€™d do would be to get all the userโ€™s current scores up front, create a dictionary mapping exercise to score, then add the score as an attribute of each exercise. Something like:

user_scores = request.user.score_set.all()
score_dict = dict((sc.exo_id, sc.score) for sc in user_scores)
exos = Exercise.objects.all()
for ex in exos:
    ex.current_user_score = score_dict.get(ex.id)

Now each exercise in exos has a current_user_score attribute, which is the current userโ€™s score for that exercise (or None).

๐Ÿ‘คDaniel Roseman


django.contrib.auth has a context processor that adds a user variable to the template context, referencing the current user. This can enable you to get all scores for the current user, then you can create a template filter that returns the score for a particular exercise.

In a file named exercises.py within a templatetags package.

[Put the package in the folder of one of your apps in INSTALLED_APPS. Remember templatetags must be a valid Python package ie. with an __init__.py]

from django.template import Library
register = Library()

def score_for_exercise(scores, exercise):
    s = scores.filter(exo=exercise)
    if s:
        return s[0].score
    return None

In the template:

{% load exercises %}
{% with user.score_set.all as user_scores %}
  {% for exo in exos %}
    {% with user_scores|score_for_exercise:exo as score %}
    <li>{{ exo }}{% if score %} - {{score}}{% endif %}</li>
    {% endwith %}
  {% endfor %}
{% endwith %}
๐Ÿ‘คSimon Kagwi


Maybe you can add an attribute to your Exercise:

class Exercise(models.Model):
    name = models.CharField(max_length=50)

    def __unicode__(self):
        return self.name

    def user_score(self):
        return Score.objects.get(exo=self).score
๐Ÿ‘คReto Aebersold

Leave a comment