#django #django-queryset #django-orm
Вопрос:
У меня есть две модели:
Model Student:
name = models.CharField()
..... ....
wishlist = models.ManyToManyField(University, blank=True)
Model University:
name = models.CharField()
...... . .. . . . .
В основном я просто создаю список пожеланий, с помощью которого пользователь может поставить лайк на университет, а затем добавить его в свой список пожеланий ! ( я выражаю это через значок сердца ), Поэтому, когда пользователь повторно нажимает на тот же элемент, он удалит его из списка желаний, вот и все !
Проблема в том, как проверить, понравился ли пользователю тот или иной университет ?
вот мой код:
def index(request):
univesity = University.objects.filter(is_approved=True)
context = {'univesity': univesity}
return render(request, 'search/index.html', context)
выше я привожу весь университет для целей поиска ! В этом случае мне нужно проверить, не добавило ли использование университета в список желаний. И если это правда, то значок сердца превратится в красный или пустой цвет !
А теперь вот как я показываю на шаблоне
{% if data.student_set.all %}
<button><em class="icon ni ni-heart-fill" ></em></button>
{% else %}
<button><em class="icon ni ni-heart"></em></button>
{% endif %}
Это работает не так, как я ожидал ! пожалуйста, направьте
Ответ №1:
Вы можете проверить, понравился ли этому человеку университет, Universities
снабдив его Exists
подзапросом [Django-doc]:
from django.contrib.auth.decorators import login_required
from django.db.models import Exists, OuterRef
@login_required
def index(request):
universities = University.objects.annotate(
liked=Exists(Student.wishlist.through.objects.filter(
student=request.user, university_id=OuterRef('pk')
))
).filter(is_approved=True)
context = {'universities': universities}
return render(request, 'search/index.html', context)
Если Student
это модель пользователя. Если это не так, вам сначала следует выбрать вошедшего в систему пользователя и использовать его в .filter(student=…, …)
части.
Затем мы можем отобразить это в шаблоне с помощью:
{% for university in universities %}
{{ university }}
{% if university.liked %}
<button><em class="icon ni ni-heart-fill" ></em></button>
{% else %}
<button><em class="icon ni ni-heart"></em></button>
{% endif %}
{% endfor %}
Примечание. Вы можете ограничить просмотры представлением для пользователей, прошедших проверку подлинности, с
помощью@login_required
декоратора [Django-doc].
Комментарии:
1. О боже, я не мог понять аннотацию — неужели так сложно выполнить обратный поиск ?
2. @sixovov947: не для фильтрации, но здесь мы делаем подзапрос, чтобы проверить, есть ли список желаний учащихся с именем пользователя
request.suer
иuniversity_id
первичным ключомUniversity
.3. что такое «Внешняя ссылка» и выполнение подзапроса считается дополнительным запросом и настолько эффективно ?
4. @sixovov947: никакие подзапросы не являются частью запроса, поэтому вся работа выполняется базой данных, а не дополнительными запросами из Django.
OuterRef
относится к полю, которое относится не к подзапросу, а к внешнему запросу (поэтому здесь запросUniversity
модели, мы, таким образом, ссылаемся на первичный ключUniversity
, по которому мы определяем, понравился ли пост).5. Это выдает ошибку «объект » Существует» не имеет атрибута»фильтр»».