Django - inline - поиск существующей записи вместо добавления новой

У меня есть библиотека с полками и книгами. Я указываю каждую книгу на одну полку в отношениях "один ко многим". Если книга указывает на 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, ]

Когда я редактирую Shelf, я могу видеть и изменять все книги, которые находятся на этой полке.

Проблема:

  • У меня есть много книг уже в библиотеке (указывая на Null).
  • Если я нажму "Добавить другую книгу" из строки, она создаст совершенно новую книгу. Но я хочу этого избежать. Я хотел бы выбрать из книг, которые уже находятся в библиотеке, но еще не принадлежит к какой-либо полке.

Ответ 1

Привет, следующий код работал у меня:

from widgets import ImproveRawIdFieldsForm

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

Он создает представление администратора, в котором вы будете использовать обычный материал Shelf и дополнительную встроенную строку, которая является сырым идентификационным полем, и у вас есть возможность добавить новые отношения, и вы можете выбрать из существующих объектов с помощью значка "лупа", который приводит к всплытию списка всех существующих книг. Кроме того, вы выбрали одну книгу во всплывающем окне, вы также можете создавать там новые книги. Поэтому из моего понимания это решает все ваши требования

здесь объясняется лучшее решение этой проблемы: встроенный выбор один-ко-многим с django admin

отредактирован для вашего прецедента:

#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