我使用的是Django 2.0和Python 3.7。我有以下型号,一个被另一个用作ManyToMany。。。
class CoopTypeManager(models.Manager):
def get_by_natural_key(self, name):
return self.get_or_create(name=name)[0]
class CoopType(models.Model):
name = models.CharField(max_length=200, null=False, unique=True)
objects = CoopTypeManager()
...
class Coop(models.Model):
objects = CoopManager()
name = models.CharField(max_length=250, null=False)
types = models.ManyToManyField(CoopType)
address = AddressField(on_delete=models.CASCADE)
enabled = models.BooleanField(default=True, null=False)
phone = PhoneNumberField(null=True)
email = models.EmailField(null=True)
web_site = models.TextField()
我已经设置了这些序列化程序。。。
class CoopTypeField(serializers.PrimaryKeyRelatedField):
queryset = CoopType.objects
def to_internal_value(self, data):
if type(data) == dict:
cooptype, created = CoopType.objects.get_or_create(**data)
# Replace the dict with the ID of the newly obtained object
data = cooptype.pk
return super().to_internal_value(data)
...
class CoopTypeSerializer(serializers.ModelSerializer):
class Meta:
model = CoopType
fields = ['id', 'name']
def create(self, validated_data):
"""
Create and return a new `CoopType` instance, given the validated data.
"""
return CoopType.objects.create(**validated_data)
def update(self, instance, validated_data):
"""
Update and return an existing `CoopType` instance, given the validated data.
"""
instance.name = validated_data.get('name', instance.name)
instance.save()
return instance
...
class CoopSerializer(serializers.ModelSerializer):
types = CoopTypeSerializer(many=True)
address = AddressTypeField()
class Meta:
model = Coop
fields = ['id', 'name', 'types', 'address', 'phone', 'enabled', 'email', 'web_site']
extra_kwargs = {
'phone': {
'required': False,
'allow_blank': True
}
}
def to_representation(self, instance):
rep = super().to_representation(instance)
rep['types'] = CoopTypeSerializer(instance.types).data
rep['address'] = AddressSerializer(instance.address).data
return rep
def create(self, validated_data):
#"""
#Create and return a new `Snippet` instance, given the validated data.
#"""
coop_types = validated_data.pop('types', {})
instance = super().create(validated_data)
for item in coop_types:
coop_type, _ = CoopType.objects.get_or_create(**item)
instance.types.add(coop_type)
return instance
但是POST请求的有效载荷如下面的
{
"name": "7899",
"types": [
{"name": "Library"}
],
"address": {
"formatted": "222 W. Merchandise Mart Plaza, Suite 1212",
"locality": {
"name": "Chicago",
"postal_code": "60654",
"state": 19313
}
},
"enabled": true,
"phone": "7739441426",
"email": "myemail@msn.com",
"web_site": "http://www.1871.com/"
}
导致这些错误。
{"types":[{"name":["coop type with this name already exists."]}]}
如果类型名称已经存在。我如何调整我必须重复使用现有条目而不是尝试创建新条目?
编辑:要查看这个问题的实际情况,Git repo就在这里——https://github.com/chicommons/maps,这样你就可以运行
git clone https://github.com/chicommons/maps.git
cd maps
docker-compose up
然后运行测试脚本
sh web/scripts/test_post_req.sh
你试过这个吗:coop_type, _ = CoopType.objects.get_or_create(name=item['name'])