Django, Python

Xử lí khi có sự khác biệt các fields trong Form Admin

Trường hợp Bảng ae_fonttype có các trường(id, name, order, font_type)

Khi hiển thị(view) cần có các trường (name, font_type, font_list) font_list: là danh sách các font có cùng font_type được lưu ở ae_fonttype_font_list

Khi thêm bản ghi mới(add) chỉ có(name, font_type)

Model(models/font_type.py):

class FontType(models.Model):
    class Meta:
        verbose_name = 'フォントタイプ'
        verbose_name_plural = 'b.1 フォントタイプ一覧'
        ordering = ['order']

    name = models.CharField(verbose_name="名前", null=True, blank=True, max_length=32)
    font_list = ManyToManyField(
        Font,
        related_name='fonttypes',
        blank=True)
    order = models.PositiveIntegerField(verbose_name="順序", default=0, blank=False, null=False)
    font_type = models.CharField(verbose_name="フォントタイプ", max_length=1, choices=Font.FONT_TYPE_CHOICES, default=Font.OTHER)

    def __str__(self):
        return self.name

Do khác biệt font_list(khi add không có) nên cần thiết kế 2 Form khác nhau (forms/font_type.py)

class FontTypeForm(ModelForm):

    class Meta:
        model = FontType
        fields = [
            'name', 'font_list', 'font_type'
            ]

    def __init__(self, *args, **kwargs):
        super(FontTypeForm, self).__init__(*args, **kwargs)
        self.fields['name'].required = True

class FontTypeAddForm(ModelForm):

    class Meta:
        model = FontType
        fields = [
            'name', 'font_type'
            ]

    def __init__(self, *args, **kwargs):
        super(FontTypeAddForm, self).__init__(*args, **kwargs)
        self.fields['name'].required = True

Trong admin.py gọi Form

admin.site.register(FontType, FontTypeAdmin)

Nếu đặt chung FontTypeForm và sử dụng readonly_fields = (‘font_list’, )

class FontTypeAdmin(SortableAdminMixin, admin.ModelAdmin):
    list_display = ('name', 'font_type')
    search_fields = ('name',)
    list_filter = ('font_type', )
    readonly_fields = ('font_list', )
    form = FontTypeForm

Sẽ dẫn đến lỗi vì DB không có font_list cũng như readonly_fields = (‘font_list’, ) chỉ để hiển thị không sửa chỉnh sửa.
Cần sửa lại như bên dưới.

class FontTypeAdmin(SortableAdminMixin, admin.ModelAdmin):
    list_display = ('name', 'font_type')
    search_fields = ('name',)
    list_filter = ('font_type', )

    def get_form(self, request, obj=None, change=False, **kwargs):
        if obj is None or request.method in ['POST', 'PUT']:
            self.form = FontTypeAddForm
            self.readonly_fields = ()
        else:
            self.form = FontTypeForm
            self.readonly_fields = ('font_list', )
        return super().get_form(request, obj, change, **kwargs)

Hàm get_form sẽ xác định Form và readonly_fields (None hay font_list) dựa vào request.method

Khi View (request.method = GET) : FontTypeForm, readonly_fields = font_list

Khi Add (request.method = POST hoặc PUT): FontTypeAddForm, readonly_fields = ()