#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:

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


 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:3>
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 [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/067.29d30a76db1cbf941861fc837af47195%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to