Django 在使用外键引用保存序列化程序时失败
Django fails when saving a serializer with foreign key references
所以我有一个带有一个外键引用的模型,它在几周内都运行良好。我最终不得不向模型添加另一个外键引用,现在我无法使用序列化程序保存任何记录。我应该提到我正在使用 Django 2.1。
这是我正在使用的模型(为简单起见删除了一些字段):
class Finding(models.Model):
finding_id = models.IntegerField(null=False, blank=False, primary_key=True, db_index=True)
name = models.CharField(null=True, blank=True, max_length=255)
web_app = models.ForeignKey(WebApplication, on_delete=models.CASCADE)
q_id = models.ForeignKey(StagingQkb, on_delete=models.CASCADE)
新外键是 q_id 字段。之前这只是一个普通的 int。我实际上已经吹走了旧的 table 而新的仍然完全是空的,所以我知道这不是现有数据的问题(带有外键的 tables 仍然完好无损)。之前保存Findings的时候,我会直接给出'web_app'的WebApplication对象的PK。据我所知,这仍然有效。 'q_id' 字段,当以相同方式插入时,抱怨它需要一个 int/string/bytes 而不是 StagingQkb 对象。好吧,我没有给它一个 StagingQkb 对象,所以给了它什么!
这是序列化程序:
class FindingSerializer(serializers.ModelSerializer):
class Meta:
model = Finding
fields = '__all__'
我提供给序列化程序的数据如下所示:
data = {'finding_id': 5514989,
'name': 'Sample-Name',
'q_id': 12345,
'web_app': 67890}
当我将数据插入序列化程序时,我正在执行以下操作:
>>> fs = FindingSerializer(data=data)
>>> fs.is_valid()
True
>>> fs.save()
我在 运行 上面的代码之后得到的错误如下所示:
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "/opt/oss/python35/lib/python3.5/site-packages/rest_framework/serializers.py", line 214, in save
self.instance = self.create(validated_data)
File "/opt/oss/python35/lib/python3.5/site-packages/rest_framework/serializers.py", line 959, in create
raise TypeError(msg)
TypeError: Got a `TypeError` when calling `Finding.objects.create()`. This may be because you have a writable field on the serializer class that is not a valid argument to `Finding.objects.create()`. You may need to make the field read-only, or override the FindingSerializer.create() method to handle this correctly.
Original exception was:
Traceback (most recent call last):
File "/opt/oss/python35/lib/python3.5/site-packages/rest_framework/serializers.py", line 940, in create
instance = ModelClass._default_manager.create(**validated_data)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/query.py", line 413, in create
obj.save(force_insert=True, using=self.db)
File "/home/dpz3w0q/AutonomousPrimeD/autonomousprimed/Finding/models.py", line 83, in save
q_id=self.q_id)
File "/home/dpz3w0q/AutonomousPrimeD/autonomousprimed/Finding/models.py", line 173, in evaluate
if ScoreMatrix.objects.filter(q_id=q_id).count() > 0:
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/query.py", line 844, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/query.py", line 862, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/sql/query.py", line 1263, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/sql/query.py", line 1287, in _add_q
split_subq=split_subq,
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/sql/query.py", line 1225, in build_filter
condition = self.build_lookup(lookups, col, value)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/sql/query.py", line 1096, in build_lookup
lookup = lookup_class(lhs, rhs)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/lookups.py", line 20, in __init__
self.rhs = self.get_prep_lookup()
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/lookups.py", line 70, in get_prep_lookup
return self.lhs.output_field.get_prep_value(self.rhs)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/fields/__init__.py", line 1807, in get_prep_value
return int(value)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'StagingQkb'
我完全被困在这里了。我没有改变将数据传递给序列化程序的方式,所以我真的不知道我做错了什么。如果有人能够帮助我解决这个问题,我将不胜感激!
感谢@WillKeeling,我意识到我在我的 save() 方法中有一个对 Finding.q_id 的引用,我在进行 FK 更改后忘记更新它。国外table的PK是qkb_id,所以我把引用改成了Finding.q_id。qkb_id,模型就可以保存了。
所以我有一个带有一个外键引用的模型,它在几周内都运行良好。我最终不得不向模型添加另一个外键引用,现在我无法使用序列化程序保存任何记录。我应该提到我正在使用 Django 2.1。 这是我正在使用的模型(为简单起见删除了一些字段):
class Finding(models.Model):
finding_id = models.IntegerField(null=False, blank=False, primary_key=True, db_index=True)
name = models.CharField(null=True, blank=True, max_length=255)
web_app = models.ForeignKey(WebApplication, on_delete=models.CASCADE)
q_id = models.ForeignKey(StagingQkb, on_delete=models.CASCADE)
新外键是 q_id 字段。之前这只是一个普通的 int。我实际上已经吹走了旧的 table 而新的仍然完全是空的,所以我知道这不是现有数据的问题(带有外键的 tables 仍然完好无损)。之前保存Findings的时候,我会直接给出'web_app'的WebApplication对象的PK。据我所知,这仍然有效。 'q_id' 字段,当以相同方式插入时,抱怨它需要一个 int/string/bytes 而不是 StagingQkb 对象。好吧,我没有给它一个 StagingQkb 对象,所以给了它什么!
这是序列化程序:
class FindingSerializer(serializers.ModelSerializer):
class Meta:
model = Finding
fields = '__all__'
我提供给序列化程序的数据如下所示:
data = {'finding_id': 5514989,
'name': 'Sample-Name',
'q_id': 12345,
'web_app': 67890}
当我将数据插入序列化程序时,我正在执行以下操作:
>>> fs = FindingSerializer(data=data)
>>> fs.is_valid()
True
>>> fs.save()
我在 运行 上面的代码之后得到的错误如下所示:
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "/opt/oss/python35/lib/python3.5/site-packages/rest_framework/serializers.py", line 214, in save
self.instance = self.create(validated_data)
File "/opt/oss/python35/lib/python3.5/site-packages/rest_framework/serializers.py", line 959, in create
raise TypeError(msg)
TypeError: Got a `TypeError` when calling `Finding.objects.create()`. This may be because you have a writable field on the serializer class that is not a valid argument to `Finding.objects.create()`. You may need to make the field read-only, or override the FindingSerializer.create() method to handle this correctly.
Original exception was:
Traceback (most recent call last):
File "/opt/oss/python35/lib/python3.5/site-packages/rest_framework/serializers.py", line 940, in create
instance = ModelClass._default_manager.create(**validated_data)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/query.py", line 413, in create
obj.save(force_insert=True, using=self.db)
File "/home/dpz3w0q/AutonomousPrimeD/autonomousprimed/Finding/models.py", line 83, in save
q_id=self.q_id)
File "/home/dpz3w0q/AutonomousPrimeD/autonomousprimed/Finding/models.py", line 173, in evaluate
if ScoreMatrix.objects.filter(q_id=q_id).count() > 0:
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/query.py", line 844, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/query.py", line 862, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/sql/query.py", line 1263, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/sql/query.py", line 1287, in _add_q
split_subq=split_subq,
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/sql/query.py", line 1225, in build_filter
condition = self.build_lookup(lookups, col, value)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/sql/query.py", line 1096, in build_lookup
lookup = lookup_class(lhs, rhs)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/lookups.py", line 20, in __init__
self.rhs = self.get_prep_lookup()
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/lookups.py", line 70, in get_prep_lookup
return self.lhs.output_field.get_prep_value(self.rhs)
File "/opt/oss/python35/lib/python3.5/site-packages/django/db/models/fields/__init__.py", line 1807, in get_prep_value
return int(value)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'StagingQkb'
我完全被困在这里了。我没有改变将数据传递给序列化程序的方式,所以我真的不知道我做错了什么。如果有人能够帮助我解决这个问题,我将不胜感激!
感谢@WillKeeling,我意识到我在我的 save() 方法中有一个对 Finding.q_id 的引用,我在进行 FK 更改后忘记更新它。国外table的PK是qkb_id,所以我把引用改成了Finding.q_id。qkb_id,模型就可以保存了。