Администрирование Django — Настройка внешнего вида списка и выбор множества ключей ManyToManyField

#python #django #administration #manytomanyfield

Вопрос:

У меня есть база данных с более чем 1000 песнями. У меня есть пользовательская модель «Расписание», которая принимает песни в качестве поля.

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-администрировании, который выглядит так. Я должен прокрутить и CTRL выбрать каждый из них, а затем добавить их.

Мне бы хотелось чего-то более практичного, где я мог бы выбирать, искать и т. Д.

Какие у меня есть варианты? Я не знаю, с чего начать поиски.

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

1. Я предполагаю, что вы ищете действия администратора, которые могут позволить вам выполнять поиск и выбирать несколько вариантов, не теряя свой выбор, и реализовывать их все сразу. Взгляните на это https://docs.djangoproject.com/en/3.2/ref/contrib/admin/actions/

2. Спасибо за предложение, но я не уверен, как там использовать действия… Это означает, что когда я нажимаю «Расписания» на главной странице администрирования, я попадаю в список расписаний (там я могу использовать действия). Но на скриншоте я затем щелкнул по определенному расписанию из этого списка, и теперь я вижу список песен…

Ответ №1:

Вариант 1

Это удобно только в том случае, если у вас очень мало связанных предметов (несколько песен в расписании). Но это очень просто и будет лучше, чем то, что у вас есть сейчас. (django.contrib.admin поставляется со встроенным выбором 2.)

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

 

Вариант 2

(upd: черт, сначала забыл об этом, это также очень просто и довольно эффективно)

Все выглядит нормально. Пригодный. Не особенно удобно. Но лучше, чем щелкать по материалу ctrl.

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

Вариант 3

Если вам нужен удобный пользовательский интерфейс без реализации пользовательских страниц или действий (которые, к сожалению, являются полным беспорядком), вам следует использовать администратора StackedInline.

Хотя это немного сложнее.

Сначала вам понадобится сквозная модель. (Я не думаю, что строки возможны с автоматически сгенерированными моделями «многие ко многим».) В основном это ваше соотношение «многие ко многим» между двумя моделями. Что-то вроде того:

 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 администратора, которое выглядит примерно так (плюс автоматическое заполнение названий песен).:

скриншот

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

1. Вариант 2 идеально подходит! Он может легко искать и добавлять, намного лучше, чем бесконечный список, который у меня сейчас есть. Также я думаю, что вы имели в виду filter_horizontal = («песни»,) для моего конкретного случая. Спасибо!

2. @Angelo Когда в вашей базе данных будет много тысяч песен, а страница с «вариантом 2» будет загружаться вечно, вы рассмотрите «вариант 3», ха-ха-ха

3. Черт возьми! Это означает, что я закладываю эту страницу, чтобы вернуться, когда вся моя жизнь рухнет xD