Reputation: 119
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?
Upvotes: 3
Views: 2553
Reputation: 10919
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
Upvotes: 0
Reputation: 239240
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)
Upvotes: 3
Reputation: 50776
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())
Upvotes: 1