【问题标题】:Django admin override model field validationDjango 管理员覆盖模型字段验证
【发布时间】:2020-03-13 03:16:59
【问题描述】:

我的模型中有一个fee DecimalField,如下所示:

class CardTypes(models.Model):
    class Meta:
        db_table = "card_types"
        verbose_name = 'Card Type'
        verbose_name_plural = 'Card Types'

    name = models.CharField("Name", max_length=255, null=True, blank=True)
    fee = models.DecimalField("Fee", max_digits=65, decimal_places=0, default=0)
    image_url = models.CharField("Image Url", max_length=255, null=True, blank=True)

    deleted_at = models.DateTimeField(null=True, blank=True)

    def card_type_image(self):
        if self.image_url is not None:
            return mark_safe('<img src="%s" width="130" height="90" />' % (self.image_url))
        else:
            return "No image yet"
    card_type_image.short_description = 'image'

    def fee_convert(self):
        if self.fee is not None:
            currency = Currency.objects.get(pk=1)
            return Decimal(self.fee / pow(10, currency.decimals))
        else:
            return None
    fee_convert.short_description = 'Fee'

我设置了DecimalField("Fee", max_digits=65, decimal_places=0, default=0),因为我想在我的数据库中不带小数位保存它,但在管理站点上我想与转换后的方法进行交互。

例如,如果数据库中的费用为 0.00005,那么在管理员中它只会显示并保存为 5 的值(因为 currency.decimals = 5)

我设法在管理端显示转换后的值并保存为 5 的值,如下所示:

class CardTypeAdminForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(CardTypeAdminForm, self).__init__(*args, **kwargs)
        if self.instance.fee is not None:
            try:
                self.initial['fee'] = self.instance.fee_convert()
            except:
                pass

    def clean_fee(self):
        if self.cleaned_data['fee'] is not None:
            currency = Currency.objects.get(pk=1)
            data = Decimal(self.cleaned_data['fee'] * pow(10, currency.decimals))
        else:
            data = None

        return data

class CardTypesAdmin(admin.ModelAdmin):
    list_display = ('name', 'card_type_image',)
    list_display_links = ('name', 'card_type_image', )

    form = CardTypeAdminForm
    fields = (
        'id',
        'name',
        'fee',
        'image_url',
        'card_type_image',
        'deleted_at',
    )

    readonly_fields = (
        'id',
        'card_type_image',
        'deleted_at'
    )

admin.site.register(CardTypes, CardTypesAdmin)

但如果我想在管理员中输入值为 0.005 或小数位的费用字段(应该可以,因为在数据库中它将保存为 500),但管理员验证返回以下验证错误:

确保不超过 0 位小数。

由于管理表单字段从模型字段继承验证,我是否可以覆盖它?

【问题讨论】:

    标签: python django django-forms django-admin django-validation


    【解决方案1】:

    我通过在表单中​​创建新字段替换费用表单字段找到了解决方法:

    class CardTypeAdminForm(forms.ModelForm):
        currency = Currency.objects.get(pk=1)
        fee = forms.DecimalField(required=False, decimal_places=currency.decimals)
        def __init__(self, *args, **kwargs):
            super(CardTypeAdminForm, self).__init__(*args, **kwargs)
            if self.instance.fee is not None:
                try:
                    self.initial['fee'] = self.instance.fee_convert()
                except:
                    pass
    
        def clean_fee(self):
            if self.cleaned_data['fee'] is not None:
                currency = Currency.objects.get(pk=1)
                data = Decimal(self.cleaned_data['fee'] * pow(10, currency.decimals))
            else:
                data = None
    
            return data
        class Meta:
            model = CardTypes
            exclude = ['fee']
    
    class CardTypesAdmin(admin.ModelAdmin):
        list_display = ('name', 'card_type_image',)
        list_display_links = ('name', 'card_type_image', )
    
        form = CardTypeAdminForm
        fields = (
            'id',
            'name',
            'fee',
            'image_url',
            'card_type_image',
            'deleted_at',
        )
    
        readonly_fields = (
            'id',
            'card_type_image',
            'deleted_at'
        )
    
        def save_model(self, request, obj, form, change):
            obj.fee = form.cleaned_data['fee']
            return super(CardTypesAdmin, self).save_model(request, obj, form, change)
    

    【讨论】:

      猜你喜欢
      • 2019-07-16
      • 1970-01-01
      • 2012-09-18
      • 1970-01-01
      • 2021-07-14
      • 2014-05-21
      • 1970-01-01
      • 2018-02-12
      • 2011-07-26
      相关资源
      最近更新 更多