社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Django

使用django-admin表单中的多值字段和多小部件

boymeetscode • 4 年前 • 351 次点击  

首先,我在Windows和Django2.1.3上使用了python 3.7。

我正试图在django表的charfield中存储一系列数字。我还希望管理站点并排显示两个数字文本框,分别表示下限值和上限值。我有以下文件和Django代码:

轿车/车型.py

from django.db import models
from django.utils.translation import gettext_lazy as _

# Create your models here.


class Car(models.Model):

    class Meta:
        verbose_name = 'car'
        db_table = 'cars'
        verbose_name_plural = 'cars'

    make = models.CharField(_('manufacturer'), max_length=32)
    model = models.CharField(_('model'), max_length=24)
    msrp = models.CharField(_('suggested price'), max_length=11)

汽车/行政人员

from django.contrib import admin
from django.forms import ModelForm, MultiWidget, MultiValueField, NumberInput, IntegerField
from django.core.validators import MinValueValidator, MaxValueValidator, ValidationError

# Register your models here.
from .models import Car


class RangeWidget(MultiWidget):
    def __init__(self, *args, **kwargs):
        self.widgets = [NumberInput(), NumberInput()]
        super().__init__(self.widgets, *args, **kwargs)

    def decompress(self, value):
        if value:
            return value.split('/')
        return ['', '']

    def value_from_datadict(self, data, files, name):
        datalist = [
            widget.value_from_datadict(
                data, files, '{name}_{i}'.format(name=name, i=i)
            ) for i, widget in enumerate(self.widgets)
        ]
        try:
            v = '/'.join(datalist)
        except ValueError:
            return ''
        else:
            return v


class RangeField(MultiValueField):
    widget = RangeWidget

    def __init__(self, *args, **kwargs):
        error_messages = {
            'incomplete': 'Enter two numbers',
        }
        fields = (
            IntegerField(
                error_messages={
                    'incomplete': 'Enter a number between 1 and 99999.'
                },
                validators=[
                    MinValueValidator(limit_value=1, message='Field cannot be less than 1'),
                    MaxValueValidator(limit_value=999999, message='Field cannot be greater than 99999')
                ],
                required=True
            ),
            IntegerField(
                error_messages={
                    'incomplete': 'Enter a number between 1 and 99999 that is equal or greater than the lower limit.'
                },
                validators=[
                    MinValueValidator(limit_value=1, message='Field cannot be less than 1'),
                    MaxValueValidator(limit_value=999999, message='Field cannot be greater than 99999')
                ],
                required=True
            )
        )

        super().__init__(
            error_messages=error_messages,
            fields=fields,
            require_all_fields=True,
            **kwargs
        )

    def compress(self, data_list):
        return '/'.join(data_list)


class CarChangeForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['msrp'].widget.attrs.update({'class': 'range', 'min': 1, 'max': 99999})

    class Meta:
        model = Car
        fields = ['make', 'model']
        exclude = []
        widgets = {
            'msrp': RangeWidget
        }

    def clean(self):
        cleaned_data = super().clean()
        try:
            lower, higher = cleaned_data.get('msrp').split('-')
        except (AttributeError, KeyError):
            raise ValidationError(message='Provide both msrp values')

        if lower.isdigit() and higher.isdigit() and int(lower) > int(higher):
            self.add_error(
                'msrp',
                'The lower MSRP cannot be more than higher MSRP.'
            )
        else:
            cleaned_data['msrp_lower'] = lower
            cleaned_data['msrp_higher'] = higher
            return cleaned_data


class CarAdmin(admin.ModelAdmin):
    fields = [
        ('make', 'model',),
        'msrp',
    ]

    form = CarChangeForm

    list_display = ('make', 'model', 'msrp')


admin.site.register(Car, CarAdmin)

除了我在rangefield.fields下指定的验证器不验证表单,并且允许我输入负数并将字段保留为空之外,似乎一切工作正常。为什么Django不尊重或运行我添加到这些字段中的验证程序?唯一有效的验证是我在custom clean()方法中所做的验证,在该方法中,我确保下限不大于上限。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/38678
 
351 次点击  
文章 [ 1 ]  |  最新文章 4 年前