Django:一个模型,不同的形式和小部件?

时间:2016-04-29 15:04:38

标签: python django django-models django-forms

我尝试找到拥有多种内容类型字段的最佳方法。 到目前为止,我所做的是具有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)。

我试图找到最优雅的方式,所以欢迎任何帮助。

感谢阅读。

2 个答案:

答案 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