Джанго - Модели FK/ много2 многих отношений
Мне нужно немного лучше понять, как работают отношения ФК / м2. Я подготовил модель изображений для загрузки изображений, и у нее есть дополнительная функция - ее можно классифицировать, добавив в определенную галерею (отношение m2m к галерее).
Чтобы получить доступ к названию галереи, мне просто нужно было сделать набор запросов, например:
Images.objects.filter(gallery__gallery_name = '')
Я хотел бы немного изменить запрос, чтобы из модели галереи я мог получить доступ к изображениям, которые находятся в определенной галерее (gallery_name).
Как я могу это сделать?
Модели:
class Images(models.Model):
image = models.ImageField(upload_to=update_filename, blank=True, null=True, verbose_name="Obrazek")
gallery = models.ForeignKey('Gallery', blank=True, null=True)
class Gallery(models.Model):
gallery_name = models.CharField(max_length=128)
gallery_description = models.TextField(blank=True, null=True)
Посмотреть:
def index(request):
p = Gallery.objects.filter(gallery_name="main").order_by('-id')
return TemplateResponse(request, 'gallery.html',
{'gallery': p,
},)
Шаблон:
{% for n in gallery.all %}
<h2 class="center">{{n.gallery_name}}</h2>
<hr>
{% for n in gallery.images_set %}
<div class="grid_4">
{{ n.image }}
</div>
{% endfor%}
3 ответа
Попробуйте что-то вроде:
# models.py
class Gallery(models.Model):
name = models.CharField(max_length=30)
description = models.CharField(max_length=200, null=True)
images = models.ManyToMany(Image)
class Image(models.Model):
title = models.CharField(max_length=30)
caption = models.CharField(max_length=200, null=True)
image = models.ImageField(upload_to=SOMEPLACE_FOR_MEDIA)
Отсюда вы должны быть в состоянии сделать такие вещи, как:
image = Image.objects.get(title="Girl Holding Cheese")
related_galleries = image.gallery_set.all()
или что-то подобное по мере необходимости, чтобы тянуть, что вы хотите То же самое идет в другую сторону. Чтобы вытащить все изображения в галерее, вы должны сделать
gallery = Gallery.objects.get(name="Cheesy Wimmin")
related_images = gallery.images.all()
Хотя в конце назначения не нужны, я обычно просто передаю gallery.images.all() или image.gallery_set.all() напрямую. Обратите внимание на "_set" в конце ссылки от объекта, который не содержит определения M2M.
На предмет непосредственного использования вы можете сделать составные ссылки, такие как
Image.objects.get(title="Girl Holding Cheese").gallery_set.all()
также, но вы должны решить, когда это делает код более четким и лаконичным, а когда просто делает его более запутанным для чтения позже.
Я надеюсь, что это направит вас в правильном направлении.
Обновить
В своем комментарии ниже вы заметили, что вы не можете сделать
images = Images.objects.filter(gallery_set="Cheesy Wimmins")
related_galleries = images.gallery_set.all()
Это потому, что вы пытаетесь фильтровать () или все () в наборе запросов, а не в отдельной модели. Поэтому, чтобы сделать это, вы можете использовать цикл for в вашем шаблоне. Что-то вроде
# views.py
galleries = Gallery.objects.all()
return render(request, 'some/template.html', {'galleries': galleries})
А потом
<!-- templates/some/template.thml -->
{% for gallery in galleries %}
<div class="gallery">
<h2>{{ gallery.name }}</h2>
{% for item in gallery.images.all %}
<div class="image">
{{ item.image }}
</div>
{% endfor %}
</div>
{% endfor %}
или что-то вроде этого. Конечно, вам нужно выполнить все необходимые шаги форматирования, чтобы это выглядело правильно, но это способ получить ваши данные.
Проблема с {% for n in gallery.images_set %}
немного в вашем шаблоне. images_set
это связанный менеджер, а не набор запросов. Чтобы получить набор запросов, вам нужно позвонить all
или другой из методов DBAPI, которые возвращают наборы запросов. Так что просто измените его на gallery.images_set.all
и ты хорош.
gallery
это QuerySet
- у него нет images_set
,
Это место, где более правильно присваивать имена переменным, можно легко начать предотвращать эти проблемы: например, galleries
было бы более подходящим для списка объектов галереи... тогда, galleries.images_set
немедленно поднимет красные флаги.
В любом случае, вам нужно позвонить images_set
на то, что вы назвали n
{% for n in gallery.all %}
<h2 class="center">{{n.gallery_name}}</h2>
<hr>
{% for n in n.images_set.all %}
<div class="grid_4">
{{ n.image }}
</div>
{% endfor%}