我刚开始使用Django REST框架,在保存外键方面遇到了困难。我有一个Merchant
模型和一个Phone
模型。Phone
有一个Merchant
的外键。当向POST
请求Merchant
时,我希望为请求中提供的数字创建Phone
对象。但是当我提供电话号码时,它会给出以下错误
对象不存在phone=0123456789。
我只想让它自己创建Phone
对象。下面是我使用的模型:
class Merchant(models.Model):
merchant_id = models.CharField(max_length=255)
name = models.CharField(max_length=255)
is_active = models.BooleanField(default=True)
class Meta:
managed = True
db_table = 'merchant'
# Managers
objects = models.Manager()
active = managers.ActiveManager()
class Phone(models.Model):
phone = models.CharField(max_length=255)
merchant = models.ForeignKey('merchant.Merchant',
related_name='phones',
blank=True,
null=True)
class Meta:
managed = True
db_table = 'phone'
下面是我使用它们的视图和序列化程序。
class MerchantSerializer(serializers.ModelSerializer):
phones = serializers.SlugRelatedField(
many=True,
slug_field='phone',
queryset=primitives.Phone.objects.all())
class Meta:
model = Merchant
fields = (
'merchant_id',
'name',
'is_active',
'phones',
)
class MerchantViewSet(viewsets.ModelViewSet):
queryset = Merchant.active.all()
serializer_class = MerchantSerializer
我的请求身体是这样的:
{
"merchant_id": "emp011",
"name": "Abhinav",
"is_active": true,
"phones": [
"0123456789",
"9876543210"
]
}
以下是我们的回应:
400个错误请求
{"phones":["Object with phone=0123456789 does not exist."]}
发布于 2015-01-18 08:15:26
与许多相关字段一样,Django REST框架提供的SlugRelatedField
被设计用于已经存在的对象。由于您正在寻找已经存在的引用对象,或者需要创建的对象,所以您将无法按原样使用它。
当新对象不存在时,您将需要一个自定义SlugRelatedField
来创建新对象。
class CreatableSlugRelatedField(serializers.SlugRelatedField):
def to_internal_value(self, data):
try:
return self.get_queryset().get_or_create(**{self.slug_field: data})[0]
except ObjectDoesNotExist:
self.fail('does_not_exist', slug_name=self.slug_field, value=smart_text(data))
except (TypeError, ValueError):
self.fail('invalid')
class MerchantSerializer(serializers.ModelSerializer):
phones = CreatableSlugRelatedField(
many=True,
slug_field='phone',
queryset=primitives.Phone.objects.all()
)
class Meta:
model = Merchant
fields = (
'merchant_id',
'name',
'is_active',
'phones',
)
通过切换到get_or_create
,如果电话号码对象还不存在,就会创建它。如果需要在模型上创建其他字段,则可能需要对此进行调整。
发布于 2020-01-08 17:53:12
在凯文回答的基础上,由于没有使用get_or_create
和[0]
,海事组织稍微干净了一点
class CreatableSlugRelatedField(serializers.SlugRelatedField):
def to_internal_value(self, data):
try:
return self.get_queryset().get(**{self.slug_field: data})
except ObjectDoesNotExist:
return self.get_queryset().create(**{self.slug_field: data}) # to create the object
except (TypeError, ValueError):
self.fail('invalid')
注意,相关对象中唯一需要的字段应该是段塞字段。
发布于 2015-01-18 05:04:07
您必须为对象Phone的phone字段指定一个值。如果希望在不指定字段电话值的情况下创建phone对象,则必须启用空字段和空白字段。
phone = models.CharField(max_length=255,null=true,blank=true)
如果仍然遇到问题,请确保post数据包含所需的字段。为此您可以使用ipdb。
https://stackoverflow.com/questions/28009829
复制相似问题