[Django] #20154: Inconsistent model save behavior when assigning model instances to CharFields

7 views
Skip to first unread message

Django

unread,
Mar 28, 2013, 4:59:56 AM3/28/13
to django-...@googlegroups.com
#20154: Inconsistent model save behavior when assigning model instances to
CharFields
----------------------------------------------+--------------------
Reporter: adsva | Owner: nobody
Type: Bug | Status: new
Component: Database layer (models, ORM) | Version: 1.4
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
----------------------------------------------+--------------------
Hi,

When I assign a model instance to a CharField on a model and save the
instance, it gets saved as the string representation of the instance on
insert, but as the string representation of the instance's pk on update.
{{{
from django.db import models

class Country(models.Model):
name = models.CharField(max_length=100)
def __unicode__(self):
return name

class Address(models.Model):
country = models.CharField(max_length=100)
}}}
{{{
>>> c = Country.objects.get(name='Sweden')
>>> a = Address.objects.create(country=c)
>>> Address.objects.get(pk=a.pk).country
>>> u'Sweden'
>>> a.save()
>>> Address.objects.get(pk=a.pk).country
>>> '1'
}}}

I do realize I should assign c.name instead if c, but it feels like a bug
to treat values differently on insert vs update.

The reason seems to be that `SQLUpdateCompiler.as_sql` preps the value
using `val.prepare_database_save` if available, whereas
`SQLInsertCompiler.as_sql` always uses `field.get_db_prep_save`.

--
Ticket URL: <https://code.djangoproject.com/ticket/20154>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Mar 28, 2013, 5:17:04 AM3/28/13
to django-...@googlegroups.com
#20154: Inconsistent model save behavior when assigning model instances to
CharFields
-------------------------------------+-------------------------------------

Reporter: adsva | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.4
(models, ORM) | Resolution:
Severity: Normal | Triage Stage:
Keywords: | Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by schmilblick):

* cc: schmilblick (added)
* needs_better_patch: => 0
* needs_tests: => 0
* needs_docs: => 0


--
Ticket URL: <https://code.djangoproject.com/ticket/20154#comment:1>

Django

unread,
Apr 4, 2013, 12:58:25 AM4/4/13
to django-...@googlegroups.com
#20154: Inconsistent model save behavior when assigning model instances to
CharFields
-------------------------------------+-------------------------------------

Reporter: adsva | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: master
(models, ORM) | Resolution:
Severity: Normal | Triage Stage: Accepted
Keywords: | Needs documentation: 0
Has patch: 0 | Patch needs improvement: 0
Needs tests: 0 | UI/UX: 0
Easy pickings: 0 |
-------------------------------------+-------------------------------------
Changes (by pegler):

* cc: pegler (added)
* version: 1.4 => master
* stage: Unreviewed => Accepted


Comment:

This also seems odd to me. Here's a test case to demonstrate it:
https://github.com/pegler/django/compare/20154

Best,
Matt

--
Ticket URL: <https://code.djangoproject.com/ticket/20154#comment:2>

Django

unread,
Oct 1, 2015, 5:34:14 PM10/1/15
to django-...@googlegroups.com
#20154: Inconsistent model save behavior when assigning model instances to
CharFields
-------------------------------------+-------------------------------------
Reporter: adsva | Owner: nobody
Type: Bug | Status: closed

Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution: fixed
Keywords: | Triage Stage: Accepted

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by timgraham):

* status: new => closed
* resolution: => fixed


Old description:

> Hi,
>
> When I assign a model instance to a CharField on a model and save the
> instance, it gets saved as the string representation of the instance on
> insert, but as the string representation of the instance's pk on update.
> {{{
> from django.db import models
>
> class Country(models.Model):
> name = models.CharField(max_length=100)
> def __unicode__(self):
> return name
>
> class Address(models.Model):
> country = models.CharField(max_length=100)
> }}}
> {{{
> >>> c = Country.objects.get(name='Sweden')
> >>> a = Address.objects.create(country=c)
> >>> Address.objects.get(pk=a.pk).country
> >>> u'Sweden'
> >>> a.save()
> >>> Address.objects.get(pk=a.pk).country
> >>> '1'
> }}}
>
> I do realize I should assign c.name instead if c, but it feels like a bug
> to treat values differently on insert vs update.
>
> The reason seems to be that `SQLUpdateCompiler.as_sql` preps the value
> using `val.prepare_database_save` if available, whereas
> `SQLInsertCompiler.as_sql` always uses `field.get_db_prep_save`.

New description:

Hi,

When I assign a model instance to a CharField on a model and save the
instance, it gets saved as the string representation of the instance on
insert, but as the string representation of the instance's pk on update.
{{{
from django.db import models

class Country(models.Model):
name = models.CharField(max_length=100)
def __unicode__(self):

return self.name

class Address(models.Model):
country = models.CharField(max_length=100)
}}}
{{{
>>> c = Country.objects.get(name='Sweden')
>>> a = Address.objects.create(country=c)
>>> Address.objects.get(pk=a.pk).country
>>> u'Sweden'
>>> a.save()
>>> Address.objects.get(pk=a.pk).country
>>> '1'
}}}

I do realize I should assign c.name instead if c, but it feels like a bug
to treat values differently on insert vs update.

The reason seems to be that `SQLUpdateCompiler.as_sql` preps the value
using `val.prepare_database_save` if available, whereas
`SQLInsertCompiler.as_sql` always uses `field.get_db_prep_save`.

--

Comment:

This is fixed in Django 1.9. The test in the shell session will now given
an error message, "TypeError: Tried to update field
tix20154.Address.country with a model instance, <Country: Sweden>. Use a
value compatible with CharField." (and similar for the test provided in
the link of comment 2).

--
Ticket URL: <https://code.djangoproject.com/ticket/20154#comment:3>

Reply all
Reply to author
Forward
0 new messages