title: Django: One model, different forms and widgets?
body: <p>I try to find the best way to have a field with multiple content types.
  What I've done so far is a Contact model with a contacttype CharField:</p>
  
  <pre><code>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()
  </code></pre>
  
  <p>My goal is to let the user add different contact informations, which'll be listed on the profile page, but with only one model.</p>
  
  <p>I was thinking about a class for each ModelForm:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Then, in my view, I would choose the correct form depending on the request argument (ex: /contact/add/email or /contact/add/phone).</p>
  
  <p>I'm trying to find the most elegant way to do this, so any help is welcome.</p>
  
  <p>Thanks for reading.</p>