Поле "Заводской мальчик" не получает ожидаемого значения
Я использую фабрику для генерации данных для моего приложения django.
Это приложение для теннисных матчей, в котором есть игрок один и два, как показано в классе ниже. Любой из них будет победителем, который будет храниться в поле winner_one.
Я получаю имя третьего игрока в этом поле вместо имени первого или второго игрока. Этот игрок также присутствует в таблице.
Посоветуйте, пожалуйста, как лучше всего это исправить?
class MatchFactory(factory.django.DjangoModelFactory):
class Meta:
model = Match
player_one = factory.SubFactory(UserFactory)
player_two = factory.SubFactory(UserFactory)
league = factory.Iterator(League.objects.all())
type = fuzzy.FuzzyChoice(Match.MATCH_CHOICES, getter=lambda c: c[0])
winner_one = random.choice([player_one, player_two])
start_date = fuzzy.FuzzyNaiveDateTime(
datetime.today() + relativedelta(months=1),
datetime.today() + relativedelta(months=3)
)
end_date = start_date
Этот кажется хорошим примером использования крючка для генерации постов от factory_boy.
class MatchFactory(factory.django.DjangoModelFactory):
class Meta:
model = Match
player_one = factory.SubFactory(UserFactory)
player_two = factory.SubFactory(UserFactory)
league = factory.Iterator(League.objects.all())
type = fuzzy.FuzzyChoice(Match.MATCH_CHOICES, getter=lambda c: c[0])
start_date = fuzzy.FuzzyNaiveDateTime(
datetime.today() + relativedelta(months=1),
datetime.today() + relativedelta(months=3)
)
end_date = start_date
@factory.post_generation
def winner_one(self, create, extracted, **kwargs):
if extracted:
self.winner_one = extracted
else:
self.winner_one = random.choice([self.player_one, self.player_two])
Проблема связана с объявлением random.choice([user_one, user_two])
: это объявление выполняется во время импорта модуля, а не во время работы фабрики.
В этот момент оба значения будут factory.SubFactory(UserFactory)
- т.е. рецепт для создания нового пользователя.
После вызова random.choice()
он вернет одно из деклараций; таким образом, ваш код эквивалентен:
class MatchFactory(factory.django.DjangoModelFactory):
...
player_one = factory.SubFactory(UserFactory)
player_two = factory.SubFactory(UserFactory)
winner_one = factory.SubFactory(UserFactory)
Каждый раз он выбирает 3 разных пользователей.
Я бы предложил следующий шаблон:
- Добавьте "параметр", чтобы решить, какой игрок должен выиграть;
- Используйте это значение для выбора нужного атрибута:
class MatchFactory(factory.django.DjangoModelFactory):
class Meta:
model = Match
class Params:
# Decide who the winner is; that field won't be passed to the `Match` model.
winner = factory.fuzzy.FuzzyChoice([1, 2])
player_one = factory.SubFactory(UserFactory)
player_two = factory.SubFactory(UserFactory)
winner_one = factory.LazyAttribute(
lambda o: o.player_one if o.winner == 1 else o.player_two
)
С помощью этого шаблона вы также можете "выбрать" победителя при вызове фабрики:
MatchFactory(player_one=some_player, player_two=some_player, winner=1)
.