Question: I am using factory boy to generate data for my django application.

It is a tennis matches app which has player one and two as shown in below class. Either of it will be a winner which will be store in winner\_one field.

I am getting some third player name in this field instead of player one or two. That player is also present in table.

Please advise what would be the best way to fix this?

```
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

```

Answer: 
This one seems like a good use case of factory\_boy's post generation hook.

```
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])

```
The issue stems from the `random.choice([user_one, user_two])` declaration: that declaration is executed at module import time, not when running the factory.

At that point, both values are `factory.SubFactory(UserFactory)` — i.e a *recipe* for creating a new user.
Once `random.choice()` is called, it will return one of the *declarations*; your code is thus equivalent to:

```py
class MatchFactory(factory.django.DjangoModelFactory):
  ...
  player_one = factory.SubFactory(UserFactory)
  player_two = factory.SubFactory(UserFactory)
  winner_one = factory.SubFactory(UserFactory)

```

It picks 3 different users each time.

I would suggest going for the following pattern:

1. Add a "parameter" to decide which player should win;
2. Use that value to choose the right attribute:

```py
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
  )

```

With that pattern, you can also "choose" the winner when calling the factory:
`MatchFactory(player_one=some_player, player_two=some_player, winner=1)`.