Имам 20+ MySQL таблици, prm_a
, prm_b
, ... с една и съща основна структура, но различни имена, и бих искал да ги асоциирам с класове на Django модел, без да пиша всеки един на ръка. И така, чувствайки се амбициозен, реших да опитам ръката си да използвам type()
като клас-фабрика:
Следните работи:
def get_model_meta_class(prm_name):
class Meta:
app_label = 'myapp'
setattr(Meta, 'db_table', 'prm_%s' % prm_name)
return Meta
prm_class_attrs = {
'foo': models.ForeignKey(Foo),
'val': models.FloatField(),
'err': models.FloatField(blank=True, null=True),
'source': models.ForeignKey(Source),
'__module__': __name__,
}
###
prm_a_attrs = prm_class_attrs.copy()
prm_a_attrs['Meta'] = get_model_meta_class('a')
Prm_a = type('Prm_a', (models.Model,), prm_a_attrs)
prm_b_attrs = prm_class_attrs.copy()
prm_b_attrs['Meta'] = get_model_meta_class('b')
Prm_b = type('Prm_b', (models.Model,), prm_b_attrs)
###
Но ако се опитам да генерирам моделните класове, както следва:
###
prms = ['a', 'b']
for prm_name in prms:
prm_class_name = 'Prm_%s' % prm_name
prm_class = type(prm_class_name, (models.Model,), prm_class_attrs)
setattr(prm_class, 'Meta', get_model_meta_class(prm_name))
globals()[prm_class_name] = prm_class
###
Получавам любопитно изключение на реда type()
(като се има предвид, че __module__
всъщност е в речника prm_class_attrs
):
File ".../models.py", line 168, in <module>
prm_class = type(prm_class_name, (models.Model,), prm_class_attrs)
File ".../lib/python2.7/site-packages/django/db/models/base.py", line 79, in __new__
module = attrs.pop('__module__')
KeyError: u'__module__'
Така че имам два въпроса: какво не е наред с моя втори подход и дали това изобщо е правилният начин за създаване на моите класови модели?
Добре - благодарение на @Anentropic виждам, че елементите в моя prm_class_attrs
речник се изваждат от Python, когато прави класовете. И сега го карам да работи, но само ако направя това:
attrs = prm_class_attrs.copy()
attrs['Meta'] = get_model_meta_class(prm_name)
prm_class = type(prm_class_name, (models.Model,), attrs)
не и ако задам класа Meta
като атрибут с
setattr(prm_class, 'Meta', get_model_meta_class(prm_name))
Наистина не знам защо е така, но поне сега работи.
prm_class_attrs.copy()
във вашияfor
цикъл, така че__modules__
излиза от dict при първата итерация - person Anentropic   schedule 24.11.2014__module__
! Този въпрос беше наистина полезен!! - person Brendan   schedule 26.09.2015