Stephen Lin
Stephen Lin

Reputation: 4912

How to dynamically set attributes to a class in models in Django?

I want to dynamically set attribute to models. Here is the way I did it.

# models.py
class pwr(models.Model):



    # test info
    tester = models.CharField(max_length=10)
    test_date = models.DateField(verbose_name='Test Date')
    test_summary = models.TextField(verbose_name='Test Summary')
    test_duration = models.CharField(max_length=20, verbose_name='Test Duration')


    for i in xrange(2):
        ii = str(i)



        test_result = 'test_result_' + ii
        test_com = 'test_comment_' + ii
        bug_level = 'bug_level_' + ii
        bug_id = 'bug_id_' + ii
        bug_sum = 'bug_summary_' + ii
        exec (test_result + "= models.CharField(max_length=20, verbose_name='Result', \
        choices=(\
        ('Pass', 'P'), \
        ('Fail', 'F'), \
        ('Not Test', 'N/T'), \
        ('Not Avaliable', 'N/A'), \
        ('Reference', 'Ref'), \
        ('Warn', 'W')\
        ))")
        exec (test_com + "= models.CharField(max_length=100,  verbose_name='Comment',  blank=True)")
        exec (bug_level + "= models.CharField(max_length=100,  verbose_name='Bug Level',  blank=True, \
                            choices=(('1', '1:Blocker'), \
                            ('2', '2:Critical'), \
                            ('3', '3:Major'), \
                            ('4', '4:Normal'), \
                            ('5', '5:Enhancement')))")
        exec (bug_id + "= models.CharField(max_length=10,  verbose_name='Bug ID',  blank=True)")
        exec (bug_sum + "= models.CharField(max_length=100,  verbose_name='Bug Summary',  blank=True)")

# When I tried to use setattr here, no 'test_attribute' field is added to table pwr in database        
setattr(pwr, 'test_attribute', models.CharField(max_length=10,  verbose_name='test attr',  blank=True))    

This seems really ugly.. Do you have any better solution for this? Thanks!!!

Upvotes: 1

Views: 3018

Answers (1)

Mikko Ohtamaa
Mikko Ohtamaa

Reputation: 83706

You cannot set it dynamically with setattr because you are dealing with Python descriptors, not attributes. This is because of the order of events when the module is imported and Python class ans descriptors put together.

Naturally, you can still do this in superious dynamic language like Python. But the solution for the problem needs different approach

  • You can use Python metaclasses and override __new__

  • See declared_attr in SQLAlchemy, its own way to solve this special case

Upvotes: 2

Related Questions