Friday, April 29, 2011

Re: .save() works with no (custom, not 'id') primary key specified?

On Fri, Apr 29, 2011 at 12:17 PM, Jeff Blaine <cjblaine@gmail.com> wrote:
> "primary_key=True implies null=False and unique=True. Only one primary key
> is allowed on an object."
> So that unique=True part is inaccurate?  Or is that, again, another thing
> that will fail only at validation?

Maybe this'll help::

# Log every SQL query
>>> import logging
>>> l = logging.getLogger('django.db.backends')
>>> l.setLevel(logging.DEBUG)
>>> l.addHandler(logging.StreamHandler())

# Now let's play...
>>> from myapp.models import Device
>>> d1 = Device()
>>> d1.save()
(0.002) SELECT (1) AS "a" FROM "cfpk_device" WHERE
"cfpk_device"."propertyno" = E'' LIMIT 1; args=('',)
(0.001) INSERT INTO "cfpk_device" ("propertyno") VALUES (E''); args=('',)

>>> d2 = Device()
>>> d2.save()
(0.001) SELECT (1) AS "a" FROM "cfpk_device" WHERE
"cfpk_device"."propertyno" = E'' LIMIT 1; args=('',)

You have to remember that `object.save()` could mean INSERT *or*
UPDATE depending on whether the object with the given primary key
exists or not. When you create a new device, because again the default
is the empty string, you've already got one of those in the DB. Django
notices that it doesn't need updating, and so it doesn't update it.

Now consider this:

>>> d2.save()
(0.001) INSERT INTO "cfpk_device" ("propertyno") VALUES (E''); args=('',)
Traceback (most recent call last):
...
IntegrityError: duplicate key value violates unique constraint
"cfpk_device_pkey"
DETAIL: Key (propertyno)=() already exists.

If you force an insert, you'll see the error you're expecting.

I'm sorry if you think it's broken. I disagree, though: Django's
working the way we designed it to work. You've exposed a subtle
edge-case (which shows just one reason why I use surrogate keys almost
without exception).

Jacob

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to django-users+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

No comments:

Post a Comment