Lett1
Lett1

Reputation: 385

Django rest framework, create model from array of other models

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,
       ...
    ]
}

Upvotes: 1

Views: 1053

Answers (2)

Ken4scholars
Ken4scholars

Reputation: 6296

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

Upvotes: 3

waqasgard
waqasgard

Reputation: 831

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:

Upvotes: 0

Related Questions