Это ответ Xelnor, но исправляет ошибку так, что создается только один function_instantiation
, а не по одному для каждого parameter
/parameter_setting
пары.
class FunctionFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.Function
name = factory.Sequence(lambda n: "Function %d" % n)
class FunctionParameterFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.FunctionParameter
function = factory.SubFactory(FunctionFactory)
class FunctionInstantiationFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.FunctionInstantiation
function = factory.SubFactory(FunctionFactory)
class ParameterSettingFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.ParameterSetting
function_instantiation = factory.SubFactory(FunctionInstantiationFactory)
function_parameter = factory.SubFactory(FunctionParameterFactory,
function=factory.SelfAttribute('..function_instantiation.function'))
class FunctionToParameterSettingsFactory(FunctionInstantiationFactory):
class Meta:
model = models.FunctionInstantiation
# This overrides the function_instantiation created inside
# ParameterSettingFactory, which then overrides the Function creation,
# with the SelfAttribute('..function_instantiation.function') syntax.
parameter_setting_1 = factory.RelatedFactory(ParameterSettingFactory,
'function_instantiation')
parameter_setting_2 = factory.RelatedFactory(ParameterSettingFactory,
'function_instantiation')
Ниже демонстрирует решения нескольких других проблем, кто использует эту модель, вероятно, столкнуться, например, перекрывая ценности объектов, связанных с, а также ссылки на другие таблицы, которые сами связаны между собой. Он в значительной степени опирается на методы, которые Xelnor представил в своем ответе.
class FunctionFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.Function
name = factory.Sequence(lambda n: "Function %d" % n)
class FunctionParameterFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.FunctionParameter
name = factory.Sequence(lambda n: "Function %d" % n)
function = factory.SubFactory(FunctionFactory)
class ParameterSettingFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.ParameterSetting
name = factory.Sequence(lambda n: "Function %d" % n)
function_instantiation = factory.SubFactory(FunctionInstantiationFactory)
function_parameter = factory.SubFactory(FunctionParameterFactory,
function=factory.SelfAttribute('..function_instantiation.function'))
class DatasetAnd2ColumnsFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.Function
dataset = factory.SubFactory(DatasetFactory,
name=factory.Sequence(lambda n: "Custom dataset %d" % n))
column_1 = factory.SubFactory(ColumnFactory, dataset=dataset,
name=factory.Sequence(lambda n: "Column 1 %d" % n))
column_2 = factory.SubFactory(ColumnFactory, dataset=dataset,
name=factory.Sequence(lambda n: "Column 2 %d" % n))
# I found it neater not to inherit in the end, due to needing quite a lot of
# additional complexity not included in my original question.
class FunctionToParameterSettingsFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.FunctionInstantiation
name = factory.Sequence(lambda n: "Custom instantiation name %d" % n)
# You can call Sequence to pass values to SubFactories
function = factory.SubFactory(FunctionFactory,
name=factory.Sequence(lambda n: "Custom function %d" % n))
parameter_setting_1 = factory.RelatedFactory(ParameterSettingFactory,
'function_instantiation',
# Note the __ syntax for override values for nested objects:
parameter__name='Parameter 1',
name='Parameter Setting 1')
# Possible to use Sequence here too, and makes looking at data easier
parameter_setting_2 = factory.RelatedFactory(ParameterSettingFactory,
'function_instantiation',
parameter__name=factory.Sequence(lambda n: "Param 1 for fn %d" % n),
name=factory.Sequence(lambda n: "Param Setting 1 for fn %d" % n))
Теперь мне нужно создать набор данных с некоторыми столбцами данных и объединить записи параметров с этими столбцами. Чтобы сделать это, это идет в конце FunctionToParameterSettingsFactory
:
@factory.post_generation
def post(self, create, extracted, **kwargs):
if not create:
return
dataset = DatasetAnd2ColumnsFactory()
column_ids_by_name =
dict((column.name, column.id) for column in dataset.column_set.all())
# self is the `FunctioInstantiation` Django object just created by the `FunctionToParameterSettingsFactory`
for parameter_setting in self.parametersetting_set.all():
if parameter_setting.name == 'age_in':
parameter_setting.column_id = column_ids_by_name['Age']
parameter_setting.save()
elif parameter_setting.name == 'income_in':
parameter_setting.column_id = column_ids_by_name['Income']
parameter_setting.save()
Это правда, немного Hacky. Я пробовал пропустить column=column_1
в вызовах RelatedFactory, но это вызвало создание нескольких наборов данных, причем каждый столбец был связан с другим.Я пробовал все виды акробатики с помощью SelfAttribute и LazyAttribute, но вы не можете использовать их в вызове RelatedFactory, и вы не можете создать что-то с SubFactory (SelfAttribute()), а затем передать его в функцию «СвязанныйFactory», поскольку это нарушает SelfAttribute (см. my other question).
В моем реальном коде у меня было еще несколько моделей с внешним ключом для набора данных, и все это было хорошо связано.
Мои правки были rej Извините, извините @ Xelnor, я пытался сохранить ответ с вами. – Chris
В последнем примере кода есть ошибка. 'dataset' повторно создается так, что' column_1' и 'column_2' получают разные наборы данных (оба с переопределенным полем' name'). Если я создаю 'column_3' с' dataset = factory.LazyAttribute (lambda col: col.factory_parent.dataset) ', он отлично работает. Если я затем добавлю 'column_3' к вызову' ParameterSettingFactory', я получаю 'AttributeError: набор данных параметров неизвестен. ', А factory_boy находит только локаторы ParameterSettingFactory и no factory_parent. – Chris
Я решил вышеупомянутую проблему [описанную здесь] (http://stackoverflow.com/posts/33110180/edit) и обновил ответ. – Chris