Подтвердить что ты не робот

Заменить сохранение в Django InlineModelAdmin

Этот вопрос может выглядеть как этот, но его не...

У меня есть модельная структура вроде:

class Customer(models.Model):
    ....

class CustomerCompany(models.Model):
    customer = models.ForeignKey(Customer)
    type = models.SmallIntegerField(....)

Я использую InlineModels и имею два типа CustomerCampany.type. Поэтому я определяю два разных строковых значения для CustomerCompany и ov override InlineModelAdmin.queryset

class CustomerAdmin(admin.ModelAdmin):
    inlines=[CustomerCompanyType1Inline, CustomerCompanyType2Inline]


class CustomerCompanyType1Inline(admin.TabularInline):
    model = CustomerCompany
    def queryset(self, request):
        return super(CustomerCompanyType1Inline, self).queryset(request).filter(type=1)

class CustomerCompanyType2Inline(admin.TabularInline):
    model = CustomerCompany
    def queryset(self, request):
        return super(CustomerCompanyType2Inline, self).queryset(request).filter(type=2)

Все хорошо и хорошо, но для добавления новых записей для InlineModelAdmin мне все равно нужно отобразить type поле CustomerCompany на AdminForm, так как я не могу переопределить метод save от InlineModelAdmin как:

class CustomerCompanyType2Inline(admin.TabularInline):
    model = CustomerCompany
    def queryset(self, request):
        return super(CustomerCompanyType2Inline, self).queryset(request).filter(type=2)
    #Following override do not work
    def save_model(self, request, obj, form, change):
        obj.type=2
        obj.save()

Использование сигнала также не является решением, так как мой сигнал sender будет таким же Model, поэтому я не могу определить, какой InlineModelAdmin отправить его, а что type должно быть...

Есть ли способ, который позволит мне установить поле type перед сохранением?

4b9b3361

Ответ 1

Ответ Alasdair не ошибается, но у него есть несколько серьезных проблем, которые могут вызвать проблемы. Во-первых, путем прокрутки набора форм с использованием form в качестве имени переменной вы фактически переопределяете значение, переданное в метод для form. Это не огромная сделка, но поскольку вы можете сделать сохранение без фиксации прямо из набора форм, лучше сделать это именно так. Во-вторых, все важные formset.save_m2m() были исключены из ответа. Фактические Django docs рекомендуют следующее:

def save_formset(self, request, form, formset, change):
    instances = formset.save(commit=False)
    for instance in instances:
        # Do something with `instance`
        instance.save()
    formset.save_m2m()

Проблема, с которой вы столкнетесь, заключается в том, что метод save_formset должен идти по родительскому ModelAdmin, а не по строкам, а оттуда нет способа узнать, какая строка используется. Если у вас есть obj с двумя "типами", и все поля одинаковы, вы должны использовать прокси-модели, и вы можете фактически переопределить метод сохранения каждого, чтобы автоматически установить соответствующий тип.

class CustomerCompanyType1(CustomerCompany):
    class Meta:
       proxy = True

    def save(self, *args, **kwargs):
        self.type = 1
        super(CustomerCompanyType1, self).save(*args, **kwargs)

class CustomerCompanyType2(CustomerCompany):
    class Meta:
       proxy = True

    def save(self, *args, **kwargs):
        self.type = 2
        super(CustomerCompanyType2, self).save(*args, **kwargs)

Затем вам не нужно делать ничего особенного с вашими строками. Просто измените существующие классы встроенных админов, чтобы использовать их подходящую прокси-модель, и все будет сортировать себя.

Ответ 2

Здесь save_formset метод, который вы можете переопределить. Вам нужно будет решить, какая строка formset представляет как-то.

def save_formset(self, request, form, formset, change):
    instances = formset.save(commit=False)
    for instance in instances:
        # Do something with `instance`
        instance.save()
    formset.save_m2m()

Ответ 3

Другие ответы правильны, когда дело доходит до использования save_formset. У них отсутствует способ проверить, какая модель в настоящее время сохраняется. Для этого вы можете просто:

if formset.model == CustomerCompany:
    # actions for specific model

Что бы сделать функцию save_formset такой: (предполагая, что вы просто хотите переопределить сохранение для конкретной модели (моделей))

def save_formset(self, request, form, formset, change):

    # if it not the model we want to change
    # just call the default function
    if formset.model != CustomerCompany:
        return super(CustomerAdmin, self).save_formset(request, form, formset, change)

    # if it is, do our custom stuff
    instances = formset.save(commit=False)
    for instance in instances:
        instance.type = 2
        instance.save()
    formset.save_m2m()