3

I need to make a model that has 15 similar fields (let's call them field_01, field_02, field_03, etc.). I also need these fields to be easily available (e.g. to be able to do things like obj.field_01). Because I wanted to get something off the ground really quickly, I just created them the stupid way:

class M (models.Model):
    ....
    field_01 = models.NullBooleanField()
    field_02 = models.NullBooleanField()
    ....

I searched online for a better way to do this. Some people say use setattr, but as far as I could tell from reading and trying some stuff out, this adds attributes to an instance of a class, not the class itself, which means that when I try to attach a model form to this model, it will not see the fields added with setattr. Then I tried overriding the __new__ function, which would allow me to add properties to a class before an instance of that class is created. But I wasn't able to figure out how to do this exactly.

So, what's a way to generate these fields without breaking South and model forms and without copy-paste?

phoenix
  • 7,988
  • 6
  • 39
  • 45
Ciprian
  • 119
  • 1
  • 1
  • 8

3 Answers3

3

It's hard to say definitively without a concrete example of what your doing, but generally, if you find yourself repeating a field, then it's a clear sign for a one-to-many or many-to-many relationship, instead:

One-to-Many

class Field(models.Model):
    m = models.ForeignKey(M, related_name='fields')
    field = models.NullBooleanField()

Many-to-Many

class Field(models.Model):
    field = models.NullBooleanField()

class M(models.Model):
    fields = models.ManyToManyField(Field)
Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • I ended up doing something like this. Thanks! – Ciprian Aug 13 '12 at 21:04
  • 1
    @ChrisPratt I am forever disappointed that you are not the actor Chris Pratt. At the small size your avatar looks like him, and the idea of an actor also having such high rep on a programming board seems cool. –  Jul 22 '15 at 02:14
1

Django models have an add_to_class method you could (ab)use for monkey-patching models the way you would like to do.

for i in range(1, 10):
    M.add_to_class('field_%s' % s, NullBooleanField())
Bernhard Vallant
  • 49,468
  • 20
  • 120
  • 148
0

It sounds like you are looking to have an EAV style database. You should try a library instead of rolling your own. To that end, Django EAV looks pretty awesome. https://github.com/mvpdev/django-eav

To read more about pros and cons of a bunch of libraries to accomplish this check out: https://stackoverflow.com/a/7934577/884453

Community
  • 1
  • 1
Francis Yaconiello
  • 10,829
  • 2
  • 35
  • 54