Django:创建具有反向关系的嵌套对象 [英] Django: Creating Nested Objects with Reverse Relationship
问题描述
尝试创建具有反向关系的嵌套对象时遇到问题.
I have a problem while trying to create Nested object with a reverse relationship.
我正在尝试 POST
一个 Work
,但是在同一时间试图 POST
一个 Price
是一个 Work
子级.
I'm trying to POST
a Work
but at the SAME time trying to POST
a Price
which is a Work
child.
这是我的 work_model
:
from django.db import models
from django.contrib.auth import get_user_model
User = get_user_model()
from PIL import Image
class Work(models.Model):
user = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
name = models.CharField(max_length=200)
length = models.IntegerField(null=True)
width = models.IntegerField(null=True)
def save(self, *args, **kwargs):
super(Work, self).save(*args, **kwargs)
img = Image.open(self.image.path)
if img.height > 300 or img.width > 300:
output_size = (300, 300)
img.thumbnail(output_size)
img.save(self.image.path)
def __str__(self):
return "{}".format(self.id)
我的 price_model
:
from django.db import models
from .model_work import *
from .model_taxes import *
from djmoney.models.fields import MoneyField
class Price(models.Model):
work = models.OneToOneField(Work, on_delete=models.CASCADE, related_name='price')
price = MoneyField(max_digits=19, decimal_places=4, default_currency='USD', null=True)
taxes = models.ForeignKey(Taxes, null=True, on_delete=models.SET_NULL)
total = models.IntegerField(null=True)
def __str__(self):
return "{}".format(self.price)
还有我的 taxes_model
:
from django.db import models
class Taxes(models.Model):
tax_percentage = models.IntegerField(null=True)
tax_country = models.CharField(max_length=200, null=True)
tax_region = models.CharField(max_length=200, null=True)
def __str__(self):
return "{}".format(self.tax_country)
这是我的 work_serializer
:
from rest_framework import serializers
from ..models.model_work import Work
from .serializers_user import *
from .serializers_price import *
class WorkIndexSerializer(serializers.ModelSerializer):
"""
Serializer listing all Works models from DB
"""
user = UserIndexSerializer()
price = PriceDetailsSerializer(many=False)
class Meta:
model = Work
fields = [
'id',
'user',
'price',
'name',
'image',
'length',
'width'
]
class WorkCreateSerializer(serializers.ModelSerializer):
"""
Serializer to create a new Work model in DB
"""
price = PriceCreateSerializer(many=False)
class Meta:
model = Work
fields = [
'user',
'price',
'name',
'length',
'width'
]
def create(self, validated_data):
price = Price.objects.create(**validated_data)
work = Work.objects.create(**validated_data)
return work
class WorkDetailsSerializer(serializers.ModelSerializer):
"""
Serializer showing details of an Works model from DB
"""
user = UserIndexSerializer()
class Meta:
model = Work
fields = fields = [
'user',
'name',
'image',
'length',
'width'
]
我的 price_serializer
:
from rest_framework import serializers
from ..models.model_price import Price
from .serializers_work import *
class PriceIndexSerializer(serializers.ModelSerializer):
"""
Serializer showing Price information when called by Work GET serializers.
Not showing 'work' field to avoid loop.
"""
taxes = serializers.StringRelatedField(read_only=True)
class Meta:
model = Price
fields = [
'price',
'price_currency',
'taxes',
'total'
]
depth = 1
class PriceDetailsSerializer(serializers.ModelSerializer):
"""
Serializer showing Price information when called by Work GET serializers.
Not showing 'work' field to avoid loop.
"""
taxes = serializers.StringRelatedField(read_only=True)
class Meta:
model = Price
fields = [
'price',
'price_currency',
'taxes',
'total'
]
depth = 1
class PriceCreateSerializer(serializers.ModelSerializer):
"""
Serializer to create a new Price when new Work model is created in DB
"""
work = serializers.StringRelatedField(read_only=True)
taxes = serializers.StringRelatedField(read_only=True)
class Meta:
model = Price
fields = [
'work',
'price',
'price_currency',
'taxes',
'total'
]
def create(self, validated_data):
work = Work.objects.create(**validated_data)
price = Price.objects.create(**validated_data)
taxes = Taxes.objects.create(**validated_data)
return price
当我尝试与邮递员 POST
一个 Work
时:
And when I'm trying to POST
a Work
with Postman:
{
"user":"2",
"name":"work 20",
"price":
{
"price":20,
"price_currency":"EUR",
"taxes":1,
"total":32
},
"length":"50",
"width":"60"
}
我得到了错误:
TypeError at /works/
conversion from collections.OrderedDict to Decimal is not supported
当我尝试通过 POST
单独设置 Price
时:
And when I try to POST
a Price
by itself:
{
"work":20,
"price":20,
"price_currency":"EUR",
"taxes":1,
"total":32
}
我得到了错误:
ValueError at /prices/
Cannot assign "<Money: 20.0000 EUR>": "Work.price" must be a "Price" instance.
我找不到适用于我的案件的解决方案.
I can't find any solution working with my case.
我在做什么磨损或丢失?
What am I doing worng or missing?
感谢您的回复!
推荐答案
1. TypeError at /works/
conversion from collections.OrderedDict to Decimal is not supported
解决方案是传递嵌套的价格字典以创建价格模型,而不是整个数据:
The solution is to pass the nested price dictionary to create Price model instead of the whole data:
class WorkCreateSerializer(serializers.ModelSerializer):
price = PriceDetailsSerializer(many=False)
...
def create(self, validated_data):
price_data = validated_data.pop('price')
work = Work.objects.create(**validated_data)
price = Price.objects.create(**price_data)
return price
2.
ValueError at /prices/
Cannot assign "<Money: 20.0000 EUR>": "Work.price" must be a "Price" instance.
首先,在PriceCreateSerializer上更改工作字段,以便可以在validated_data中保存工作数据:
First, change work field on PriceCreateSerializer, so you can have work data in validated_data:
work = WorkDetailsSerializer(many=False)
然后:
def create(self, validated_data):
work_data = validated_data.pop('work')
work = Work.objects.create(**work_data)
price = Price.objects.create(**validated_data)
return price
这篇关于Django:创建具有反向关系的嵌套对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!