2016-02-11 3 views
0

Я работаю с Django 1.9 и замечаю странное поведение при работе с моделями. Я знаю, что следующий код создает объект, сохраняет его в базу данных, изменяет поле, а затем обновляет ту же самую запись в базе данных: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. Может быть, поэтому он не обновляется, а создает совершенно новую запись?

ответ

1

Вы правы, проблема заключается в том, что ваш первичный ключ - это поле name. Django выполнит обновление, если в базе данных существует значение pk, а вставка - нет. Например:

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'>] 

Если возможно, я бы рекомендовал удаление атрибута на name поле primary_key=True. Если вы хотите, чтобы name был уникальным, может быть, просто установить unique=True?

2

Первичный ключ - это то, что использует Django для определения необходимости обновления или создания элемента. Обычно это непрозрачный идентификатор, который вы не изменяете; но в вашем случае это часть ваших данных. Когда вы изменяете значение, Django не знает, что объект ссылается на существующую строку в базе данных.

Не делайте этого; придерживаться автоинкрементных идентификаторов, которые не имеют никакого отношения к вашим фактическим данным.

Смежные вопросы