Chandana Deshmukh
Chandana Deshmukh

Reputation: 181

how to generate unique data in Django using factory and faker?

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

Answers (2)

Chandana Deshmukh
Chandana Deshmukh

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

neeraj9194
neeraj9194

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

Related Questions