Django: Как правильно использовать ManyToManyField с фабриками Factory Factory и сериализаторами?

Эта проблема

Я использую модельный класс Event который содержит необязательный ManyToManyField для другого класса модели, User (разные события могут иметь разных пользователей), с фабричным классом EventFactory (используя библиотеку Factory Boy) с сериализатором EventSerializer, Я полагаю, что следовал документации для изготовления и сериализации, но получаю сообщение об ошибке:

ValueError: "" должно иметь значение для поля "id", прежде чем можно будет использовать это отношение "многие ко многим".

Я знаю, что оба экземпляра модели должны быть созданы в ManyToMany перед их связыванием, но я не вижу, где даже происходит добавление!

Вопрос

Может кто-нибудь уточнить, как правильно использовать ManyToManyField с использованием моделей, фабрики и сериализаторов так, как я этого еще не делал?

Настройка

Вот мой код:

models.py

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

factories.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)

serializers.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',)

test.py

class EventTest(APITestCase):
@classmethod
def setUpTestData(cls):
    cls.user = User.objects.create_user(email='test@gmail.com',  
    password='password')

def test_post_create_event(self):
    factory = factories.EventFactory.build()
    serializer = serializers.EventSerializer(factory)

    # IMPORTANT: Calling 'serializer.data' is the exact place the error occurs!
    # This error does not occur when I remove the ManyToManyField
    res = self.post_api_call('/event/', serializer.data)

Информация о версии

  • Джанго 1.11
  • Python 2.7.10

Спасибо за любую помощь, которую вы можете оказать!

1 ответ

Решение

По поводу ошибки: похоже пропал id связано с использованием .build() вместо .create() (или просто EventFactory()). Первый не сохраняет модель, и поэтому он не получает id значение, в то время как последний делает (обратитесь к заводским документам и модельным документам).

Я подозреваю, что сериализатор все еще ожидает, что объект имеет idдаже если отношение "многие ко многим" является необязательным, потому что оно не может навязать потенциальные отношения без id,

Однако может быть более простое решение для реальной задачи. Вышеуказанный метод является способом генерации данных POST, передаваемых post_api_call(), Если вместо этого эти данные были созданы вручную, то и фабрика, и сериализатор становятся ненужными. Метод явных данных может быть даже лучше с точки зрения теста, потому что теперь вы можете видеть точные данные, которые должны привести к ожидаемому результату. Принимая во внимание, что при использовании метода фабрики и сериализатора это гораздо более очевидно в том, что фактически используется в тесте.

Другие вопросы по тегам