26👍
DRF does not support create
method for nested serializers. If you want to show related fields in an extended layout and not only with pks then you can override the to_representation
method instead of rewriting default mtm
field. You should also override a create
method, because of the third model in mtm
link:
class EquipmentSerializer(serializers.ModelSerializer):
class Meta:
model = Equipment
fields = '__all__'
def create(self, validated_data):
order = Order.objects.get(pk=validated_data.pop('event'))
instance = Equipment.objects.create(**validated_data)
Assignment.objects.create(Order=order, Equipment=instance)
return instance
def to_representation(self, instance):
representation = super(EquipmentSerializer, self).to_representation(instance)
representation['assigment'] = AssignmentSerializer(instance.assigment_set.all(), many=True).data
return representation
Now it’ll save mtm fields properly passing list of pks, like [1, 2, 3]
and for representation of that mtm related model, EquipmentSerializer
will use AssignmentSerializer
.
6👍
Maybe for most people who is having the same issue, this question is a quite long.
The short answer is that DRF does not support natively create
method for nested serializers. so what to do?
Simply overriding the default behaviour. Check out a full example in the Official DRF docs
- [Django]-Distributed task queues (Ex. Celery) vs crontab scripts
- [Django]-Deploying Django with gunicorn and nginx
- [Django]-What is the advantage of Class-Based views?
2👍
I had a similar problem but with the update()
method …
The solution was simple thanks to this thread: https://github.com/beda-software/drf-writable-nested/issues/104...
All I had to do was installing the library pip install drf-writable-nested
and import it:
from drf_writable_nested import WritableNestedModelSerializer
the code should look like this:
(credit to: https://github.com/Leonardoperrella)
–serializers.py–
from drf_writable_nested import WritableNestedModelSerializer
class ProductsSerializer(serializers.ModelSerializer):
class Meta:
model = Products
fields = ('name', 'code', 'price')
class VendorsSerializer(WritableNestedModelSerializer,
serializers.ModelSerializer):
products = ProductsSerializer(source='vendor', many=True)
class Meta:
model = Vendors
fields = ('name', 'cnpj', 'city', 'products')
–models.py–
class Vendors(models.Model):
name = models.CharField('Name', max_length=50)
cnpj = models.CharField('CNPJ', max_length=14, unique=True, validators=[validate_cnpj])
city = models.CharField('City', max_length=100, blank=True)
class Meta:
verbose_name = "Vendor"
verbose_name_plural = "Vendors"
def __str__(self):
return self.name
class Products(models.Model):
name = models.CharField('Name', max_length=60)
code = models.CharField('Code', max_length=13)
price = models.DecimalField('Price',
max_digits=15,
decimal_places=2,
default=0.00,
validators=[MinValueValidator(Decimal("0.01"))])
vendor = models.ForeignKey('Vendors', on_delete=models.CASCADE, related_name='vendor')
class Meta:
verbose_name = "Product"
verbose_name_plural = "Products"
def __str__(self):
return self.name
- [Django]-Access fields in Django intermediate model
- [Django]-Creating email templates with Django
- [Django]-Django 1.5 – How to use variables inside static tag
0👍
I think that the cause for error: JSON parse error - No JSON object could be decoded
is because you forgot to put .data
at the 2nd line from @Ivan Semochkin solution: representation['assigment'] = AssignmentSerializer(instance.assigment_set.all(), many=True).data
.
Thus I find out that I will stumble upon Keyword Error: 'event'
from line: representation = super(EquipmentSerializer, self).to_representation(instance)
since the EquipmentSeralizer object contain the intermediary assignment_set
instead of event
.
Here are the end result adapting from @Ivan Semochkin solution I do. Correct me if I’m wrong/inappropriate in practice.
class EquipmentSerializer(serializers.ModelSerializer):
class Meta:
model = Equipment
fields = '__all__'
def create(self, validated_data):
order = Order.objects.get(pk=validated_data.pop('assignment_set').get('id'))
instance = Equipment.objects.create(**validated_data)
Assignment.objects.create(Order=order, Equipment=Equipment)
return instance
def to_representation(self, instance):
representation = super(EquipmentSerializer, self).to_representation(instance)
representation['assigment'] = AssignmentSerializer(instance.assigment_set.all(), many=True).data
return representation
Please correct me if I’m wrong. I’m new to Django.
- [Django]-Django Static files 404
- [Django]-How can I use break and continue in Django templates?
- [Django]-Django REST Framework POST nested objects