21👍
I was dealing with similiar issue this week and I found out, that django rest framework 3 actually supports nested writable serialisation (http://www.django-rest-framework.org/topics/3.0-announcement/#serializers in subchapter Writable nested serialization.)
Im not sure if nested serialisers are writable be default, so I declared them:
ingredients = RecipeIngredientSerializer(many=True, read_only=False)
steps = RecipeStepSerializer(many=True, read_only=False)
and you should rewrite your create methon inside RecipeSerializer:
class RecipeSerializer(serializers.ModelSerializer):
ingredients = RecipeIngredientSerializer(many=True, read_only=False)
steps = RecipeStepSerializer(many=True, read_only=False)
class Meta:
model = Recipe
fields = (
'name', 'dish_type', 'cooking_time', 'steps', 'ingredients'
)
def create(self, validated_data):
ingredients_data = validated_data.pop('ingredients')
steps_data = validated_data.pop('steps')
recipe = Recipe.objects.create(**validated_data)
for ingredient in ingredients_data:
#any ingredient logic here
Ingredient.objects.create(recipe=recipe, **ingredient)
for step in steps_data:
#any step logic here
Step.objects.create(recipe=recipe, **step)
return recipe
if this structure Step.objects.create(recipe=recipe, **step) wont work, maybe you have to select data representeng each field separatly from steps_data / ingredients_data.
This is link to my earlier (realted) question/answer on stack: How to create multiple objects (related) with one request in DRF?
1👍
I think that I get the answer.
class RecetaSerializer(serializers.ModelSerializer):
ingredientes = IngredientesSerializer(many=True, partial=True)
autor = serializers.PrimaryKeyRelatedField(queryset=User.objects.all())
depth = 2
class Meta:
model = Receta
fields = ('url','pk','nombre','foto','sabias_que','ingredientes','pasos','fecha_publicacion','autor')
def to_internal_value(self,data):
data["fecha_publicacion"] = timezone.now()
ingredientes_data = data["ingredientes"]
for ingrediente in ingredientes_data:
alimento_data = ingrediente["alimento"]
if Alimento.objects.filter(codigo = alimento_data['codigo']).exists():
alimento = Alimento.objects.get(codigo= alimento_data['codigo'])
ingrediente["alimento"] = alimento
else:
alimento = Alimento(codigo = alimento_data['codigo'], nombre = alimento_data['nombre'])
alimento.save()
ingrediente["alimento"] = alimento
data["ingredientes"] = ingredientes_data
return data
def create(self, validated_data):
ingredientes_data = validated_data.pop('ingredientes')
receta_data = validated_data
usuario = User.objects.get(id = validated_data["autor"])
receta_data['autor'] = usuario
receta = Receta.objects.create(**validated_data)
for ingrediente in ingredientes_data:
alimento_data = ingrediente["alimento"]
ingrediente = Ingredientes(receta= receta, cantidad = ingrediente['cantidad'], unidad = ingrediente['unidad'], alimento = alimento_data)
ingrediente.save()
receta.save()
return receta
It’s important to override to_internal_value(). I had problems with the function is_valid(). So every change make in the function to_internal_value() is before the function is_valid()
- Has_permission() missing 1 required positional argument: 'view'
- Uwsgi: unrecognized option '–module=MyProject.wsgi:application'
- Django admin: use checkboxes in list view in list_filter()