Django 管理员扩展外键下拉选择器

92 阅读2分钟

在 Django 中,当你在管理界面编辑外键时,你会发现下拉列表中只包含了已经存在的对象,而无法创建新的对象。这对于某些场景来说可能不是很方便,比如你在创建新模型时需要选择一个外键,而又不想先创建这个外键对象。

2、解决方案 Django 提供了多种方法来扩展外键下拉选择器,以便在管理界面中可以选择已经存在的对象或创建新的对象。

方法一:使用 RawIdField

RawIdField 允许你在管理界面中输入外键对象的 ID,然后 Django 会自动加载这个对象。在 admin.py 中,你可以通过以下方式使用 RawIdField:

class BookInline(admin.TabularInline):
    model = Book
    raw_id_fields=('shelf',)
    extra =1

class Shelf(admin.ModelAdmin):
    inlines = [BookInline,]

方法二:使用 Select2

Select2 是一个 JavaScript 库,可以为你的下拉列表提供更丰富的功能,比如支持搜索和分页。在 Django 中,你可以使用 django-select2 库来集成 Select2。

在 admin.py 中,你可以通过以下方式使用 Select2:

from django.contrib.admin import widgets

class BookInline(admin.TabularInline):
    model = Book
    formfield_overrides = {
        models.ForeignKey: {'widget': widgets.Select2Widget},
    }
    extra =1

class Shelf(admin.ModelAdmin):
    inlines = [BookInline,]

方法三:使用 ModelForm

ModelForm 允许你在管理界面中使用表单来编辑模型。在 admin.py 中,你可以通过以下方式使用 ModelForm:

from django.forms import ModelForm
from django.contrib.admin import widgets

class BookForm(ModelForm):
    class Meta:
        model = Book

    shelf = forms.ModelChoiceField(queryset=Shelf.objects.all())

class Shelf(admin.ModelAdmin):
    form = BookForm

方法四:使用自定义视图

如果你需要更加复杂的自定义行为,你可以创建自定义视图来处理外键的选择。在 admin.py 中,你可以通过以下方式创建自定义视图:

from django.contrib.admin import ModelAdmin, AdminSite
from django.contrib import admin

class MyAdminSite(AdminSite):
    def has_permission(self, request):
        return True

class BookAdmin(ModelAdmin):
    def change_view(self, request, object_id, form_url='', extra_context=None):
        return super().change_view(request, object_id, form_url, extra_context)

    def add_view(self, request, form_url='', extra_context=None):
        return super().add_view(request, form_url, extra_context)

admin_site = MyAdminSite()
admin_site.register(Book, BookAdmin)

代码示例:

#models.py
class Book(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)

class Author(models.Model):
    name = models.CharField(max_length=200)

#admin.py
from django.contrib.admin import ModelAdmin, TabularInline, site
from django import forms

class AuthorInline(TabularInline):
    model = Book

class AuthorAdmin(ModelAdmin):
    inlines = [AuthorInline]

site.register(Author, AuthorAdmin)

这样,当你在管理界面编辑作者时,你就可以在右侧看到所有属于这个作者的书籍,并且可以添加新的书籍。