开发者

Check whether object is in QuerySet of related objects

I am building an application having to do with game achievements, and I want to display for each game, a page that lists the related achievements. That is done.

However, I also want each user to be able to see in that list which achievements they have completed.

My model is like this:

class Achievement(models.Model):
    game = models.ForeignKey(Game)
    ...

class Game(models.Model):
    ...

class GameProfile(models.Model):
    achievements = models.ManyToManyField(Achievement, through='Achieved')
    ...

class Achieved(models.Model):
    profile = models.ForeignKey(GameProfile)
    achievement = models.ForeignKey(Achievement)
    curr_count = models.PositiveSmallIntegerField()

In the game template page, I get all the achievements for the current game through the relationship with the Achievement model (ie achievements = game.achievement_set.all). Then I do a {% for ach in achievements %} on them and output a <li> for each. If a user is logged in, I also want to display the curr_count associated with the achievement. So I need a list of Achieved objects for the specific GameProfile (think of it as the current user).

The problem is that I cannot do {% if ach in achieved %} (where ach is an Achievement instance and achieved an Achieved QuerySet), obviously.

I also thought I could get a QuerySet with the Achievements the user has achieved, but that lacks the curr_count, which I want to display.

I think what I want is some kind of list or dictionary with the Achievements of the user against which I can test if a specific Ac开发者_C百科hievement is a member, but which will also carry the curr_count variable. Another solution might be to somehow add curr_count as a field to a QuerySet of Achievement objects (which will be the ones the user has achieved).

Can you suggest how to accomplish this in django?


If your GameProfile model has a link to (auth.)User then you can generate the following queryset and send it to the template.

def achievements_by_user(request, *args, **kwargs):
    user = request.user
    queryset = Achieved.objects.filter(profile__user = user)
    return render_to_response(...)

This queryset will filter all rows from Achieved based on the currently logged in user. If you also want to filter based on game (i.e. return all achievements for the currently logged in user for a specific game) then you can add another filter condition.

    queryset = Achieved.objects.filter(profile__user = user, 
            achievement__game = <a game>)

Update

Apparently I misunderstood the question. Here is another stab at it.

@register.filter
def achievement_in(achieved, achievement):
    count = achieved.filter(achievement = achievement).count()
    return count > 0

# In template
{% for ach in achievements %}
    {% if achieved|achievement_in:ach %} 
        ...
    {% else %}
        ...
    {% endif %}
{% endfor %}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜