title: Django dynamic model fields
body: <p>I'm working on a <strong>multi-tenanted</strong> application in which some users can define their own data fields (via the admin) to collect additional data in forms and report on the data.  The latter bit makes JSONField not a great option, so instead I have the following solution:</p>
  
  <pre><code>class CustomDataField(models.Model):
      """
      Abstract specification for arbitrary data fields.
      Not used for holding data itself, but metadata about the fields.
      """
      site = models.ForeignKey(Site, default=settings.SITE_ID)
      name = models.CharField(max_length=64)
  
      class Meta:
          abstract = True
  
  class CustomDataValue(models.Model):
      """
      Abstract specification for arbitrary data.
      """
      value = models.CharField(max_length=1024)
  
      class Meta:
          abstract = True
  </code></pre>
  
  <p>Note how CustomDataField has a ForeignKey to Site - each Site will have a different set of custom data fields, but use the same database.
  Then the various concrete data fields can be defined as:</p>
  
  <pre><code>class UserCustomDataField(CustomDataField):
      pass
  
  class UserCustomDataValue(CustomDataValue):
      custom_field = models.ForeignKey(UserCustomDataField)
      user = models.ForeignKey(User, related_name='custom_data')
  
      class Meta:
          unique_together=(('user','custom_field'),)
  </code></pre>
  
  <p>This leads to the following use:</p>
  
  <pre><code>custom_field = UserCustomDataField.objects.create(name='zodiac', site=my_site) #probably created in the admin
  user = User.objects.create(username='foo')
  user_sign = UserCustomDataValue(custom_field=custom_field, user=user, data='Libra')
  user.custom_data.add(user_sign) #actually, what does this even do?
  </code></pre>
  
  <p>But this feels very clunky, particularly with the need to manually create the related data and associate it with the concrete model.  Is there a better approach?  </p>
  
  <p>Options that have been pre-emptively discarded:</p>
  
  <ul>
  <li>Custom SQL to modify tables on-the-fly.  Partly because this won't scale and partly because it's too much of a hack.</li>
  <li>Schema-less solutions like NoSQL.  I have nothing against them, but they're still not a good fit.  Ultimately this data <strong>is</strong> typed, and the possibility exists of using a third-party reporting application.</li>
  <li>JSONField, as listed above, as it's not going to work well with queries.</li>
  </ul>