简体   繁体   English

从管理表单中的 Django 验证中排除字段

[英]Exclude field from Django validation in admin form

I am working on project with a lot of legacy code base ( Django 2.2 ).我正在处理具有大量遗留代码库( Django 2.2 )的项目。 I have a custom model field for price that goes like this我有一个自定义的 model 价格字段,如下所示

class PriceField(PositiveIntegerField):

    def get_prep_value(self, value: float) -> Optional[int]:
        return int(value * 100) if value else self.default

    def from_db_value(self, value: int, expression, connection) -> Optional[float]:
        return value / 100 if value else value


class Expertise(models.Model):
    price = PriceField(blank=True, default=0, help_text='Price per min.')
    ...

Prices are stored in db multiplied by 100, eg 9.90 is stored as 990 , and values are obtained from db in human readable way ( 990 as 9.90 ).价格存储在 db 中乘以 100,例如9.90存储为990 ,值以人类可读的方式从 db 中获取( 9909.90 )。

Now I am facing a problem with default PositiveIntegerField Django admin form validation for that field.现在,我面临该字段的默认 PositiveIntegerField Django 管理表单验证问题。 Because this value represented as float every time I click "Save" I get a PositiveIntegerField 's ValidationError .因为每次单击“保存”时此值都表示为float ,所以我得到了PositiveIntegerFieldValidationError Is there any way to exclude this field from admin form validation or to send this field value multiplied by 100?有什么方法可以从管理表单验证中排除此字段或发送此字段值乘以 100? 截屏

If you setup a custom form you can manipulate the data entry of the form before actually save it to the DB, as well as determine the data type for the input.如果您设置自定义表单,您可以在将表单实际保存到数据库之前操作表单的数据条目,并确定输入的数据类型。

Edit: to do what i said you may as well end up removing the custom input and just doing the *100 thing on the custom form, anyway i think if you wanna ignore validations the anwser may be in a custom form.编辑:按照我说的做,你可能最终会删除自定义输入并只在自定义表单上执行 *100 操作,无论如何我认为如果你想忽略验证,则 anwser 可能是自定义表单。

I used to have custom form like this:我曾经有这样的自定义表单:

class ArticleModelForm(forms.ModelForm):
    project = forms.ModelChoiceField(
        queryset=Project.objects.order_by('title'),
        label="Proyecto",
        empty_label="Seleccionar proyecto",
        widget=forms.Select(
            attrs={
                "class": "basic-single form-control w-100",
                "id": "id-select-project-article"
            }))
    //lot more inputs

    def __init__(self, *args, **kwargs):
        super(ArticleModelForm, self).__init__(*args, **kwargs)
        self.fields['image'].widget.attrs['class'] = 'form-control-file'
        self.fields['image'].widget.attrs['accept'] = 'image/*'
        self.fields['file'].widget.attrs['class'] = 'form-control-file'
        self.fields['file'].widget.attrs['accept'] = 'application/pdf'
        for field in self.fields.values():
            field.error_messages = {
                'required':
                'El campo {fieldname} es requerido'.format(
                    fieldname=field.label)
            }

    def clean_file(self):
        file = self.cleaned_data.get("file")
        if not (file.name.endswith(".pdf")):
            raise forms.ValidationError(
                "Favor de ingresar un archivo en formato pdf")
        return file

    def clean_project(self):
        project = self.cleaned_data.get("project")
        user = self.cleaned_data.get("user")
        if project:
            projectObj = Project.objects.get(id=project.id)
            if not user in projectObj.participants.all():
                raise forms.ValidationError(
                    "Usted no es participante en este proyecto.")
        return project

    class Meta:
        model = Article
        fields = [
            'user', 'project', 'journal', 'authors', 'title', 'indexed',
            'indexInfo', 'arbitration', 'publicationYear', 'pages', 'file',
            'image', 'programTribute', 'academyTribute', 'eventPublication',
            'tags'
        ]

You can do your logic to *100 your number on the clean method for the field and return that value to be saved.您可以在该字段的 clean 方法上执行您的逻辑 *100 您的号码并返回要保存的值。

I don't remember excatly how to setup custom forms on admin but i know for sure you can do it.我不记得如何在管理员上设置自定义 forms,但我确信你可以做到。

I know i did this to setup custom usermodel and had to import my custom user forms on the admin.py of my users app:我知道我这样做是为了设置自定义用户模型,并且必须在我的用户应用程序的 admin.py 上导入我的自定义用户 forms:

from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin

from .forms import UserSapCreationForm, UserSapChangeForm //my custom forms 
from .models import UserSap

class UserSapAdmin(UserAdmin):
    add_form = UserSapCreationForm
    form = UserSapChangeForm
    model = UserSap
    verbose_name = 'Usuario Sap'
    list_display = (
        'email',
        'account',
        'rol',
        'is_staff',
        'is_active',
    )
    list_filter = (
        'rol',
        'is_staff',
        'is_active',
    )

    fieldsets = (
        ('Usuario Sap', {
            'fields': (
                'email',
                'password',
                'rol',
            )
        }),
        ('Informacion personal', {
            'fields': ('account', )
        }),
        ('Grupos', {
            'classes': ('wide', ),
            'fields': ('groups', )
        }),
        ('Permisos', {
            'classes': ('wide', ),
            'fields': ('user_permissions', )
        }),
        ('Login', {
            'fields': ('is_active', )
        }),
        ('Staff', {
            'fields': ('is_staff', )
        }),
    )
    """
    add_fieldsets = (
        ('add', {
            'classes': ('wide',),
            'fields': ('email', 'account', 'rol', 'password1', 'password2', 'is_staff', 'is_active')}
         ),
    )
"""
    ordering = ('email', )

    search_fields = ('email', )

    filter_horizontal = ()


admin.site.register(UserSap, UserSapAdmin)

sorry i can't develop a full answer for you case but hopefully this examples will help you start searching for solutions.抱歉,我无法为您的案例制定完整的答案,但希望这些示例能帮助您开始寻找解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM