fuji
fuji

Reputation: 1203

Different display of items in view/template depending on model in Django

I have a model, that looks something like this:

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

class Vote(models.Model):
    user = models.ForeignKey(User, related_name='user_set')
    topic = models.ForeignKey(Topic, related_name='topic_set')
    score = models.IntegerField(default=0)

    class Meta:
        unique_together = ("user", "topic")

In my index view, I want to display a list of all the topics. If the user has already voted on the topic, it should show his score. If the user has not voted, it should display a form for the user to vote.

I have extended the model with this method as part of the Topic class:

def user_has_already_voted(self, user):
    if not Vote.objects.filter(topic=self.id,user=user.id):
        return True
    else:
        return False

However I don't know whether this is the way to go in Django, since I don't know how to write a view with a corresponding template to perform this task. As of now, I am using a generic IndexView, which looks like this:

class IndexView(generic.ListView):
    template_name = 'topics/index.html'
    context_object_name = 'latest_topic_list'

    def get_queryset(self):
        return Topic.objects.order_by('-pub_date')[:5]

Upvotes: 1

Views: 249

Answers (3)

OBu
OBu

Reputation: 5177

You can use a RedirectView to achieve this:

in your views.py, do something like this (this is code I'm using in a current project, the idea ist quite similar.

class AbstimmungRedirectView(generic.RedirectView):

    def get_redirect_url(self, pk):
        abstimmung = get_object_or_404(Abstimmung, pk=pk)     
        if abstimmung.abgeschlossen(): 
            #Die Abstimmung wurde durch Angabe eines Enddatms als "Beendet" markiert
            return reverse('my_app:MultipleChoiceFrageResults', args=(int(pk),))
        else:
            return reverse('my_app:MultipleChoiceFrageDetail', args=(int(pk),))

you should replace my abstimmung.abgeschlossen() by your has_voted() and use the reverse url for the templates you want to show.

Upvotes: 0

gameboy
gameboy

Reputation: 43

use context. In view add:

    def get_context_data(self, **kwargs):
        context = {
            'is_voted' : self.user_has_already_voted(self.request.user),
        }
        context.update(kwargs)
        return super(IndexView, self).get_context_data(**context)

and in template use:

{% if is_voted %}
     Show vote results
{% else %}
     Show vote form
{% endif %}

Upvotes: 2

Konstantin Kovrizhnykh
Konstantin Kovrizhnykh

Reputation: 191

You can access your user_has_already_voted in template:

{% if topic.user_has_already_voted %}
Show vote results
{% else %}
Show vote form
{% endif %}

Upvotes: 1

Related Questions