Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

factory_boy objects seem to lack primary keys

When I create factory_boy objects, the object doesn't appear to have a primary key and I'm not sure why. Here's my model and factory:

# models.py
from django.db import models
from django.contrib.auth.models import User

class UserProfile(models.Model):
    # UserProfile is a subset table of User.  They have a 1:1 relationship.
    user = models.ForeignKey(User, unique=True)
    gender = models.CharField(max_length=1)

# factories.py
import factory
from django.contrib.auth.models import User
from .models import UserProfile

class UserFactory(factory.Factory):
    FACTORY_FOR = User
    username = 'jdoe'

class UserProfileFactory(factory.Factory):
    FACTORY_FOR = UserProfile
    user = factory.lazy_attribute(lambda a: UserFactory())
    gender = 'M'

Now according to the factory_boy documentation on associations, if I create a User instance, I should get an 'id' field. However, I don't. This is what I get (in the interpreter):

>>> from app.factories import UserFactory, UserProfileFactory
>>> user = UserFactory()
>>> user.username  # This result is correct
'jdoe'
>>> user.id is None   # User should be 'saved' and so this should return False
True

Similarly:

>>> user_profile = UserProfileFactory()
>>> user_profile.gender   # This is OK
'M'
>>> user_profile.user     # This is OK
<User: jdoe>
>>> user_profile.id is None  # Why isn't this False?
True

The documentation says these user.id and user_profile.id commands should return 'False' instead of 'True' since I'm creating (as opposed to building) factory_boy instances. What am I missing here? Why am I not getting an 'id' value when I create these instances? It seems that the only way I can get an id is by explicitly creating an 'id' attribute in my factories. However, I don't see this done anywhere in the documentation so I don't think that's what you're supposed to do.

Thanks.

like image 469
Jim Avatar asked Sep 23 '13 15:09

Jim


2 Answers

For django support you need to use DjangoModelFactory:

https://factoryboy.readthedocs.org/en/latest/orms.html#the-djangomodelfactory-subclass

like image 161
mariodev Avatar answered Nov 17 '22 13:11

mariodev


For the sake of completeness, it's also worthwhile to note that in order to explicitly save a factory to the database, the documentation says you can use:

user = UserProfile.create()

which does the same thing as the following once you are using a subclass of DjangoModelFactory:

user = UserProfile()

Only when objects are saved to the database do they recieve PK's.

To create a factory and explicitly not save it to the database, use:

user = UserProfile.build()
like image 35
Jon Poler Avatar answered Nov 17 '22 14:11

Jon Poler