我正在向 Django (1.6.11) Rest Framework (3.0.5) 发送一个包含以下信息的 XML 文件(我无法控制该文件)。
<?xml version="1.0" encoding="utf-8"?>
<Company xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Invoices>
<Invoice>
<Id />
<Number>150</Number>
<Date>2012-11-20</Date>
<InvoiceItems>
<Item>
<Sku>MAT</Sku>
<Description>Example description</Description>
<Total>10</Total>
</Item>
<Item>
<Sku>RMS</Sku>
<Description>Example description 2</Description>
<Total>10</Total>
</Item>
</InvoiceItems>
<Carriage>
<Sku />
<UnitPrice>20</UnitPrice>
</Carriage>
<ItemsTotal>50</ItemsTotal>
</Invoice>
</Invoices>
</Company>
如何遍历这些项目 (Invoices>Invoice>InvoiceItems>Items>) 并保存链接到其 Invoice 模型的每个对象 (Item)?
models.py
class Invoice(models.Model):
id = models.CharField(primary_key=True,max_length=10)
invoice_date = models.DateTimeField()
total = models.DecimalField(max_digits=10, decimal_places=2, default=0)
items = models.ForeignKey('Item', blank=True, null=True, related_name='items')
carriage = models.ForeignKey('Carriage', blank=True, null=True, related_name='carriage')
class Item(models.Model):
item_sku = models.CharField(max_length=100, blank=True)
item_description = models.CharField(max_length=400, blank=True)
item_total = models.DecimalField(max_digits=10, decimal_places=2, default=0)
class Carriage(models.Model):
carriage_sku = models.CharField(max_length=100, blank=True)
carriage_price = models.DecimalField(max_digits=10, decimal_places=2, default=0)
views.py
@api_view(['POST'])
@parser_classes((XMLParser,))
def zynk_upload(request, format=None):
if request.method == 'POST':
data = request.data
serializer = InvoiceSerializer(data=data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
serializer.py
class InvoiceSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Invoice
fields = ('id', 'invoice_date', 'total', 'carriage','items')
def to_internal_value(self, data):
id = data['Invoices']['Invoice']['Number']
invoice_date = data['Invoices']['Invoice']['Date']
total = data['Invoices']['Invoice']['ItemsTotal']
carriage_sku = data['Invoices']['Invoice']['Carriage']['Sku']
carriage_price = data['Invoices']['Invoice']['Carriage']['UnitPrice']
item_sku = data['Invoices']['Invoice']['InvoiceItems']['Item']['Sku']
item_description = data['Invoices']['Invoice']['InvoiceItems']['Item']['Description']
item_total = data['Invoices']['Invoice']['InvoiceItems']['Item']['Total']
return {
'id': id,
'invoice_date': invoice_date,
'total': total,
'carriage': {
'carriage_sku': carriage_sku,
'carriage_price': carriage_price,
},
'items': {
'item_sku':item_sku,
'item_description': item_description,
'item_total': item_total,
},
}
def create(self, validated_data):
carriage_data = validated_data.pop('carriage')
carriage_id = Carriage.objects.create(**carriage_data)
items_data = validated_data.pop('items')
items_id = Item.objects.create(**items_data)
return Invoice.objects.create(carriage=carriage_id, items=items_id,**validated_data)
请您参考如下方法:
如果字段名称不同,我相信您可以通过类范围变量指定映射到/从名称:
class InvoiceSerializer(serializers.HyperlinkedModelSerializer):
my_xml_name = serializers.CharField(source='my_django_name')
[...]
class Meta:
[...]
fields = ([...], 'my_xml_name')
More documentation on explict field names can be found here.
