Джанго - Модели 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%}
Другие вопросы по тегам