我有一个带有自定义modelchoicefield的模型表单。
class UserModelChoiceField(forms.ModelChoiceField):
def label_from_instance(self, obj):
return obj.get_full_name()
class TaskForm(forms.ModelForm):
originator = UserModelChoiceField(queryset=User.objects.all().order_by('first_name'),widget=forms.Select(attrs={'class':'form-control'}))
class Meta:
model = Task
fields = ['originator']
我的阅读建议以这种方式处理我的字段会覆盖模型中的任何信息(例如是否需要),因为它从我的定义中实例化它而不是增加模型的字段
似乎最小化我对这样的字段的更改我应该与init进行交互(见下文)
def __init__(self,*args, **kwargs):
super(TaskForm, self).__init__(*args, **kwargs)
self.fields['originator'].queryset=User.objects.all().order_by('first_name')
self.fields['originator'].widget = forms.Select(attrs={'class':'form-control'})
我理解如何执行查询集和小部件,假设上述内容是正确的。我的问题是如何使用该自定义选择域。此外,我甚至不确定这是否是这样做的方式,因为它似乎有点hacky。
答案 0 :(得分:1)
呃..我记得有这个问题而没有找到内置或惯用的解决方案。我没有提出比这个装饰更好的解决方案(是的,这是production code):
public class Example {
private int a;
public static final void main(String[] args) {
new Example().go();;
}
Example() {
this.a = 42;
}
void go() {
System.out.println(a); // 42, `a` is resolved to the instance field
int a = 67;
System.out.println(a); // 67, `a` is resolved to the local because it
// is "closer" to this code
System.out.println(this.a); // 42, because we qualified it
}
}
所以例如我会:
def model_generated(model):
"""Generate form fields from model fields
Purpose:
This decorator lets you have form field attributes like
`max_length` copied over from a model field while being DRY.
Usage:
Decorate a form class with this decorator and set MODEL_GENERATED_FIELDS
to a list of attribute names you would like to be generated.
Limitations:
- Currently, this decorator only supports CharFields.
"""
def decorator(cls):
for field_name in cls.MODEL_GENERATED_FIELDS:
model_field = model._meta.get_field(field_name)
model_field_type = type(model_field)
if model_field_type == django_models.CharField:
form_field_type = forms.CharField
attributes = { # (form_attribute, model_attribute, processor)
('label', 'verbose_name', None),
('max_length', None, None),
('min_length', None, None),
('required', 'blank', lambda value: not value),
}
else:
# (Maybe one day this decorator will support more types of fields.)
raise ValueError("Unknown type of model field: {}".format(model_field_type))
kwargs = {}
for form_attribute, model_attribute, processor in attributes:
if model_attribute is None:
model_attribute = form_attribute
if processor is None:
processor = lambda value: value
if hasattr(model_field, model_attribute):
kwargs[form_attribute] = processor(getattr(model_field, model_attribute))
form_field = form_field_type(**kwargs)
setattr(cls, field_name, form_field)
# Register field since we're monkey-patching
# (Django's meta-class hackery to detect fields only runs the first time the class is declared.)
cls.base_fields[field_name] = form_field
return cls
return decorator
和
class Team(models.Model):
name = models.CharField(max_length=30, unique=True,
verbose_name="Team Name")
passphrase = models.CharField(max_length=30,
verbose_name="Passphrase")
...
您可以根据自己的特定需求调整和扩展@model_generated(models.Team)
class TeamJoiningForm(forms.Form):
MODEL_GENERATED_FIELDS = ('name', 'passphrase')
...
装饰器。遗憾。