Request: initialize fields with built-in class defaults

1,167 views
Skip to first unread message

Bobby Mozumder

unread,
Jun 15, 2015, 1:52:13 AM6/15/15
to django-d...@googlegroups.com
Hi all,

Here’s an issue of usability that if fixed could make usage of custom fields simpler.

Right now fields don’t allow a built-in defaults, and you need to explicitly set the default parameter for model fields.  The problem is that this adds a ton of boilerplate code.

Using the Polls tutorial example, if I do:

>>> from polls.models import Question, Choice
>>> q = Question()

By default it’s always <class 'NoneType’>:

>>> type(q.pub_date)
<class 'NoneType'>

The pub_date should always be a type <class 'datetime.datetime'>.  If this was defined in the model constructor, then we could start to access the datetime.datetime class immediately, to assign data.  If I had a custom datetime.datetime class, I could possibly do this immediately:

>>> q = Question()
>>> q.pub_date.month = 11
>>> q.pub_date.day = 26
>>> q.pub_date.year = 2016
>>> q.save()

But right it would give the following error:

>>> q.pub_date.year = 2016
Traceback (most recent call last):
  File "<console>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'year'

Is this a reasonable request?  

I’m able to do something like this now with my own custom fields that derive from models.SubfieldBase, but that class is deprecated, and the new 1.8 model initializer doesn’t do this anymore.

Thank you,

-bobby

Rick van Hattem (wolph)

unread,
Jun 15, 2015, 1:42:51 PM6/15/15
to django-d...@googlegroups.com
While I understand the rationale, it's not really possible due to the underlying Python object:
>>> import datetime
>>> datetime.date()

Traceback (most recent call last):

 
File "<stdin>", line 1, in <module>
TypeError: Required argument 'year' (pos 1) not found
>>> datetime.datetime()

Traceback (most recent call last):

 
File "<stdin>", line 1, in <module>
TypeError: Required argument 'year' (pos 1) not found

Note that you can easily support it by having something like this:

class Question(models.Model):
     pub_date = models.DateField(default=datetime.date.today, blank=True)




~wolph

Bobby Mozumder

unread,
Jun 15, 2015, 6:18:20 PM6/15/15
to django-d...@googlegroups.com
On Jun 15, 2015, at 1:42 PM, Rick van Hattem (wolph) <wol...@gmail.com> wrote:

While I understand the rationale, it's not really possible due to the underlying Python object:
>>> import datetime
>>> datetime.date()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Required argument 'year' (pos 1) not found
>>> datetime.datetime()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Required argument 'year' (pos 1) not found


A custom Django field would either assign initial values to classes that need it, or use classes that have their own initial values.  The point is that the class itself should always exist in the field.

Note that you can easily support it by having something like this:

class Question(models.Model):
     pub_date = models.DateField(default=datetime.date.today, blank=True)



Right.  I’m trying to avoid this situation, as this adds a lot of code - I have dozens of custom fields instantiated hundreds of times in an app, with a lot of initialization data each.  It also requires the knowledge of which internal class that the field uses.  So, I have a common get/set interface for each custom field, so I don’t need to know which class that a field uses, as long as I interface with it properly.

-bobby

--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To post to this group, send email to django-d...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/43d136dd-b8d7-45fe-91af-1863cb5aa205%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Shai Berger

unread,
Jun 16, 2015, 1:51:57 AM6/16/15
to django-d...@googlegroups.com
Hi Bobby,

I'm not sure what you mean by "fields don't allow built-in defaults". While
it's true that Django's DateField (for example) doesn't have a built-in
default, here's[1] a custom field with a built-in default:

class MyDateField(models.DateField):

EPOCH = date(1970, 1, 1)

def __init__(self, *args, **kw):
kw.setdefault('default', self.EPOCH)
super(MyDateField, self).__init__(*args, **kw)

I use kw.setdefault so that the default can still be overridden by the
definition of a specific field.

Did you mean something else?

Shai.

[1] Caveat Lector: Untested code. I'd be quite surprised if it doesn't work.
Reply all
Reply to author
Forward
0 new messages