Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django Rest框架:如何在反序列化期间批量创建嵌套对象?_Python_Django_Django Rest Framework - Fatal编程技术网

Python Django Rest框架:如何在反序列化期间批量创建嵌套对象?

Python Django Rest框架:如何在反序列化期间批量创建嵌套对象?,python,django,django-rest-framework,Python,Django,Django Rest Framework,我有三种型号: class Customer(models.Model): name = models.CharField(max_length=30) class Order(models.Model): customer = models.ForeignKey(Customer,on_delete=models.CASCADE) class LineItem(models.Model): order = models.ForeignKey(Order,on_del

我有三种型号:

class Customer(models.Model):
    name = models.CharField(max_length=30)

class Order(models.Model):
    customer = models.ForeignKey(Customer,on_delete=models.CASCADE)

class LineItem(models.Model):
    order = models.ForeignKey(Order,on_delete=models.CASCADE)
    name = models.CharField(max_length=30)
这是我的测试:

class CreateOrdersTest(APITestCase):
    def setUp(self):
        self.TEST_SIZE = 10
        self.factory = APIRequestFactory()
        self._setup_source()
        self.data = self._build_data()

    def _setup_source(self):
        Customer.objects.create(name='test-customer')

    def _build_data(self):
        return [{'customer':'test-customer','lineitems':[{'name':'apples'},{'name':'oranges'}]} for x in range(self.TEST_SIZE)]

    def test_post_orders(self):

        request = self.factory.post('/create_orders',self.data)
        response = create_orders(request)
        response.render()
        self.assertEqual(response.status_code,status.HTTP_201_CREATED)
所以post对象看起来像

[{'customer': 'test-customer', 'lineitems': [{'name': 'apples'}, {'name': 'oranges'}]}, .... ] 
以下是序列化程序:

class BulkLineItemSerializer(serializers.ModelSerializer):
    def create(self,validated_data):
        lineitems = [LineItem(**validated_data) for item in validated_data]
        return LineItem.objects.bulk_create(**validated_data)

class LineItemSerializer(serializers.ModelSerializer):

    order = ModelObjectidField()

    def create(self,validated_data):
        return LineItem.objects.create(**validated_data)

    class Meta:
        model = LineItem
        list_serializer_class = BulkLineItemSerializer
        fields = ['name','order']

class BulkOrderSerializer(serializers.ListSerializer):
    def create(self,validated_data):
        orders = [Order(**item) for item in validated_data]
        return Order.objects.bulk_create(orders)

class OrderSerializer(serializers.ModelSerializer):

    customer = serializers.SlugRelatedField(slug_field='name',queryset=Customer.objects.all())

    def create(self,validated_data):
        return Order.objects.create(**validated_data)
    
    class Meta:
        model = Order
        fields = ['customer']
        list_serializer_class = BulkOrderSerializer
这是我用于order对象的ModelObjectedField

class ModelObjectidField(serializers.Field):

    def to_representation(self, value):
        return value.id

    def to_internal_value(self, data):
        return data
因为我将实际对象传递到字段中,就像,我直接返回它作为内部_值

最后是我的观点。这是如何将行项目与订单匹配的

@api_view(['POST'])
def create_orders(request):
    if request.method == 'POST':
        fixed_orders = []
        lineitems_matching = []
        offset = 0
        lineitems_data = []
        for order in request.data:
            order_lineitems = order['lineitems']
            lineitems_data.extend(order_lineitems)
            for item in order_lineitems:
                lineitems_matching.append(offset)
            offset += 1
            fixed_orders.append(order)
        orderSerializer = OrderSerializer(data=fixed_orders,many=True)
        if orderSerializer.is_valid():
            orders = orderSerializer.save()
            fixed_lineitems = []
            offset = 0
            for lineitem_data in lineitems_data:
                lineitem_data['order'] = orders[lineitems_matching[offset]]
                fixed_lineitems.append(lineitem_data)
                offset += 1
            lineItemSerializer = LineItemSerializer(data=fixed_lineitems, many=True) # this line is getting the error
            if lineItemSerializer.is_valid():
                lineItemSerializer.save()
                return Response(orderSerializer.data,status=status.HTTP_201_CREATED)
            return Response(lineItemSerializer.errors,status=status.HTTP_400_BAD_REQUEST)
        return Response(orderSerializer.errors,status=status.HTTP_400_BAD_REQUEST)
目前我遇到以下错误:

(venv) alexmarshall@Alexs-MacBook-Pro spicy % ./manage.py test NestedOrderTest
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
E
======================================================================
ERROR: test_post_orders (NestedOrderTest.tests.CreateOrdersTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/alexmarshall/src/GreenData/spicy/spicy/NestedOrderTest/tests.py", line 23, in test_post_orders
    response = create_orders(request)
  File "/Users/alexmarshall/src/GreenData/spicy/venv/lib/python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/Users/alexmarshall/src/GreenData/spicy/venv/lib/python3.8/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/Users/alexmarshall/src/GreenData/spicy/venv/lib/python3.8/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "/Users/alexmarshall/src/GreenData/spicy/venv/lib/python3.8/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/Users/alexmarshall/src/GreenData/spicy/venv/lib/python3.8/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/Users/alexmarshall/src/GreenData/spicy/venv/lib/python3.8/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/Users/alexmarshall/src/GreenData/spicy/venv/lib/python3.8/site-packages/rest_framework/decorators.py", line 50, in handler
    return func(*args, **kwargs)
  File "/Users/alexmarshall/src/GreenData/spicy/spicy/NestedOrderTest/views.py", line 31, in create_orders
    lineItemSerializer = LineItemSerializer(data=fixed_lineitems, many=True)
  File "/Users/alexmarshall/src/GreenData/spicy/venv/lib/python3.8/site-packages/rest_framework/serializers.py", line 121, in __new__
    return cls.many_init(*args, **kwargs)
  File "/Users/alexmarshall/src/GreenData/spicy/venv/lib/python3.8/site-packages/rest_framework/serializers.py", line 158, in many_init
    return list_serializer_class(*args, **list_kwargs)
  File "/Users/alexmarshall/src/GreenData/spicy/venv/lib/python3.8/site-packages/rest_framework/serializers.py", line 115, in __init__
    super().__init__(**kwargs)
TypeError: __init__() got an unexpected keyword argument 'child'

----------------------------------------------------------------------
Ran 1 test in 0.010s

FAILED (errors=1)
我认为问题在于我正在传递具有顺序本身的lineitem序列化程序数据。以下是fixed_lineitems数据的外观:

[{'name': 'apples', 'order': <Order: Order object (1)>}, ... ]  

查看
BulkLineItemSerializer
,它必须继承自
ListSerializer
。 需要使用
many=True处理传递列表

像这样:

类BulkLineItemSerializer(serializers.ListSerializer):
...

查看
BulkLineItemSerializer
,它必须继承自
ListSerializer
。 需要使用
many=True处理传递列表

像这样:

类BulkLineItemSerializer(serializers.ListSerializer):
...

你想要什么?是否为请求数据中的每个dict创建订单和行项目?你需要额外的逻辑吗?@kamilyrb假设有2000个订单,每个订单有4个订单。我想打两个数据库电话。2000份订单1份。另一个用于每个与订单关联的8000行项目。python代码显示了在尝试批量保存lineitem对象之前,如何手动将订单分配给这些对象。这说明了吗?你想要什么?是否为请求数据中的每个dict创建订单和行项目?你需要额外的逻辑吗?@kamilyrb假设有2000个订单,每个订单有4个订单。我想打两个数据库电话。2000份订单1份。另一个用于每个与订单关联的8000行项目。python代码显示了在尝试批量保存lineitem对象之前,如何手动将订单分配给这些对象。这说明了吗?谢谢!有了这些变化和我在编辑中显示的变化,我相信它又能工作了。我猜是有点输入错误,但我也不确定你是如何从回溯错误中发现的。谢谢!有了这些变化和我在编辑中显示的变化,我相信它又能工作了。我猜这有点输入错误,但我也不确定你是如何从回溯错误中发现的。
class BulkLineItemSerializer(serializers.ListSerializer):
    def create(self,validated_data):
        lineitems = [LineItem(**item) for item in validated_data]
        return LineItem.objects.bulk_create(lineitems)