Code

Opened 6 years ago

Closed 6 years ago

Last modified 2 years ago

#8633 closed Uncategorized (invalid)

Field default value force to unicode when create custom field.

Reported by: flytwokites Owned by: nobody
Component: Database layer (models, ORM) Version: master
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

When create a custom field like document "http://www.djangoproject.com/documentation/custom_model_fields/" does:

class Hand(object):
    def __init__(self, north, east, south, west):
        self.north = north
        self.east = east
        self.south = south
        self.west = west

class HandField(...):
    ...
    def to_python(self, value):
        ...

class Foo(models.Model):
    hand = HandField(default=Hand(...))

f = Foo()
# This will use the default hand value, but value passed to HandField.to_python is string format of hand.
# If we not define a Hand.__str__ function, this string is like '<Hand instance at 0x????????>'.
# So the HandField.to_python not able to recognize this string value.
# So we must define a __str__ on Hand, and HandField must convert this string back to Hand instance.
# In some custom field value __str__ output is a human readable text, and difficult to convert back to a instance.
# So it is better to pass default value direct to to_python().
f.save()

The code in django/db/models/fields/init.py

class Field:
    def get_default(self):
        "Returns the default value for this field."
        if self.default is not NOT_PROVIDED:
            if callable(self.default):
                return self.default()
            return force_unicode(self.default, strings_only=True)
        if not self.empty_strings_allowed or (self.null and not connection.features.interprets_empty_strings_as_nulls):
            return None
        return ""

Attachments (0)

Change History (3)

comment:1 Changed 6 years ago by flytwokites

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to invalid
  • Status changed from new to closed

Ohh, i have a mistake.

comment:2 Changed 6 years ago by carljm

Just to document this further for anybody else who stumbles across this: the "mistake" here is in setting a Field's default value to any mutable object (a Hand instance, a list, a set, whatever). This is almost certainly not what you want to do, as a reference to the same _instance_ of that object would be used as the default value for that field in all new model instances. So Django instead forces that default value to unicode, which is immutable.

The correct approach is to instead use as the default a callable that returns a Hand instance (or list, or set, or whatever).

comment:3 Changed 2 years ago by aaugustin

  • Easy pickings unset
  • Severity set to Normal
  • Type set to Uncategorized
  • UI/UX unset

#18478 was a duplicate.

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.