Django-rest-framework创建具有多对多关系的对象

时间:2017-05-08 17:16:15

标签: django django-rest-framework

我需要创建对象“Tag”,其中多对多关系附加到对象“任务”。我有这个代码,不明白为什么它不起作用。我看到错误无法将关键字'task'解析为字段。选择是:id,name,tags, 附: 我依靠这篇文章manyToMany with django rest framework

.models

class Tag(models.Model):
    name = models.CharField(max_length=200)
    def __str__(self):
        return "{}".format(self.name)

class Task(models.Model):
    name = models.CharField(max_length=200, blank=True)
    tags = models.ManyToManyField(Tag)
    def __str__(self):
        return "{}".format(self.name)

.views

class TagCreateView(generics.ListCreateAPIView):
    serializer_class = TagSerializer

    def get_queryset(self):
        queryset = Tag.objects.all()
        task_id = self.kwargs.get('task_id', None)
        if task_id is not None:
            queryset = queryset.filter(task=task_id)
        return queryset
    def perform_create(self, serializer):
        task_id = self.kwargs.get('task_id', None)
        try:
            tasks = Task.objects.get(task__id__exact=task_id)
        except Task.DoesNotExist:
            raise NotFound()
        serializer.save(tag=tasks)

.serielizers

class TagSerializer(serializers.ModelSerializer):
    class Meta:
        model = Tag
        fields = ('id', 'name','')

class TaskSerializer(serializers.ModelSerializer):
    tag = TagSerializer(many=True, read_only=True)
    class Meta:
        model = Task
        fields = ('id', 'name', 'tags')
        read_only_fields = ('tags')

.urls

urlpatterns = {
url(r'^todolists/(?P<task_id>[0-9]+)/tags', TagCreateView.as_view(), name="tags")}

2 个答案:

答案 0 :(得分:3)

您需要在序列化程序create方法中处理嵌套序列化程序;

如同:http://www.django-rest-framework.org/api-guide/serializers/#writing-create-methods-for-nested-representations

答案 1 :(得分:0)

如果您不希望在一个HTTP请求中创建中间记录和其他表记录。否则,您必须处理嵌套的representations

models.py

from django.db import models
import django.urls
import urllib

class Product(models.Model):
    name = models.CharField(max_length=255)

    def get_absolute_url(self):
        return django.urls.reverse('app:product', args=(self.pk,))

    def __str__(self):
        return self.name

class Size(models.Model):
    products = models.ManyToManyField(Product, through=ProductVariant,
        related_name='sizes', related_query_name='size')
    name = models.CharField(max_length=255)

    def __str__(self):
        return self.name

class ProductVariant(models.Model):
    product = models.ForeignKey(Product, on_delete=models.CASCADE,
        related_name='productvariants', related_query_name='productvariant')
    size = models.ForeignKey('Size', on_delete=models.CASCADE,
        related_name='productvariants', related_query_name='productvariant')

    class Meta:
        unique_together = ('product', 'size')

    def __str__(self):
        return str(self.product) + ': ' + str(self.size)

api.py

from rest_framework import routers, serializers, viewsets
from app import models

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Product
        fields = ('id', 'name')
        read_only_fields = ('id',)

class ProductViewSet(viewsets.ModelViewSet):
    queryset = models.Product.objects.all()
    serializer_class = ProductSerializer

class SizeSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Size
        fields = ('id', 'name')
        read_only_fields = ('id',)

class SizeViewSet(viewsets.ModelViewSet):
    queryset = models.Size.objects.all()
    serializer_class = SizeSerializer

class ProductVariantSerializer(serializers.ModelSerializer):
    product = serializers.PrimaryKeyRelatedField(
        queryset=models.Product.objects.all())
    size = serializers.PrimaryKeyRelatedField(
        queryset=models.Size.objects.all())
    class Meta:
        model = models.ProductVariant
        fields = ('id', 'product', 'size')
        read_only_fields = ('id',)

class ProductVariantViewSet(viewsets.ModelViewSet):
    queryset = models.ProductVariant.objects.all()
    serializer_class = ProductVariantSerializer

router = routers.DefaultRouter()
router.register(r'products', ProductViewSet)
router.register(r'sizes', SizeViewSet)
router.register(r'productvariants', ProductVariantViewSet)

api_urlpatterns = ([
    url('', include(router.urls)),
], 'api')
urlpatterns += [
    url(r'^api/', include(api_urlpatterns)),
]

之后您可以

POST /api/products/ {name: ...}
POST /api/sizes/ {name: ...}
POST /api/productvariants/ {product: productId, size: sizeId}