Django: получить атрибут (imagefield) из объекта обратной связи внешнего ключа

#python #django #django-models

#python #django #django-модели

Вопрос:

Я боролся с правильным синтаксисом для этого. Я хочу создать галерею фотоальбомов и выбрать фотографию обложки для каждого альбома. Но для этого мне нужно захватить объект обратной связи, а затем выбрать из него атрибут imagefield. Я знаю, как использовать диспетчер отношений для фильтрации объекта cover photo (на основе логического атрибута cover), но не знаю, как затем получить атрибут imagefield из этого объекта (для последующей ссылки в шаблоне для img src). Вот мой models.py

 from django.db import models
    
def make_pic_path (instance, filename):
        albname = instance.album.name
    path = 'AlbPics/{0}/{1}'.format(albname, filename)
    return path

class Album(models.Model):
    name = models.CharField(max_length = 100)
    dates = models.CharField(max_length = 100) 
    description = models.CharField(max_length = 1000)
    
    def cover_photo (self):
        return self.albumpicture_set.filter(cover = True)

    def __str__(self):
        return self.name    

class AlbumPicture(models.Model):
    picture = models.ImageField(upload_to = make_pic_path, blank = True)
    picture_desc = models.CharField(max_length=200)
    album = models.ForeignKey(Album, on_delete=models.CASCADE)
    cover = models.BooleanField()
    
    def __str__(self):
        return self.picture_desc
 

и views.py:

 from django.shortcuts import render
from .models import Album, AlbumPicture
from django.contrib.auth.decorators import login_required

@login_required
def alb_gallery(request):
    gallery = Album.objects.all()
    context = {'gallery': gallery, }
    return render(request, 'gallery/gallery.html', context)
 

И шаблон gallery.html (или мое лучшее предположение)

 {% if gallery %}
    <ul>
        {% for entry in gallery %}
            <ul>
                <li> {{entry.name}} </li>
                <li><img src= "{{entry.cover_photo.url}}"> {{entry.name}}</li>
            </ul>
        {% endfor %}
    </ul>
{% endif %}
 

Я думаю, в идеале я хотел бы иметь метод внутри модели альбома, который вернет атрибут imagefield, необходимый для фотографии обложки. Это кажется достаточно простым, но я не могу в этом разобраться!

Заранее спасибо 🙂

Комментарии:

1. Как вы хотите обрабатывать альбомы с несколькими фотографиями на обложке или без фотографий на обложке? Простым решением может быть добавление внешнего ключа из альбома в AlbumPicture для фотографии обложки

2. Я, честно говоря, еще не там…. Я хотел сначала разобраться с этим, а затем закрыть эти дыры. Но, допустим, если нет фотографии обложки, фотография не отображается.

Ответ №1:

Благодаря объединенным предложениям Biplove и iklinac я понял, как это сделать!

Метод в модели альбома:

 def cover_photo (self):
    cov = self.adventurepicture_set.get(cover = True)
    return cov.picture
 

Спасибо!

Ответ №2:

Во-первых, фотография обложки не будет больше одной (я полагаю?). Спасибо @iklinac за указание на filter неверность при ожидании отдельного объекта. Поскольку ответ уже дан @Sara. Я все же хотел бы предложить хороший способ обработки пустых случаев.

 class Album(models.Model):
    ....

    def cover_photo (self):
        obj = {}
        try:
            obj = (self.albumpicture_set.get(cover = True)).picture
        except:
            # The cover photo is empty then show default cover pic
            obj.url = "default_cover.jpg" 
        return obj
 

Комментарии:

1. Я попробовал это, и я получаю следующую ошибку: объект ‘QuerySet’ не имеет атрибута ‘picture’

2. фильтр всегда будет возвращать набор запросов

3. да, как задокументировано docs.djangoproject.com/en/3.1/topics/db/queries /…

4. в случае использования filter: obj = self.albumpicture_set.filter(cover = True) будет obj[0] ссылаться на фактический объект?

5. да, единственное различие в конце будет в случае разной обработки исключений