我正在使用Django 1.9并且在使用模型时发现了一些奇怪的行为。我知道以下代码创建了一个对象,将其保存到数据库,更改字段,然后更新数据库中的相同条目:
cat = models.Cat(name="Bob")
cat.save()
cat.name = "Sally"
cat.save()
但是,当我使用cats = models.Cat.objects.all()
查询所有对象时,我发现它不是返回["Sally"]
而是返回["Bob", "Sally"]
。显然cat.save()
正在数据库中创建一个新元素,而不是更新现有元素。我以前和Django合作过,但从未遇到过这个问题。需要注意的一点是name
属性是Cat模型的主键。这可能是为什么它不是更新,而是创建一个全新的条目?
答案 0 :(得分:2)
主键是Django用来确定是更新还是创建项目的主键。通常,这是一个您不会修改的不透明ID;但在您的情况下,它是您数据的一部分。修改该值时,Django无法知道该对象是否引用了数据库中的现有行。
不要这样做;坚持使用与您的实际数据无关的自动增量ID。答案 1 :(得分:1)
你是对的,这里的问题是你的主键是name
字段。如果数据库中存在pk
值,Django将进行更新,如果不存在,则进行插入。例如:
class Cat(models.Model):
name = models.CharField(max_length=255)
cat = Cat(name='Bart')
cat.save() # This creates a new object
print(cat.pk)
> '1'
cat.name = 'Sally'
cat.save() # This updates the object, the pk will still be '1'
print(cat.pk)
> '1'
print(Cat.objects.all())
> [<Cat 'Sally'>]
fluffy = Cat(name='Fluffy')
fluffy.pk = 1
fluffy.save()
'''This will UPDATE the existing object, since an object
with that primary key already exists'''
print(Cat.objects.all())
> [<Cat 'Fluffy'>]
fluffy.pk = 2
fluffy.save()
'''This will CREATE a new object, since no object with
that primary key already exists'''
print(Cat.objects.all())
> [<Cat 'Fluffy'>, <Cat 'Fluffy'>]
如果可能,我建议删除primary_key=True
字段上的name
属性。如果您希望name
是唯一的,可能只需设置unique=True
?