Django: MultiValueField and MultiWidget
Django's documentation doesn't do a very thorough job of explaining how to use MultiValueField and MultiWidget. I've tried dissecting the one implementation and haven't had good results. Would someone mind giving me a quick pointer in the right direction?
My example:
widgets.py
from django import forms
class TestMultiWidget(forms.MultiWidget):
def __init__(self, attrs=None):
widgets = (
forms.TextInput(attrs=attrs),
forms.TextInput(attrs=attrs),
)
super(TestMultiWidget, self).__init__(widgets, attrs)
def decompress(self, value):
if value:
return value.split(':::')[0:2]
return ['', '']
fields.py
from django import forms
from widgets import TestMultiWidget
class TestMultiField(forms.MultiValueField):
widget = TestMultiWidget
def __init__(self, *args, **kwargs):
fields = (
forms.CharField(),
forms.CharField(),
)
super(TestMultiField, self).__init__(fields, *args, **kwargs)
def compress(self, data_list):
if data_list:
return ':::'.join(data_list)
return ''
models.py
from django.db import models
from util.fields import TestMultiField
class Test(models.Model):
a = models.CharField(max_length=128)
b = TestMultiField()
c = models.CharField(max_length=128)
admin.py
from django.contrib import admin
from models import Test
admin.site.register(Test)
And the resulting admin.
Anybody have a clue what's happening here? My guess is that there's some unintended exception suppression happening, but I haven't been able to locate the so开发者_高级运维urce.
Thanks!
Please notice that django.forms.MultiValueField is a form field and not a model field (like django.db.models.CharField). Therefore, it is not treated as a model field in your Test model, and was not created in your database. (You can check it with ./manage.py sqlall myapp
).
Change your models.py to:
from django.db import models
from fields import TestMultiField
class TestMultiModelField(models.Field):
def formfield(self, **kwargs):
defaults = {'form_class': TestMultiField}
defaults.update(kwargs)
return super(TestMultiModelField, self).formfield(**defaults)
def get_internal_type(self):
return 'TextField'
class Test(models.Model):
a = models.CharField(max_length=128)
b = TestMultiModelField()
c = models.CharField(max_length=128)
drop your table (on linux/mac: ./manage.py sqlclear myapp | ./manage.py dbshell
) and syncdb to create your table, this time with column b. Check your admin now.
Explanation: To create a custom model field, follow this: https://docs.djangoproject.com/en/dev/howto/custom-model-fields/
The set the model field's matching form field, the formfield method was used.
(BTW, The "correct" way to design the model field is probably a bit different, using to_python and get_prep_value)
精彩评论