Django 管理 - 自定义列表外观和 ManyToManyField 键的选择

Posted

技术标签:

【中文标题】Django 管理 - 自定义列表外观和 ManyToManyField 键的选择【英文标题】:Django Administration - Customize list appearance and selection of ManyToManyField keys 【发布时间】:2021-11-01 04:46:35 【问题描述】:

我有一个包含 1000 多首歌曲的数据库。我有一个自定义模型“Schedule”,它接受歌曲作为字段。

models.py

from django.db import models

class Song(models.Model):
    title = models.CharField(max_length=255)
    words = models.TextField()
    slug = models.SlugField()
    date = models.DateTimeField(auto_now_add=True)
    snippet = models.CharField(max_length=50)

    def __str__(self):
        return self.title

class Schedule(models.Model):
    songs = models.ManyToManyField(Song)
    date = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return str(self.date)

admin.py

from django.contrib import admin
from .models import Song, Schedule

@admin.register(Song)
class SongModel(admin.ModelAdmin):
    search_fields = ('title',)
    list_display = ('title',)
    list_per_page = 100

@admin.register(Schedule)
class ScheduleModel(admin.ModelAdmin):
    search_fields = ('date',)
    list_display = ('date',)
    list_per_page = 100

我希望能够将任何我想要的歌曲添加到时间表中,但是通过 Django-Administration 中的默认列表(looks like this)很难做到这一点。我必须滚动并 CTRL+选择它们中的每一个,然后添加它们。

我想要更实用的东西,我可以选择、搜索等。

我有哪些选择?我不知道从哪里开始寻找。

【问题讨论】:

我猜您正在寻找的是管理操作,它可以让您执行搜索并选择多个而不会丢失您的选择并一次实施它们。看看这个https://docs.djangoproject.com/en/3.2/ref/contrib/admin/actions/ 感谢您的建议,但我不知道如何在那里使用操作...意思是,当我从主管理页面单击“时间表”时,我会进入时间表列表(在那里,我可以使用动作)。但在屏幕截图中,我点击了该列表中的特定时间表,现在我看到了一个歌曲列表...... 【参考方案1】:

选项 1

只有当您的相关项目很少(计划中的歌曲很少)时,它才会很舒服。但这非常容易,并且会比您现在拥有的更好。 (django.contrib.admin 自带内置select2。)

@admin.register(Schedule)
class ScheduleAdmin(admin.ModelAdmin):
    ...
    autocomplete_fields = ("songs",)

选项 2

(upd:该死,一开始忘记了,也超级简单高效)

看起来还不错。可用。不是特别舒服。但比 ctrl-click 更好。

@admin.register(Schedule)
class ScheduleAdmin(admin.ModelAdmin):
    ...
    filter_horizontal = ('songs',)

选项 3

如果您想要一个舒适的用户界面而不实现自定义页面或操作(不幸的是,这完全是一团糟),您应该使用StackedInline admin。

不过难度还是蛮大的。

首先您需要一个through model。 (我认为自动生成的多对多模型不可能内联。)这两个模型之间基本上是你的many-to-many。类似的东西:

class ScheduleSongNM(models.Model):
    song = models.ForeignKey("Song", null=False)
    schedule = models.ForeignKey("Schedule", null=False)

告诉您的Schedule 模型使用您的自定义直通模型:

class Schedule(models.Model):
    songs = models.ManyToManyField(Song, through="ScheduleSongNM")

现在为ScheduleSongNM 创建一个内联管理员:

class ScheduleSongInline(admin.StackedInline):
    model = ScheduleSongNM
    fields = ["song"]
    autocomplete_fields = ["song"]  # select2 works here too

最后,告诉您的 Schedule 管理员它现在有一个内联:

@admin.register(Schedule)
class ScheduleAdmin(admin.ModelAdmin):
    ...
    inlines = [ScheduleSongInline]
    ...

也许我错过了一些东西(显然我没有测试过),但我想你已经明白了。最后,您会在 Schedule 管理员中看到一个看起来像这样的框(加上歌曲名称的自动完成):

【讨论】:

选项 2 非常完美!它可以轻松搜索和添加,比我现在拥有的无穷无尽的列表要好得多。另外,我认为您的意思是 filter_horizo​​ntal = ('songs',) 对于我的特殊情况。谢谢! @Angelo 当您的数据库中有数千首歌曲并且带有“选项 2”的页面将永远加载时,您会考虑“选项 3”哈哈 该死!这意味着我正在将此页面添加为书签,以便在我的一生都崩溃时返回 xD

以上是关于Django 管理 - 自定义列表外观和 ManyToManyField 键的选择的主要内容,如果未能解决你的问题,请参考以下文章

Django,在管理员中更多2个

管理员中的 Django 自定义列表视图

如何在 Django 管理列表显示页面中编辑 ManyToManyField?

python DJANGO - 管理员自定义列表过滤器

html 通过Django的部件,调整自定义表单外观

python Django:向管理员更改列表视图添加自定义按钮