简体   繁体   中英

factory_boy extract original kwargs

I'm building a factory with factory_boy that generates a django model. I would like to see what arguments the user inputs inline. My factory itself looks like this

class SomeFactory(factory.django.DjangoModelFactory):

    name = factory.Sequence(lambda n: 'Instance #{}'.format(n))
    some_other_thing = factory.SubFactory(SomeOtherFactory)

    class Meta:
        model = SomeModel

Now the user could say s = SomeFactory() and it would work fine, but I want to detect if the user input their own argument. For instance, to tell if the user passed in their own name, as in s = SomeFactory(name='Matt')

What I've tried so far is

  • Writing my own __init__ function in the SomeFactory class
    • This gets mysteriously overwritten and is neither called when I call s = SomeFactory() , nor when I call s.__init__()
  • Same goes for overwriting the __new__ method
  • Overwriting the poorly named _adjust_kwargs
    • This gives me all fields as kwargs , not just the ones the user defined. For instance, calling s = SomeFactory(name='Matt') , I would get a kwargs dict with keys for name and some_other_thing , which makes it impossible to tell input their own argument or not
  • Overwriting _create
    • Still encounter the same problem with overwriting _adjust_kwargs , in that kwargs doesn't contain the original kwargs , but rather all of the arguments

I think a lot of the functionality I'm after is black-boxed inside of factory_boy 's StepBuilder (I suspect it's in the instantiate method) but I have no idea how to modify it to do what I want.

Does anyone have any thoughts on how to figure out which kwargs were set originally in the call to s = SomeFactory() ? Ie determine that if I said s = SomeFactory(name='Matt') , that the user manually set the name?

Thanks!

Update: I'm running django version 1.11.2 , factory_boy version 2.8.1 , and python version 3.5.2

You can override the create method to only get the user kwargs.

A full example would be something like this:

from django.contrib.auth.models import User
import factory


class UserFactory(factory.DjangoModelFactory):
    username = factory.Sequence(
        lambda n: 'test'
    )
    email = factory.Sequence(lambda n: 'user{0}@example.com'.format(n))

    class Meta:
        model = User

    @classmethod
    def create(cls, **kwargs):

        # here you'll only have the kwargs that were entered manually

        print(str(kwargs))

        return super(UserFactory, cls).create(**kwargs)

So when I call it:

In [2]: UserFactory(username='foobar')
{'username': 'foobar'}
Out[2]: <User: foobar>

If you want to catch kwargs for other build strategies than create , you would also need to do this for the stub and build method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM