Сменщик классов Python - PullRequest
       19

Сменщик классов Python

4 голосов
/ 10 ноября 2010

Мне нужно объявление класса времени выполнения класса из базы данных.

Некоторым классам необходимо переопределить поле и переопределение.

models.py

class Staff(object):
    name = StringField( verbose_name = "Full name")
    age = IntegerField( verbose_name = "Age")

utils.py

def class_changer(class_path, field_key, new_Field):
    pass
    ?????? 
>>> class_changer("models.Staff", "gender", BooleanField()) # Add new field to Staff
>>> class_changer("models.Country", "name", StringField()) # Add new class with name field
>>> class_changer("models.Staff", "country", ForeignKey("Country")) # Add new field to Staff

результат

class Staff(object):
    name = StringField( verbose_name = "Full name")
    age = IntegerField( verbose_name = "Age")
    gender = BooleanField()
    country = ForeignKey("Country")

class Country(object):
    name = StringField()

Как реализовать class_changer?

Ответы [ 2 ]

4 голосов
/ 10 ноября 2010

вам нужна лучшая архитектура для этого, но в качестве исходного решения вы можете попробовать это,

In [12]: class a1(object):
   ...:     pass

In [13]: def class_changer(cls_path, attr, val):
   ....:     try:
   ....:         obj = eval(cls_path)
   ....:         setattr(obj, attr, val)
   ....:     except:
   ....:         raise 
   ....:     
In [14]: def getGender(self):
   ...:     return True


In [15]: class_changer('a1','getGender', getGender)

In [16]: a1().getGender()
Out[16]: True
1 голос
/ 10 ноября 2010

Первое добавление новых атрибутов в класс:

>>> class_changer("models.Staff", "gender", BooleanField()) # Add new field to Staff
>>> class_changer("models.Staff", "country", ForeignKey("Country")) # Add new field to Staff

Для этих двух, просто продолжайте и установите Staff напрямую:

models.Staff.gender = BooleanField()
models.Staff.country = ForeignKey("Country")

Или сделать его общим:

def add_to_class(cls, name, attr):
    setattr(cls, name, attr)

add_to_class(models.Staff, "gender", BooleanField())
add_to_class(models.Staff, "country", ForeignKey("Country"))

Во-вторых, создание нового класса:

>>> class_changer("models.Country", "name", StringField()) # Add new class with name field

Вы можете создать класс в функции и затем назначить его модулю:

def new_class(mod, name):
    class New(object): pass
    setattr(mod, name, New)

new_class(test, "Country")
add_to_class(test, "Country", StringField())

Я не уверен, что вы захотите объединить new_class и add_to_class, но я полагаю, вы могли бы сделать:

def create_if_needed_and_add_to_class(mod, clsname, attrname, value):
    if clsname not in dir(mod):
        new_class(mod, clsname)
    add_to_class(mod, attrname, value)

и, наконец, для вашего class_changer:

def class_changer(mod_clsname_string, attrname, value):
    modname, clsname = '.'.split(mod_clsname_string)
    create_if_needed_and_add_to_class(globals()[modname], clsname, attrname, value)

Редактировать: исправлено class_changer для использования locals() для поиска имени модуля, поскольку это строка, а не модуль.

Редактировать: упс, должно быть globals().

...