Пользовательское поле модели MultiInput в Django

Я пытаюсь создать пользовательское поле для объема, состоящее из 4 частей (длина, ширина, высота и единицы измерения). Я думаю, что расширение класса models.JSONField имеет наибольший смысл.

Вот что у меня есть на данный момент.

inventory/models.py

from django.db import models
from tpt.fields import VolumeField

class Measurement(models.Model):
    volumne = VolumeField()

tpt/fields.py

from django.db import models
from tpt import forms
    
class VolumeField(models.JSONField):
    description = 'Package volume field in 3 dimensions'
    
    def __init__(self, length=None, width=None, height=None, units=None, *args, **kwargs):
        
        self.widget_args = {
            "length": length,
            "width": width,
            "height": height,
            "unit_choices": units,
        }

        super(VolumeField, self).__init__(*args, **kwargs)        
        
    def formfield(self, **kwargs):
        defaults = {"form_class": forms.VolumeWidgetField}
        defaults.update(kwargs)
        defaults.update(self.widget_args)
        return super(VolumeField, self).formfield(**defaults)

tpt/forms.py

import json
from django import forms

class VolumeWidget(forms.widgets.MultiWidget):
    def __init__(self, attrs=None):
        widgets = [forms.NumberInput(),
                   forms.NumberInput(),
                   forms.NumberInput(),
                   forms.TextInput()]
        super(VolumeWidget, self).__init__(widgets, attrs)

    def decompress(self, value):
        if value:
            return json.loads(value)
        else:
            return [0, 0, 0, '']

class VolumeWidgetField(forms.fields.MultiValueField):
    widget = VolumeWidget

    def __init__(self, *args, **kwargs):
        list_fields = [forms.fields.CharField(max_length=8),
                       forms.fields.CharField(max_length=8),
                       forms.fields.CharField(max_length=8),
                       forms.fields.CharField(max_length=4)]
        super(VolumeWidgetField, self).__init__(list_fields, *args, **kwargs)

    def compress(self, values):                                                
        return json.dumps(values)

Я смог запустить сервер, но когда я пытаюсь добавить новую запись в модель измерений в Admin, я получаю эту ошибку:

Я пробовал расширить models.CharField для тестирования, но получаю ошибку CharFields must define a 'max_length' attribute., а когда я указываю max_length, то получаю результат, аналогичный JSONField, но с max_length вместо encode: TypeError: Field.__init__() got an unexpected keyword argument 'max_length'

Есть идеи, что я делаю не так?

Спасибо

После небольшого расследования я обнаружил, что причиной проблемы была передача kwargs обратно в класс VolumeWidgetField. Простое удаление этого элемента позволило коду работать так, как ожидалось.

Вот обновленный tpt/forms.py

import json
from django import forms

class VolumeWidget(forms.widgets.MultiWidget):
    def __init__(self, attrs=None):
        widgets = [forms.NumberInput(),
                   forms.NumberInput(),
                   forms.NumberInput(),
                   forms.TextInput()]
        super(VolumeWidget, self).__init__(widgets, attrs)

    def decompress(self, value):
        if value:
            return json.loads(value)
        else:
            return [0, 0, 0, '']

class VolumeWidgetField(forms.fields.MultiValueField):
    widget = VolumeWidget

    def __init__(self, *args, **kwargs):
        list_fields = [forms.fields.CharField(max_length=8),
                       forms.fields.CharField(max_length=8),
                       forms.fields.CharField(max_length=8),
                       forms.fields.CharField(max_length=4)]
        super(VolumeWidgetField, self).__init__(list_fields, *args)

    def compress(self, values):                                                
        return json.dumps(values)
Вернуться на верх