#29331: Model fields where the python attribute name does not match the db 
column
are not saved
-------------------------------------+-------------------------------------
     Reporter:  Ben Mathes           |                    Owner:  nobody
         Type:  Bug                  |                   Status:  new
    Component:  Database layer       |                  Version:  2.0
  (models, ORM)                      |
     Severity:  Normal               |               Resolution:
     Keywords:  models,              |             Triage Stage:
  deferred_field, save               |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  1                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Description changed by Ben Mathes:

Old description:

> When defining a model, if you rename a model's db column, django will
> thing that model is deferred and will not {{{save()}}} it.
>
> e.g.
> {{{
> class SomeModel(models.Model):
>     """
>     a contrived model field where we want a "field" that is stored
>     in a "field" column, but we use @property getter/setters so
>     we name the SomeModel class's attribute as "_field".
>     """
>     name = models.TextField(null=True)
>     _field = models.TextField(name="field")
>
>     @property
>     def field(self):
>         return self._field.upper()
>
>     @field.setter
>     def field(self, new_value):
>         self._field = new_value.lower()
> }}}
>

>
> With a renamed db column, {{{"_field"}} is in {{{self.__dict__}}}, but
> {{{"field"}}} is not,
>

> {{{
>
>  def get_deferred_fields(self):
>      """
>      Return a set containing names of deferred fields for this instance.
>      """
>      return {
>          f.attname for f in self._meta.concrete_fields
>          if f.attname not in self.__dict__
>      }
> }}}
>
> So {{{field}}} is not saved in {{{.save()}}}, because django _mistakenly_
> thinks {{{"field"}}} is deferred, so it is ignored during {{{.save()}}}
>
> {{{
> #
> https://github.com/django/django/blob/93331877c81c1c6641b163b97813268f483ede4b/django/db/models/base.py#L712
> # ...
> #     elif not force_insert and deferred_fields and using ==
> self._state.db:
> #         field_names = set()
> #         for field in self._meta.concrete_fields:
> #             if not field.primary_key and not hasattr(field, 'through'):
> #                 field_names.add(field.attname)
> # ->      loaded_fields = field_names.difference(deferred_fields)
> #         if loaded_fields:
> #             update_fields = frozenset(loaded_fields)
> #
> #     self.save_base(using=using, force_insert=force_insert,
> #                    force_update=force_update,
> update_fields=update_fields)
> # ...
> }}}
>

> Reproduced in this github django repo:
> https://github.com/benmathes/deferred_fields_bug

New description:

 When defining a model, if you rename a model's db column, django will
 thing that model is deferred and will not {{{save()}}} it.

 e.g.
 {{{
 class SomeModel(models.Model):
     """
     a contrived model field where we want a "field" that is stored
     in a "field" column, but we use @property getter/setters so
     we name the SomeModel class's attribute as "_field".
     """
     name = models.TextField(null=True)
     _field = models.TextField(name="field")

     @property
     def field(self):
         return self._field.upper()

     @field.setter
     def field(self, new_value):
         self._field = new_value.lower()
 }}}



 With a renamed db column, {{{"_field"}}} is in {{{self.__dict__}}}, but
 {{{"field"}}} is not,


 {{{

  def get_deferred_fields(self):
      """
      Return a set containing names of deferred fields for this instance.
      """
      return {
          f.attname for f in self._meta.concrete_fields
          if f.attname not in self.__dict__
      }
 }}}

 So {{{field}}} is not saved in {{{.save()}}}, because django _mistakenly_
 thinks {{{"field"}}} is deferred, so it is ignored during {{{.save()}}}

 {{{
 #
 
https://github.com/django/django/blob/93331877c81c1c6641b163b97813268f483ede4b/django/db/models/base.py#L712
 # ...
 #     elif not force_insert and deferred_fields and using ==
 self._state.db:
 #         field_names = set()
 #         for field in self._meta.concrete_fields:
 #             if not field.primary_key and not hasattr(field, 'through'):
 #                 field_names.add(field.attname)
 # ->      loaded_fields = field_names.difference(deferred_fields)
 #         if loaded_fields:
 #             update_fields = frozenset(loaded_fields)
 #
 #     self.save_base(using=using, force_insert=force_insert,
 #                    force_update=force_update,
 update_fields=update_fields)
 # ...
 }}}


 Reproduced in this github django repo:
 https://github.com/benmathes/deferred_fields_bug

--

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

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/067.c21883c8cc6329658967b823461fa433%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to