Я создаю модель Django на основе абстрактного класса модели AbstractAttr
и обычной модели (скажем, Foo
).Добавить динамически сгенерированную модель Model.py в проект Django
Я хочу, чтобы мой foo/models.py
выглядеть следующим образом:
from bar.models import Attrs
# ...
class Foo(models.Model):
....
attrs = Attrs()
В классе AttrS, который имитирует поле у меня есть contribute_to_class
, который генерирует требуемую модель, используя type()
. Сгенерированная модель c называется FooAttr.
Все работает. Если я мигрирую, я вижу, что FooAttr появляется в соответствующей таблице.
ЗА ИСКЛЮЧЕНИЕМ ОДНОГО ВЕЩИ.
Я хочу иметь возможность from foo.models import FooAttr
. Как-то мой сгенерированный класс FooAttr не связан с файлом models.py, в котором он сгенерирован.
Если я изменить models.py к этому:
class Foo(models.Model):
# ...
FooAttr = generate_foo_attr_class(...)
это работает, но это не то, что я хочу (например, это заставляет Дев угадать имя генерировать класс).
Является ли это возможным, определите класс, как в первом примере, и привяжите его к определенному mod.py модулю?
Проекта (пра-альфа) здесь (в разработке филиала): https://github.com/zostera/django-mav
Некоторые соответствующий код:
def create_model_attribute_class(model_class, class_name=None, related_name=None, meta=None):
"""
Generate a value class (derived from AbstractModelAttribute) for a given model class
:param model_class: The model to create a AbstractModelAttribute class for
:param class_name: The name of the AbstractModelAttribute class to generate
:param related_name: The related name
:return: A model derives from AbstractModelAttribute with an object pointing to model_class
"""
if model_class._meta.abstract:
# This can't be done, because `object = ForeignKey(model_class)` would fail.
raise TypeError("Can't create attrs for abstract class {0}".format(model_class.__name__))
# Define inner Meta class
if not meta:
meta = {}
meta['app_label'] = model_class._meta.app_label
meta['db_tablespace'] = model_class._meta.db_tablespace
meta['managed'] = model_class._meta.managed
meta['unique_together'] = list(meta.get('unique_together', [])) + [('attribute', 'object')]
meta.setdefault('db_table', '{0}_attr'.format(model_class._meta.db_table))
# The name of the class to generate
if class_name is None:
value_class_name = '{name}Attr'.format(name=model_class.__name__)
else:
value_class_name = class_name
# The related name to set
if related_name is None:
model_class_related_name = 'attrs'
else:
model_class_related_name = related_name
# Make a type for our class
value_class = type(
str(value_class_name),
(AbstractModelAttribute,),
dict(
# Set to same module as model_class
__module__=model_class.__module__,
# Add a foreign key to model_class
object=models.ForeignKey(
model_class,
related_name=model_class_related_name
),
# Add Meta class
Meta=type(
str('Meta'),
(object,),
meta
),
))
return value_class
class Attrs(object):
def contribute_to_class(self, cls, name):
# Called from django.db.models.base.ModelBase.__new__
mav_class = create_model_attribute_class(model_class=cls, related_name=name)
cls.ModelAttributeClass = mav_class
Можете ли вы разместить соответствующую часть (-ы) определения класса Attrs? – ryanmrubin
Отредактированный вопрос, добавлена ссылка на исходный код и запрошенный код inline. Спасибо, что пытался помочь мне. – dyve
Также я не слишком повешен в классе Attrs. Я попробовал решение декоратора, тот же эффект: класс генерируется, переносится и т. Д., Но он не привязан к моделям. – dyve