Django 动态小部件/表单字段表示
我有一个包含各种类型设置的表。我想在表单中以不同的方式显示和验证每个设置。例如,如果设置是针对整数或字符串。
这是我的模型
class Setting(models.Model):
SETTING_TYPES = (
(u'1', u'Decimal'),
(u'2', u'Integer'),
(u'3', u'String'),
)
type = models..CharField(max_length=2, choices=SETTING_TYPES)
name = models.CharField(max_length=50, unique=True)
value = models.CharField(max_length=200)
,因此,如果类型为 1,我想限制表单输入并验证我期望小数的事实。但如果类型是 3,我需要显示更大的输入表单并验证我期望一个字符串的事实。
我可以看到有可能做到这一点的几个地方是:
- 在自定义小部件中
- 通过重写 BaseModelFormSet 类来更改 init 上的字段属性(http://snippets.dzone.com/posts/show/7936)
- 通过使用自定义模板过滤器来评估类型是什么,然后通过自定义模板手动渲染表单对于该设置类型,
- 将类型和值一起存储在 jsonfield 中,并使用类似 http://www.huyng.com/archives/django-custom-form-widget-for-dictionary-and-tuple-key-value-pairs/ 661/ 在一个地方更改设置值的显示和验证。
使用选项 1,我不确定是否在“值”字段上使用自定义小部件,如果它能够访问'type' 字段来确定如何表示 'value'
我尝试了选项 2,虽然我可以访问表单元素,但我无法访问表单值来确定设置的类型(也许它们还没有绑定? )。我认为这条路线可能是最简单的,但我需要访问表单值..
class BaseSettingFormset(BaseModelFormSet):
def __init__(self, *args, **kwargs):
super(BaseSettingFormset, self).__init__(*args, **kwargs)
for form in self.forms:
# here i would access the type value and then change the widget propeties below
if form.fields['type'] == 3: # DOESN"T WORK :(
# change the widget and field properties
form.fields['value'].help_text='some text'
form.fields['value'].widget = CustomWidget() # or switch from decimal to string widgets..
def editProfile(request, strategy_id):
settingModelFormset = modelformset_factory(profile, formset=BaseSettingFormset)
... retrieve the values and show them..
(在发布此内容时,我确实找到了一篇文章,可以允许我在初始化期间绑定表单,因此可以访问该值,请参阅 django - 我怎样才能从自定义小部件内部访问表单字段)
选项 3 适用于显示字段,但不适用于验证任何数据。 我想我需要将它与选项 2 结合起来以在保存过程中验证它。
#Custom template filter
@register.filter(name='show_setting')
def show_setting(form):
setting = field_value(form['type']) # calls another function to retrieve value (works ok)
# render page using custom template that can alter the form to show a small field or text area etc.
# can also add js validations here.. (but no server validations)
if setting:
return render_to_string('setting-'+str(setting)+'.html', { 'form': form })
。
哪种方法最好(或者有其他方法),我该如何完成? 或者我是否以错误的方式处理这个问题,是否有更 djangoesc 的方法来解决我的问题?
I have a table that contains various types of settings. I want to display and validate each setting differently in a form. For example if the setting is for an integer or for a string.
This is my model
class Setting(models.Model):
SETTING_TYPES = (
(u'1', u'Decimal'),
(u'2', u'Integer'),
(u'3', u'String'),
)
type = models..CharField(max_length=2, choices=SETTING_TYPES)
name = models.CharField(max_length=50, unique=True)
value = models.CharField(max_length=200)
So if the type is 1 I want to restrict form entry and validate against the fact that I'm expecting a decimal. But if the type is 3, I need to show a bigger entry form and validate against the fact im expecting a string.
A few places I can see with possibility to do this is:
- In a custom widget
- By overriding the BaseModelFormSet class to change field properties on init (http://snippets.dzone.com/posts/show/7936)
- by using a custom template filter that will evaluate what the type is and then render the form manually via a custom template for that setting type
- store the type and value together in a jsonfield and use something like http://www.huyng.com/archives/django-custom-form-widget-for-dictionary-and-tuple-key-value-pairs/661/ to alter the display and validation of the setting value in one place..
With option 1, i'm not sure if I use a custom widget on the 'value' field if it will be able to access the 'type' field to determine how to represent the 'value'
I tried option 2, and while I could access the form elements, I could not access the form values to determine the type of the setting (maybe they weren't bound yet?). I think this route might be the simpliest but I will need access to form values..
class BaseSettingFormset(BaseModelFormSet):
def __init__(self, *args, **kwargs):
super(BaseSettingFormset, self).__init__(*args, **kwargs)
for form in self.forms:
# here i would access the type value and then change the widget propeties below
if form.fields['type'] == 3: # DOESN"T WORK :(
# change the widget and field properties
form.fields['value'].help_text='some text'
form.fields['value'].widget = CustomWidget() # or switch from decimal to string widgets..
def editProfile(request, strategy_id):
settingModelFormset = modelformset_factory(profile, formset=BaseSettingFormset)
... retrieve the values and show them..
(while posting this i did find a post that may allow me to bind the form during the init and therefore have access to the value, see django - how can I access the form field from inside a custom widget )
Option 3 works for displaying the field, but not for validating any data.
I think I would need to combine it with option 2 to validate it during save.
#Custom template filter
@register.filter(name='show_setting')
def show_setting(form):
setting = field_value(form['type']) # calls another function to retrieve value (works ok)
# render page using custom template that can alter the form to show a small field or text area etc.
# can also add js validations here.. (but no server validations)
if setting:
return render_to_string('setting-'+str(setting)+'.html', { 'form': form })
.
Which method would be best (or is there another way), and how do I complete it?
Or am I going about this the wrong way, is there a more djangoesc way to solve my problem?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我相信您正在寻找的是自定义验证器 传递到 CharField 构造函数中。
根据具体情况,另一个可能更优雅的解决方案是创建自己的字段类来扩展 CharField 并重载其验证代码。
I believe what you're looking for is a custom validator passed into the CharField constructor.
Another, possibly more elegant solution depending on the situation, would be to make your own field class that extends CharField and overloads its validation code.