尝试在Django中按类别过滤图像

时间:2011-04-25 21:40:11

标签: django django-models

我正在尝试通过类别过滤图像。它工作但不是我想要的方式。以下是我的模型设置方式:

class Image(models.Model):
    CATEGORY_CHOICES = (
    ('Cover', 'Cover'),    
    ('Scan', 'Scan'),
    ('Other', 'Other'),
    )
    title = models.CharField(max_length=256)
    image = models.ImageField(upload_to="images/")
    category = models.CharField(max_length=10, choices=CATEGORY_CHOICES)
    contributor = models.ManyToManyField(Contributor, blank=True, null=True)
    date_added = models.DateField(auto_now_add=True)    
    def __unicode__(self):
        return self.title
    class Meta:
        ordering = ['title']


class Issue(models.Model):

    ...

    images = models.ManyToManyField(Image, related_name="images_inc", blank=True, null=True)

    ....

    def __unicode__(self):
        return u'%s #%s' % (self.title, self.number)
    def get_absolute_url(self):
        return "/issues/%s" % self.slug     
    class Meta:
        ordering = ['-date_added']

Views.py:

def issue(request, issue_slug):
    issue = get_object_or_404(Issue, slug=issue_slug)
    cover = Image.objects.filter(category='Cover')
    scan = Image.objects.filter(category='Scan')
    return render_to_response('comics/issue_detail.html', {'issue': issue, 'cover': cover, 'scan': scan}, context_instance=RequestContext(request))

我正试图通过Cover或Scan过滤它,如你所见,但是当我把它放入我的模板时:

{{ cover }} or {{ scan }}

它返回:

<Image: Astonishing X-Men 1 Cover A>] [<Image: Astonishing X-Men 1, teamshot>]

显然,我需要它来返回图片网址。添加{{cover.url}}不起作用。

哦,我刚刚意识到它没有显示问题中的特定图像。它显示分类为扫描或封面的所有图像。

2 个答案:

答案 0 :(得分:0)

filter总是返回数组中的匹配列表。

如果你只是想要第一场比赛,你可以做这样的事情

 cover = issue.images.filter(category='Cover')[:1][0]
 scan = issue.images.filter(category='Scan')[:1][0]

但如果没有匹配则会抛出异常,所以最好在尝试中包装但不包括

try:
     cover = issue.images.filter(category='Cover')[:1][0]
except:
     cover = None 

在模板中,由于封面和扫描代表图像对象,因此您可以使用以下语法获取网址:

{{ cover.image.url }} or {{ scan.image.url }}

如果要查看所有图像,可以选择加载封面和扫描(复数)并检查模板中是否为空。除了这里的索引错误之外没有必要,而且它更简单。

在这种情况下,你会这样做:

 covers = issue.images.filter((category='Cover'))

然后在模板中:

{% if covers %}
    {% for cover in covers %}
          {{cover.image.url}} - {{cover.title}}
    {% endfor %}
{% endif %}

答案 1 :(得分:0)

在您当前的代码中,您将返回所有图像,甚至是与您选择的漫画问题无关的图像。我假设您想要选定问题的那些。你可能想要这样做:

def issue(request, issue_slug):
    issue = get_object_or_404(Issue, slug=issue_slug)
    try:
        cover = issue.images_inc.filter(category='Cover')[0]
    except IndexError:
        cover = None
    try:
        scan = issue.images_inc.filter(category='Scan')[0]
    except IndexError:
        scan = None
    return render_to_response('comics/issue_detail.html', {'issue': issue, 'cover': cover, 'scan': scan}, context_instance=RequestContext(request))

然后,在模板中:

{% if cover.image %}
    <img src="{{ cover.image.url }}" alt="{{ cover.image.title }}" />
{% endif %}

{% if scan.image %}
    <img src="{{ scan.image.url }}" alt="{{ scan.image.title }}" />
{% endif %}

更新

如果您确实需要多个封面或扫描,那么您不希望只获得第一个项目。实际上,您应该将此逻辑移至models.py以避免可能的代码重复。

这样的事情会更好:

# models.py


class Issue(models.Model):
    ...
    def scans(self):
        return self.images.filter(category='Scan')

    def covers(self):
        return self.images.filter(category='Cover')

# views.py

def issue(request, issue_slug):
    issue = get_object_or_404(Issue, slug=issue_slug)
    return render_to_response('comics/issue_detail.html', {'issue': issue }, context_instance=RequestContext(request))

然后,在模板中:

<ul>
{% for cover in issue.covers %}
    <li><img src="{{ cover.image.url }}" alt="{{ cover.image.title }}" /></li>
{% empty %}
    <li>No cover</li>
{% endfor %}
</ul>

<ul>
{% for scan in issue.scans %}
    <li><img src="{{ scan.image.url }}" alt="{{ scan.image.title }}" /></li>
{% empty %}
    <li>No scans</li>
{% endfor %}
</ul>
相关问题