Bastien
Bastien

Reputation: 1487

Django : handle post JSON requests

I need to handle some JSON data with django. I will receive this data :

{
    "user": 8,
    "orderDay": "2020-06-24",
    "deliveryDay": "2020-06-30",
    "deliveryAddress": "Place des Fêtes",
    "comment": "",
    "orderDetail": 
    [
        {
            "product": 2,
            "byProduct": 2,
            "quantity": 43
        },
        {
            "product": 3,
            "byProduct": 3,
            "quantity": 5
        }
    ]
}

I would like to save this data in 3 differents table: order and orderDetail. models.py:

class order(models.Model):
    user = models.ForeignKey(memberArea, on_delete=models.CASCADE)
    comment = models.TextField(null=True, blank=True)
    orderDay = models.DateTimeField(auto_now_add=True)
    deliveryDay = models.DateField()
    deliveryPlace = models.CharField(max_length=255)
    state = models.CharField(max_length=255)
    price = models.TextField(null=True, blank=True)
    response = models.TextField(null=True, blank=True)
...
class orderDetail(models.Model):
    order = models.ForeignKey(order, on_delete=models.CASCADE)
    product = models.ForeignKey(product, on_delete=models.CASCADE)
    byProduct = models.ManyToManyField(byProduct)
    quantity = models.CharField(max_length=255)
...
class byProduct(models.Model):
    product = models.ForeignKey(product, on_delete = models.CASCADE)
    name = models.CharField(max_length=255)
...
class product(models.Model):
    name = models.CharField(max_length=255)
    prix_uni = models.TextField(null=True, blank=True)
    prix_kg = models.TextField(null=True, blank=True)
    dispo = models.BooleanField(null=True, blank=True)
    category = models.ForeignKey(category, on_delete=models.CASCADE)
    redu = models.TextField(null=True, blank=True)

I don't find any good documentation about how to handle JSON data whith Django. Thanks by advance

UPDATE

I tried something like this: serializer.py:

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = product
        fields = '__all__'

class ByProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = byProduct
        fields = '__all__'

class orderDetailSerializer(serializers.ModelSerializer):

    order = serializers.PrimaryKeyRelatedField(many=False, queryset=order.objects.all())

    class Meta:
        model = orderDetail
        fields = '__all__'

class OrderSerializer(serializers.ModelSerializer):

    orderDetail = orderDetailSerializer(many=True)

    class Meta:
        model = order
        fields = ['user', 'comment', 'deliveryDay', 'deliveryAddress', 'orderDetail']

    def create(self, validated_data):
            order_detail_data = validated_data.pop('orderDetail')
            new_order = order.objects.create(**validated_data)
            new_order.save()
            for product in order_detail_data:
                order_detail = orderDetail.objects.create(**product)
                order_detail.order.add(new_order.id)
            
            return new_order

views.py:

@api_view(['POST'])
def order(request, format=None):
    if request.method == 'POST':
        serializer = OrderSerializer(data=request.data)
        data = {}
        if serializer.is_valid():
            serializer.save()
            data['response'] = "Your order went well"
            return Response(data)
        return Response(serializer.errors)

Upvotes: 0

Views: 468

Answers (1)

neferpitou
neferpitou

Reputation: 424

There are few changes you need to make.

  1. Change your data format:
{
    "user": 8,
    "orderDay": "2020-06-24",
    "deliveryDay": "2020-06-30",
    "deliveryAddress": "Place des Fêtes",
    "comment": "",
    "orderDetail": 
    [
        {
            "product": 2,
            "byProduct": [2],
            "quantity": 43
        },
        {
            "product": 3,
            "byProduct": [3],
            "quantity": 5
        }
    ]
}

byProduct is a ManyToMany field so it must have a list of products.

  1. In your orderDetailSerializer:
class orderDetailSerializer(serializers.ModelSerializer):

    class Meta:
        model = orderDetail
        fields = ['product', 'byProduct', 'quantity']

Take note, in fields I have not included order because in our data there is no such field, and hence the error, order field is required. It's simple because serializer will parse the data we are sending and if there is something missing it will notify us.

  1. Changes in orderSerializer:
class OrderSerializer(serializers.ModelSerializer):

    orderDetail = orderDetailSerializer(many=True)

    class Meta:
        model = order
        fields = ['user', 'comment', 'deliveryAddress', 'deliveryDay', 'orderDetail']

    def create(self, validated_data):
            order_detail_data = validated_data.pop('orderDetail')
            new_order = order.objects.create(**validated_data)
            # new_order.save()
            for product in order_detail_data:
                by_products = product.pop('byProduct')
                order_detail = orderDetail.objects.create(order=new_order, **product)
                order_detail.byProduct.set(by_products)
                order_detail.save()

            return new_order

Few things to notice, fields include orderDetail although it is not a part of order model, but in order to parse the data being passed we need to add such fields, if there are more. Inside create method byProduct is a ManyToMany field, so we will have to use set() method in order assign them, direct assignment is not allowed.

Upvotes: 1

Related Questions