django - 内联 - 搜索现有记录而非添加新记录

15 投票
1 回答
7768 浏览
提问于 2025-04-18 15:17

我有一个图书馆,里面有书架和书籍。每本书都指向一个书架,这是一种一对多的关系。如果一本书指向Null,那就意味着这本书在图书馆里,但还没有放到任何书架上。

#models.py

class Shelf(models.Model):
    pass

class Book(models.Model):
    shelf = models.ForeignKey(Shelf, blank=True, null=True)

接下来:

#admin.py

class BookInLine(admin.TabularInLine):
    model = Book
    extra = 0

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

当我编辑书架的时候,我可以看到并修改所有在这个书架上的书。

问题:

  • 我在图书馆里已经有很多书(指向Null)。
  • 如果我点击“添加另一本书”,它会创建一本全新的书。但我想避免这样。我希望能从那些已经在图书馆里但还没有放到任何书架上的书中进行选择。

1 个回答

9

你好,下面的代码对我来说是有效的:

from widgets import ImproveRawIdFieldsForm

class BookInline(admin.TabularInline):
    model = Book
    raw_id_fields=('shelf',)
    extra =1
class Shelf(ImproveRawIdFieldsForm):
    inlines = [BookInline,]

这段代码创建了一个管理员视图,你可以看到正常的书架内容,还有一个额外的内联字段,这个字段是一个原始的ID字段。你可以添加新的关系,并且可以通过“放大镜”图标选择已有的对象,这样会弹出一个包含所有现有书籍的列表。在这个弹出的窗口中,除了选择一本书之外,你还可以创建新的书籍。所以根据我的理解,这个方法满足了你所有的需求。

这个问题的更好解决方案可以在这里找到:Django 管理后台的一对多内联选择

根据你的使用情况进行了编辑:

#models.py
class Book(models.Model):
    shelf = models.ForeignKey(Shelf, blank=True, null=True, related_name="in_shelf")

#admin.py
class ShelfForm(forms.ModelForm):
    class Meta:
        model = Shelf

    books = forms.ModelMultipleChoiceField(queryset=Book.objects.all())

    def __init__(self, *args, **kwargs):
        super(ShelfForm, self).__init__(*args, **kwargs)
        if self.instance:
            if self.instance.in_shelf:
                self.fields['books'].initial = self.instance.in_shelf.all()
            else:
                self.fields['books'].initial = []

    def save(self, *args, **kwargs):    
        instance = super(ShelfForm, self).save(commit=False)
        self.fields['books'].initial.update(shelf=None)
        self.cleaned_data['books'].update(shelf=instance)
        return instance

撰写回答