Django: Как правильно использовать ManyToManyField с фабриками Factory Factory и сериализаторами? - PullRequest
0 голосов
/ 14 февраля 2019

Проблема

Я использую класс модели 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)

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

  • Django 1.11
  • Python 2.7.10

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

1 Ответ

0 голосов
/ 14 февраля 2019

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

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

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

...