我正在创建一个API,该API列出并保存交易。我的Transaction
模型具有FK到Category
模型。创建Transaction
时,我的目标是如果类别是新的,也要创建Category
。
我第一次创建交易时,它成功创建了新类别和交易。下次我尝试使用现有类别创建事务时,收到错误消息,指出该类别已存在。在我的Transaction
序列化程序中,添加了一个create方法,该方法应使用get_or_create
作为类别。但是,我在我的唯一字段上仍然遇到错误。我的期望是它将返回现有的Category
。
在有机会使用create
之前,似乎在Transaction
序列化程序中使用get_or_create
方法之前就抛出了错误。
型号:
class Category(models.Model):
name = models.CharField(max_length=128, null=False)
owner = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
created_time = models.DateTimeField(auto_now_add=True)
modified_time = models.DateTimeField(auto_now=True)
class Meta:
unique_together = ('name', 'owner')
class Transaction(models.Model):
date = models.DateField()
payee = models.CharField(max_length=256)
category = models.ForeignKey(Category,
related_name='category',
on_delete=models.CASCADE)
amount = MoneyField(max_digits=19,
decimal_places=2,
default_currency='USD')
created_time = models.DateTimeField(db_index=True,
auto_now_add=True)
modified_time = models.DateTimeField(auto_now=True)
序列化器:
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ('id', 'name', 'owner', 'created_time', 'modified_time')
class TransactionSerializer(serializers.ModelSerializer):
balance = serializers.DecimalField(
decimal_places=2, max_digits=19, read_only=True)
category = CategorySerializer(many=False, read_only=False)
class Meta:
model = Transaction
fields = ('id', 'date', 'payee', 'category',
'amount', 'balance', 'created_time', 'modified_time',
'is_cleared', 'paid_or_deposited')
def create(self, validated_data):
category_data = validated_data.pop('category')
category, created = Category.objects.get_or_create(**category_data)
transaction = Transaction.objects.create(category=category,
**validated_data)
return transaction
POST:
{
"date": "2018-12-19",
"payee": "Test",
"category": {"owner": 1, "name": "TEST"},
"amount": "-134"
}
错误:
{
"category": {
"non_field_errors": [
"The fields name, owner must make a unique set."
]
}
}
答案 0 :(得分:1)
您正确地认识到您无法使用create()
方法。
之所以会这样,是因为默认情况下,ModelSerializer
根据您的模型Meta.unique_together
的值https://www.django-rest-framework.org/api-guide/serializers/#modelserializer创建验证器
禁用这种类型的验证器的最简单方法是为序列化程序覆盖get_unique_together_validators
:
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ('id', 'name', 'owner', 'created_time', 'modified_time')
def get_unique_together_validators(self):
return []
另一种更干净的解决方案是覆盖Meta.validations
中的CategorySerializer
* :
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ('id', 'name', 'owner', 'created_time', 'modified_time')
validators = []
* 请注意,这将禁用来自模型的串行化器验证器unique_for_date
,unique_for_month
和unique_for_year