Объединение, фильтрация моделей / представлений в ManyToMany Django - PullRequest
1 голос
/ 11 июля 2011

Я работаю над базой комиксов, и есть основные обложки и варианты обложек.У меня есть страница, на которой показаны все основные обложки, но я бы тоже хотел объединить варианты обложек в порядке даты публикации.Вот как выглядит часть моих моделей:

class Image(models.Model):
    CATEGORY_CHOICES = (
    ('Cover', 'Cover'),    
    ('Scan', 'Scan'),
    ('Other', 'Other'),
    )
    title = models.CharField(max_length=128)
    number = models.CharField(max_length=20, help_text="Do not include the '#'.")
    image = models.ImageField(upload_to="images/")
    category = models.CharField(max_length=10, choices=CATEGORY_CHOICES)
    ### The variant cover is determined by the category_choice 'Cover'. ###
    contributor = models.ManyToManyField(Contributor, blank=True, null=True)
    date_added = models.DateField(auto_now_add=True, auto_now=True)    
    def __unicode__(self):
        return self.title        
    class Meta:
        ordering = ['title']

class Issue(models.Model):
    CATEGORY_CHOICES = (
    ('Major', 'Major'),    
    ('Minor', 'Minor'),
    ('Cameo', 'Cameo'),
    ('Other', 'Other'),
    )
    title = models.ForeignKey(Title)
    number = models.CharField(max_length=20, help_text="Do not include the '#'.")
    pub_date = models.DateField(blank=True, null=True)
    cover_image = models.ImageField(upload_to="covers/", blank=True, null=True)
    ### This would be where the main image goes. ^^^ ###
    images = models.ManyToManyField(Image, related_name="images_inc", blank=True, null=True)
    ### This is where the variant covers go.^^^  ### 
    has_emma = models.BooleanField(help_text="Check if Emma appears on the cover.")

Мой views.py для главной титульной страницы выглядит так:

def covers(request):
    sort_by = request.GET.get('sort', 'pub_date')
    if sort_by not in ['-date_added', 'date_added', '-pub_date', 'pub_date']:
        sort_by = '-date_added'
    issues = Issue.objects.filter(has_emma=True).order_by(sort_by).select_related(depth=1)
    return render_to_response('comics/covers.html', {'issues': issues}, context_instance=RequestContext(request))

Но я бы хотел отобразить варианты обложектоже, а не только cover_image.Есть ли способ сделать это?Может быть, с чем-то image и последующей фильтрацией категории (модели Image по обложке)?

Я, конечно, могу сделать это:

def variants(request):
    Issue.objects.filter(has_emma=True).order_by(sort_by).select_related(depth=1)
    images = Image.objects.filter(category='Cover').order_by('id')
    return render_to_response('comics/variants.html', {'images': images}, context_instance=RequestContext(request))

Но это не дает мне достаточной гибкости, как def covers, и я хочу, чтобы они объединялись и сортировались по pub_date, как def covers.

Редактировать

models.py:

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


class Issue(models.Model):
    title = models.ForeignKey(Title)
    number = models.CharField(max_length=20)
    ######
    has_emma = models.BooleanField(help_text="Check if cover appearance.")    
    cover_image = models.ImageField(upload_to="covers/", blank=True, null=True)
    images = models.ManyToManyField(Image, related_name="images_inc", blank=True, null=True)
    ######
    def get_images(self):
        ''' Returns a list of all cover images combined,
            "main" cover image first.
        '''
        images = [self.cover_image]
        for image in self.images.filter(category='Cover'):
            images.append(image.image)
        return images   

views.py:

def covers(request):
    sort_by = request.GET.get('sort', '-pub_date')
    if sort_by not in ['-date_added', 'date_added', '-pub_date', 'pub_date']:
        sort_by = '-date_added'         
    issues = Issue.objects.filter(has_emma=True).order_by(sort_by)
    return render_to_response('template.html', {'issues': issues,}, context_instance=RequestContext(request))

шаблон.html: {% for issue in issues %}{% for image in issue.get_images %}{{ image.image }}{% endfor %}{% endfor %} - ничего не отображается, однако {% for issue in issues %} {% for image in issue.get_images %} {{ issue.cover_image }} {% endfor %} {% endfor %} будет многократно отображать cover_image модели Issue, если есть варианты обложек, которые классифицированы в модели Image.

Что я могу сделать, чтобы это исправить, чтобы он все правильно показывал?И снова для записи, я хочу, чтобы он отображал {{ cover_image }} (из модели Issue) и {{ image.image }}, как это определено в сочетании с Image моделью.

1 Ответ

0 голосов
/ 11 июля 2011

Если я правильно понимаю вашу проблему, одним из способов ее решения было бы добавление метода в класс Issue, например:

class Issue(models.Model):
    # fields...

    def get_images(self):
        ''' Returns a list of all cover images combined,
            "main" cover image first.
        '''
        images = [self.cover_image]
        for image in self.images.filter(category='Cover'):
            images.append(image.image)
        return images

Затем в вашем шаблоне вы можете, например,{% for image in issue.get_images %}....

(Если это не совсем то, что вам нужно, то, я думаю, было бы лучше, если бы вы предоставили некоторый шаблон кода в качестве примера того, чего вы пытаетесь достичь.)

...