Reputation: 181
I am trying to insert data into my database (sqlLite3) using factory and faker.
This is my model:
class User(models.Model):
id = models.CharField(max_length=9, primary_key=True)
real_name = models.CharField(max_length=200)
tz = models.CharField(max_length=200)
Factory for the model:
class UserFactory(factory.django.DjangoModelFactory):
class Meta:
model = User
fake.add_provider(MyProvider)
real_name = factory.Faker('name')
id = ''.join(fake.random_letters(length=9)).upper()
tz = fake.timezone()
When I run UserFactory.create()
for the first time, User is added but when I run the second time in the same python shell or try to run UserFactory.create_batch(5)
, it gives me the following error:
django.db.utils.IntegrityError: UNIQUE constraint failed: activities_user.id
If I run it in a different terminal or exit from shell and run the same command again it runs fine.
Seems ''.join(fake.random_letters(length=9)).upper()
always returns same value. Even though I have used random_letters I wonder why this is happening.
I am new to using factory boy and faker. Please help me out on this. Let me know if I am missing anything.
Upvotes: 6
Views: 5134
Reputation: 181
Just found a solution. It was a simple thing! I have modified this line
id = ''.join(fake.random_letters(length=9)).upper()
to
id = factory.Sequence(lambda n: ''.join(fake.random_elements(elements=(string.ascii_uppercase + string.digits), length=9, unique=True)).upper())
and it worked!
Upvotes: 2
Reputation: 373
I think you have to add the provider outside of class, and the declare the field with the name of the function you want to run as an argument. See the example below (from factoryboy docs).
What is happening is, your code is running only once at the time of declaration of class and hence producing only 1 string every time.
factory.Faker.add_provider(SmileyProvider)
class FaceFactory(factory.Factory):
class Meta:
model = Face
smiley = factory.Faker('smiley')
So here SmileyProvider
will have a method named smiley
.
Upvotes: 1