1

In my app I have the following models: Products, Orders and OrderEntries

Orders are made out of OrderEntries, which represent each row in a shopping cart and are made out of the Product and the amount.

Now, what I want to do with my rest api is the ability to create Order objects by posting an array of OrderEntries to /api/orders, which would validate the array and then create new OrderEntries and the final Order object.

How would I do something like that in rest-framework?

EDIT: How my serializers look like now:

class ProductSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Product
        fields = ('pk', 'name', 'author', 'description', 'imageUrl', 'thumbUrl', 'price')


class OrderEntrySerializer(serializers.PrimaryKeyRelatedField, serializers.ModelSerializer):
    class Meta:
        model = OrderEntry
        fields = ("pk", "product", "amount")


class OrderSerializer(serializers.HyperlinkedModelSerializer):
    entries = OrderEntrySerializer(many=True, queryset=OrderEntry.objects.all())

    class Meta:
        model = Order
        fields = ("pk", "order_state", "entries")

Which would require me to post the following to /orders:

{
  "order_state": "string",
  "entries": [
    "string"
  ]
}

What I want is to just post the following, the state field would be set during creation:

{
   "entries": [
       ProductEntry,
       ...
    ]
}
1
  • Can you show something you've tried? Commented Dec 19, 2018 at 8:32

2 Answers 2

3

When you have such a complex relationship you always have to override the serializer's create method and take care of creating the objects. Checkout DRF Writable Nested Serializers. A simple solution in your case can be in this form:

class OrderSerializer(serializers.HyperlinkedModelSerializer):
    entries = OrderEntrySerializer(many=True, queryset=OrderEntry.objects.all())

    class Meta:
        model = Order
        fields = ("pk", "order_state", "entries")

    def create(self, validated_data):
        entries = validated_data.pop('entries', None)

        order = super().create(validated_data)

        for entry in entries:
            OrderEntry.objects.create(order=order, **entry)

        return order

Of course, this is a very simple solution since I don't have the full details of your models and their relationships but this should give you the idea of what needs to be done. Here, I am assuming that OrderEntry has a ForeignKey linked to Order

Sign up to request clarification or add additional context in comments.

2 Comments

you are correct in your assumption that they are linked via ForeignKey, that looks exactly like what I've been thinking off.
Good. You can try it out then and if the result is satisfactory, don't forget to accept the answer
0

You can try passing your order json objects as a Base64 string.

So, for example:

Let's say your order looks like below:

    {
       "name" : "Doughnut",
       "price" : "1.50"
    }

The Base64 encoded version of this would be something like:

ewogICAgICAgICAgICJuYW1lIiA6ICJEb3VnaG51dCIsCiAgICAgICAgICAgInByaWNlIiA6ICIxLjUwIgogICAgICAgIH0=

Now, you can decode this and retrieve order details.

Base64 encoding is a fairly common technique that's used in building web services.

Useful references:

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.