在Django管理站点中显示ManyToManyField

时间:2018-05-24 12:49:50

标签: django django-models django-admin

我正在浏览Mozilla的django tutorial。他们基本上创建了一个公共图书馆。他们并没有真正谈论ManyToMany关系,并且已经设置好了,因此一本书只能有一个作者。

在完成本教程的过程中,我决定不再复制本地库,而是尝试创建IMDB的基本功能。所以我最终只是基本上复制和粘贴代码而不是学习任何东西。

我已经设置了一个展示可以让很多创作者使用ManyToMany字段的方式。在我的类创建者中,我有两个变量 first_name last_name 。我有另一个类Show ,它有很多其他变量。

现在在名为show的应用程序的 admin.py 中,我想要它,以便在我的ShowAdmin中,它将显示admin表中的创建者。问题在于Django不支持ManyToMany,因为查询负担很大。

Now my possible solution is to:
1) create an empty array
2) loop through the first_name array and add it to the empty array.
3) loop through the last_array and add it to the empty array
4) then join the array to get my desired result of "last_name, first_name" in the admin table.

在我开始讨论之前,我想知道是否有更简单的方法可以解决这个问题?我不太了解python和django,(或者一般关于编程),所以如果可能,你能ELI5吗?

以下是我的模特和我的管理员:

Admin.py

from django.contrib import admin
from .models import Show, Creator, Cast, Language, Genre


class ShowAdmin(admin.ModelAdmin):
    list_display =('title','language','display_genre', 'display_creator')

# Register your models here.
admin.site.register(Show, ShowAdmin)
admin.site.register(Creator)
admin.site.register(Cast)
admin.site.register(Language)
admin.site.register(Genre)

Models.py (至于我的模特,有什么我做错了或者会给我带来很多麻烦吗?)

from django.db import models
from django.urls import reverse

class Genre(models.Model):
    name = models.CharField(max_length=200, help_text="Enter a show genre (e.g. Action, Drama, etc.)")

    def __str__(self):
        return self.name

class Language(models.Model):
    name = models.CharField(max_length=200, help_text="Enter a show's language (e.g. English, Japanese, etc.)")

    def __str__(self):
        return self.name

class Creator(models.Model):
    first_name = models.CharField(max_length=100)
    last_name  = models.CharField(max_length=100)

    class Meta:
        ordering = ['first_name','last_name']

    def get_absolute_url(self):
            return reverse('author-detail', args=[str(self.id)])

    def __str__(self):
        return '{0}, {1}'.format(self.first_name,self.last_name)

class Show(models.Model):
        title = models.CharField(max_length=200)
        creator = models.ManyToManyField(Creator, help_text="Select a creator(s)")
        genre = models.ManyToManyField(Genre, help_text='Select a genre for this book')
        language = models.ForeignKey('Language', on_delete=models.SET_NULL, null=True)
        summary = models.TextField(max_length=1000, help_text='Enter a brief description of the show', null=True)
        cast = models.ManyToManyField(Cast, help_text="Select cast")

        def __str__(self):
            return self.title


        def get_absolute_url(self):
            return reverse('show-detail', args=[str(self.id)])

        def display_genre(self):
            return ', '.join([ genre.name for genre in self.genre.all()[:3] ])

        def display_creator(self):
            return ', '.join([creator.first_name for creator in self.creator.all()[:3]])

        display_creator.short_description = 'Creator'
        display_genre.short_description = 'Genre'

奖金问题(如果你有时间):通过管理员添加节目肯定是可能的,但在我看来效率不高。在我的工作模型中,如果我想在节目中添加创作者,我必须经过大量选择并选择正确的人。现在让我们说我的数据库有1000个创建者,向下滚动所有选项并找到正确的人是不太实际的。现在我认为我只是在教程的第4部分(AdminSite),是否有更实用的方法在节目中添加创作者?

我知道这篇文章真的很长,我很抱歉。但我只是想说谢谢你的时间。我真的很感激。

1 个答案:

答案 0 :(得分:1)

您可以将生成器表达式与join()

一起使用
def get_creator_names(self, obj):
    return ', '.join('{} {}'.format(creator.first_name, creator.last_name)  for creator in obj.creators.all()