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.
* cc: schmilblick (added)
* needs_better_patch: => 0
* needs_tests: => 0
* needs_docs: => 0
--
Ticket URL: <https://code.djangoproject.com/ticket/20154#comment:1>
* 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>
* 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>