I need to create object "Tag" with relationship many-to-many attached to object "Task".I have this code and don't understand why it doesn't work. I see error Cannot resolve keyword 'task' into field. Choices are: id, name, tags,
P.S.
I relied on this post 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")}
You need to handle the nested serializers creation in the serializers create
method;
As in here: http://www.django-rest-framework.org/api-guide/serializers/#writing-create-methods-for-nested-representations
If you're not hung up on creating intermediate and other table records in one HTTP request. Otherwise you've got to handle nested 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)),
]
After that you can
POST /api/products/ {name: ...}
POST /api/sizes/ {name: ...}
POST /api/productvariants/ {product: productId, size: sizeId}