我尝试找到拥有多种内容类型字段的最佳方法。 到目前为止,我所做的是具有contacttype CharField的Contact模型:
class Contact(models.Model):
CONTACT_TYPES = (
('email', 'Email'),
('phone', 'Phone'),
('address', 'Address'),
('facebook', 'Facebook'),
('linkedin', 'LinkedIn'),
('youtube', 'Youtube'),
('twitter', 'Twitter'),
('google', 'Google'),
)
teammember = models.ForeignKey(TeamMember)
description = models.CharField(max_length=100, null=True)
contacttype = models.CharField(max_length=100, choices= CONTACT_TYPES, default='email')
contact = models.TextField()
我的目标是让用户添加不同的联系信息,这些信息将在个人资料页面上列出,但只有一个模型。
我在考虑每个ModelForm的一个类:
class ContactForm(ModelForm):
def __init__(self, data, *args, **kwargs):
super(ModelForm, self).__init__(data, *args, **kwargs)
self.contacttype = ""
class Meta:
model = Contact
fields = ['description', 'contact']
widgets = {'contact': TextInput()}
def clean_contacttype(self):
return self.contacttype
class ContactEmailForm(ContactForm):
def __init__(self, data, *args, **kwargs):
super(ContactForm, self).__init__(data, *args, **kwargs)
self.contacttype = "email"
class Meta(ContactForm.Meta):
model = Contact
fields = ['description', 'contact']
widgets = {'contact': EmailInput()}
class ContactPhoneForm(ContactForm):
def __init__(self, data, *args, **kwargs):
super(ContactForm, self).__init__(data, *args, **kwargs)
self.contacttype = "phone"
class Meta(ContactForm.Meta):
model = Contact
fields = ['description', 'contact']
widgets = {'contact': TextInput()}
def clean_contact(self):
cleaned_data = super(ContactForm, self).clean()
contact = cleaned_data.get("contact")
# Perform some phone number validations
return contact
然后,在我看来,我会根据请求参数选择正确的表单(例如:/ contact / add / email或/ contact / add / phone)。
我试图找到最优雅的方式,所以欢迎任何帮助。
感谢阅读。
答案 0 :(得分:0)
如果你想使用一个html文件,那么这就是解决方案之一。
class YourView(TemplateView):
template_name = 'your_template.html'
def get(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
if context['type'] == 'phone':
context['form'] = ContactPhoneForm
elif ...
如果您设置了视图,那么
<form action="{% url "your view" %}" enctype="multipart/form-data" method="POST">{% csrf_token %}
{% if form.contenttype == 'phone' %}
{% include "partials/contact_phone_form.html" with form=form %}
{% elif form.contenttype == 'email' %}
{% include "partials/contact_email_form.html" with form=form %}
{% else %}
do something.
{% endif %}
</form>
并且,contact_phone_form.html和contact_email_form看起来像
anything.
<input name='phone'>
anything.
此解决方案适用于一个模板,多种形式。
如果你想为特定表格做多模板,那么你可以使用它。
class YourView(TemplateView):
template_name = 'your_template.html'
def get(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
if context['type'] == 'phone':
template_name = 'phone_form_template.html'
elif context['type'] == 'email':
template_name = 'email_form_template.html'
...
答案 1 :(得分:0)
我会使用 forms.Form ,具体取决于请求参数,如:
/ contact / add /?type = email或/ contact / add /?type = phone
所以你可以使用它(不是测试代码):
class ContactForm(forms.Form):
def __init__(self, *args, **kwargs):
super(CreateUserquestionnaireForm, self).__init__(*args, **kwargs)
if "email" in self.data:
... do some thing like change contact type or widget
if "phone" in self.data:
... do some thing like change contact type or widget