Opened 8 years ago

Closed 8 years ago

Last modified 8 years ago

#26807 closed Cleanup/optimization (fixed)

Document how to replicate SubfieldBase behavior of calling to_python on assignment

Reported by: Aarni Koskela Owned by: nobody
Component: Documentation Version: 1.8
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

With the deprecation of SubfieldBase, custom fields no longer automatically have the Creator class behavior that calls to_python() on every assignment (see https://github.com/django/django/blob/4fd264b6f1737b0317fdd95b3d7ff3bba15ae6c3/django/db/models/fields/subclassing.py#L44), incl. construction.

This causes the problem described here – https://github.com/hzdg/django-enumfields/issues/60 – i.e. enumfields.EnumField doesn't coerce values to the actual Enum value types anymore.

The fix is naturally to reimplement a descriptor like Creator (and that does indeed fix this particular issue), but I feel like I'm missing something doing that.

(The deprecation warning for SubfieldBase says that one should use from_db_value(), but it doesn't get called on instance construction either, it seems.)

Here's a trivial py.test style test case (the assertions fail):

from django.db import models

class CoolCharField(models.CharField):
    def to_python(self, value):
        return str(value).upper() + "!!!"

    def from_db_value(self, value):
        return self.to_python(value)


class CoolModel(models.Model):
    yay = CoolCharField()


def test_cool_char_field_1():
    m = CoolModel(yay="ponies")
    assert m.yay == "PONIES!!!"


def test_cool_char_field_2():
    m = CoolModel()
    m.yay = "ponies"
    assert m.yay == "PONIES!!!"

Change History (5)

comment:1 by Tim Graham, 8 years ago

Component: Database layer (models, ORM)Documentation
Summary: Custom fields do not call to_python on assignmentDocument how to replicate SubfieldBase behavior of calling to_python on assignment
Triage Stage: UnreviewedAccepted
Type: UncategorizedCleanup/optimization
Version: 1.91.8

The django-developers thread that proposed the removal of SubfieldBase says:

Django provides a metaclass called SubfieldBase, which basically means that that field will have it's to_python() method called whenever a value is assigned to the model, including when it is loaded from the database. This really is an abuse of to_python() whose primary purpose is to convert strings from serialisation and forms into the relevant python object.

The deprecation note in the the 1.8 release notes says, "the new approach does not call the to_python() method on assignment as was the case with SubfieldBase." We could say that custom fields can copy the Creator implementation if they require this behavior.

comment:2 by Tim Graham, 8 years ago

Has patch: set

comment:3 by Tim Graham <timograham@…>, 8 years ago

Resolution: fixed
Status: newclosed

In 518eaf1f:

Fixed #26807 -- Documented how to replicate SubfieldBase's assignment behavior.

comment:4 by Tim Graham <timograham@…>, 8 years ago

In 3342f24f:

[1.10.x] Fixed #26807 -- Documented how to replicate SubfieldBase's assignment behavior.

Backport of 518eaf1fa2d86dc1b0ba7adba22b30bcc8f3a497 from master

comment:5 by Tim Graham <timograham@…>, 8 years ago

In 717aa884:

[1.8.x] Fixed #26807 -- Documented how to replicate SubfieldBase's assignment behavior.

Backport of 518eaf1fa2d86dc1b0ba7adba22b30bcc8f3a497 from master

Note: See TracTickets for help on using tickets.
Back to Top