Django objects.filter в шаблоне - PullRequest
0 голосов
/ 07 мая 2018

У меня есть проект django с тремя нижеприведенными моделями:

models.py
from django.db import models
from django.contrib.auth.models import User


class Album(models.Model):
    owner = models.ForeignKey(User)
    title = models.CharField(max_length=127)
    artist = models.CharField(max_length=63)
    release_date = models.DateField()
    logo = models.ImageField(blank=True, upload_to='album_logos', default='album_logos/no-image.jpeg')
    t_added = models.DateTimeField(auto_now_add=True)
    slug = models.SlugField(null=True, blank=True, max_length=63)

    class Meta:
        ordering = ['-release_date']

    def __str__(self):
        return self.title


class Song(models.Model):
    album = models.ForeignKey(Album, on_delete=models.CASCADE)
    name = models.CharField(max_length=255)
    # is_favorite = models.BooleanField(default=False)
    favorites = models.IntegerField(default=0)
    song_file = models.FileField(blank=True, null=True, upload_to='song_files', default='song_files/mektub.mp3')

    class Meta:
        ordering = ['name']

    def __str__(self):
        return self.name


class Favorite(models.Model):
    user = models.ForeignKey(User)
    song = models.ForeignKey(Song)
    created = models.DateTimeField(auto_now_add=True)

Как видно из этих моделей, многие пользователи могут добавлять в избранное множество песен. В шаблоне я хочу добавить класс к песням, которым пользуется аутентифицированный пользователь:

template
<span {% if authenticated user favorited this song %}class="favorited" {% endif %}></span>

Моя проблема в том, что я не знаю, как написать «если аутентифицированный пользователь одобрил эту песню» в шаблоне. В терминале я могу получить эту информацию по этому коду:

user_favorited_this = song.favorite_set.filter(user=sample_user) and True or False

Я не мог сделать то же самое в шаблоне, так как он не поддерживает передачу аргумента в метод фильтра. Как я могу преодолеть эту проблему?

Ответы [ 2 ]

0 голосов
/ 08 мая 2018

Может быть проще сделать это в представлении, а затем передать результат в шаблон в виде логического флага.

Например:

def song_view(request):
    ...
    song = Song.objects.get(pk=request.GET['song_id'])
    is_favorite = song.favorite_set.filter(user=request.user).exists()
    return render(request, 'my_template.html', {'is_favorite': is_favorite})

или для универсальногопредставление на основе классов:

class SongDetail(DetailView):
    ...
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        song = self.get_object()
        is_favorite = song.favorite_set.filter(user=self.request.user).exists()
        context['is_favorite'] = is_favorite
        return context

, а затем код в вашем шаблоне можно упростить до:

<span {% if is_favorite %}class="favorited" {% endif %}></span>
0 голосов
/ 07 мая 2018

Фильтр тегов может делать то, что вы хотите:
Если User.favorite_set.all имеет что-то общее с Song.favorite_set.all, это означает, что текущий пользователь добавил эту песню в избранное

from django import template
register = template.Library()

# Method 1 for django queryset (Better)
@register.filter    
def intersection(queryset1,queryset2):
    return queryset1 & queryset2

# Method 2 for queryset or python List
@register.filter
def intersection(queryset1,queryset2):
    return list(set.intersection(set(queryset1),set(queryset2)))

HTML:

{% if request.user.favorite_set.all|intersection:song.favorite_set.all %} class="favorited" {% endif %}
...