Django:如何在Factory Boy Factories和序列化程序中正确使用ManyToManyField?

时间:2019-02-14 16:17:36

标签: django django-serializer manytomanyfield factory-boy

问题

我正在使用一个模型类Event,该模型类包含一个可选 ManyToManyField到另一个模型类User(不同事件可以具有不同的用户),并带有一个工厂类{ {1}}(使用Factory Boy库)和串行器EventFactory。我相信我已经按照文档进行了工厂制造和序列化,但是却收到错误消息:

  

ValueError:“ <事件:测试事件>”需要具有字段“ id”的值   在使用这种多对多关系之前。

我知道在链接它们之前必须在ManyToMany中创建这两个模型实例,但是我看不到添加的地方!

问题

有人可以阐明如何通过我尚未使用的模型,工厂男孩和序列化程序正确使用ManyToManyField吗?

设置

这是我的代码:

models.py

EventSerializer

factories.py

@python_2_unicode_compatible
class Event(CommonInfoModel):
    users = models.ManyToManyField(User, blank=True, related_name='events')
    # other basic fields...

serializers.py

class EventFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.Event

    @factory.post_generation
    def users(self, create, extracted, **kwargs):
        if not create:
            # Simple build, do nothing.
            return

        if extracted:
            # A list of users were passed in, use them
            # NOTE: This does not seem to be the problem. Setting a breakpoint                     
            # here, this part never even fires
            for users in extracted:
                self.users.add(users)

test.py

class EventSerializer(BaseModelSerializer):
    serialization_title = "Event"
    # UserSerializer is a very basic serializer, with no nested 
    # serializers
    users = UserSerializer(required=False, many=True)

    class Meta:
        model = Event
        exclude = ('id',)

版本信息

  • Django 1.11
  • Python 2.7.10

感谢您提供的任何帮助!

1 个答案:

答案 0 :(得分:1)

关于错误: 似乎丢失的id是由于使用.build()而不是.create()(或仅仅是EventFactory())引起的。前者不会保存模型,因此不会获得id值,而后者会得到(请参考factory docsmodel docs)。

我怀疑序列化程序仍然期望对象具有id,即使多对多关系是可选的,因为如果没有id,它就不能强制执行潜在的关系。

但是,对于实际任务可能会有更简单的解决方案。上面的方法是一种生成传递到post_api_call()的POST数据的方法。如果改为手动创建此数据,则不需要工厂和序列化程序。从测试角度来看,显式数据方法甚至可能更好,因为您现在可以看到必须产生预期结果的确切数据。而使用factory和serializer方法时,它在测试中实际使用的内容中要隐含得多。