django restframework — Сериализатор для создания отношений m2m

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

У меня есть сущность Contact и Product. Между ними стандартный м2м для likes.

Вот моя модель:

class Contact(models.Model):
    ...
    products_of_interest = models.ManyToManyField(Product, related_name="interested_contacts")

Мой сериализатор настолько прост, насколько это возможно:

class ContactSerializer(serializers.ModelSerializer):

    class Meta:
        model = Contact

Когда я перечисляю свои контакты через этот сериализатор, я получаю все свои контактные объекты с массивом идентификаторов продуктов — круто:

"products_of_interest": [
        1,
        2
    ]

Теперь, когда я хочу создать контакты и заполнить m2m, я получаю следующее (через мой почтальон Chrome и данные формы):

  • Отправить products_of_interest = 1 --> работает (!!!) но только для одного товара!
  • Отправить products_of_interest = [1,2] --> требуется pk, а не unicode
  • Отправить products_of_interest = 1;2 --> нужен pk, а не юникод
  • Отправить products_of_interest[0] = 1, products_of_interest[1] = 2 --> вообще ничего не делается

У меня есть некоторый опыт работы с сериализаторами, поэтому я подумал, может быть, мне нужно сказать сериализатору, что я хочу дать ему более одного продукта. Поэтому я добавил это в свой сериализатор:

products_of_interest = ProductSerializer(many=True, required=False, read_only=False)

Теперь я получаю эту ошибку:

«‹Контакт: ›» должно иметь значение для поля «контакт», прежде чем можно будет использовать эту связь «многие ко многим».

Я совсем потерялся сейчас. Что я могу сделать? Не может быть, что мне нужно переопределить стандартные rfw-функции для сохранения чертовски легкого m2m, не так ли?

Спасибо!

Рон


person Ron    schedule 10.09.2014    source источник
comment
Попробуйте использовать HyperLinkRelatedField. В последний раз, когда я сталкивался с подобной проблемой, я нашел этот ответ полезным.   -  person Nagkumar Arkalgud    schedule 10.09.2014


Ответы (1)


Какую версию Django и drf вы используете? Я не могу воспроизвести ваши ошибки, используя Django 1.7 и drf 2.4.2. Вот мой код:

модели.py

from django.db import models

class Product(models.Model):
    pass


class Contact(models.Model):
    products_of_interest = models.ManyToManyField(Product,
        related_name="interested_contacts")

сериализаторы.py

from .models import Contact
from rest_framework import serializers


class ContactSerializer(serializers.ModelSerializer):
    class Meta:
        model = Contact

просмотры.py

from rest_framework import viewsets
from .models import Contact
from .serializers import ContactSerializer

class ContactViewSet(viewsets.ModelViewSet):
    queryset = Contact.objects.all()
    serializer_class = ContactSerializer

urls.py

from django.conf.urls import include, url

from rest_framework import routers
from . import views

router = routers.DefaultRouter()
router.register(r'contacts', views.ContactViewSet, 'contacts')
urlpatterns = router.urls

urlpatterns = [
    url(r'^', include(router.urls)),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

./manage.py shell
>>> from m2m_test.models import Product
>>> for i in range(3): Product.objects.create()
...
<Product: Product object>
<Product: Product object>
<Product: Product object>
>>>

А затем в веб-интерфейсе по адресу http://localhost:8000/contacts/:

POST с формой необработанных данных: { "products_of_interest": [1, 2, 3]}

-> просто работает.

person ephes    schedule 10.09.2014
comment
спасибо пока! но дело в том, что я также отправляю файлы, поэтому мне нужны данные формы... есть идеи, что я могу с этим поделать? - person Ron; 10.09.2014
comment
Ну, у кого-то была похожая проблема некоторое время назад stackoverflow.com/questions/25291466/;). На самом деле невозможно отправить структурированные данные (списки вещей) в поля формы с кодировкой формы. Вы можете написать свой собственный синтаксический анализатор, но это затормозит веб-представление вашего API. Сейчас я использую разные конечные точки для файлов и данных. - person ephes; 10.09.2014