Nullable User email

73 views
Skip to first unread message

Demian Brecht

unread,
Aug 7, 2012, 11:08:50 AM8/7/12
to django...@googlegroups.com
In an authentication backend I'm currently writing, I've supplied a custom User model that extends the contrib.auth User model. I have the need to allow email addresses to be NULL. 

A little context: I'm writing an OAuth2 wrapper for an OAuth2 client I relatively recently wrote (yes, I know that there are other clients already written out there, but I'm writing this one due to being quite partial to my module ;)). Some OAuth2 providers don't provide user e-mail addresses, regardless of scope params. All providers however, provide some form of a user ID. As you can't simply use field hiding in Django models, I figure that I can achieve this by one of the following two methods:

1. Copy/paste the entire model, changing the attribute of the one field.
2. User._meta.fields[4].null = true

#2, even though seemingly hacky at best seems to be the lesser of the two evils as it at least keeps things DRY (and is potentially far less maintenance down the road).

My question is, is there another method of achieving this that I'm not seeing? Preferably one that isn't hacky?

Thanks,
Demian

Germán

unread,
Aug 7, 2012, 1:33:56 PM8/7/12
to django...@googlegroups.com
It seems you shouldn't use null but rather an empty string:
Avoid using null on string-based fields such as CharField and TextField unless you have an excellent reason. If a string-based field has null=True, that means it has two possible values for “no data”: NULL, and the empty string. In most cases, it’s redundant to have two possible values for “no data;” Django convention is to use the empty string, not NULL.

Demian Brecht

unread,
Aug 7, 2012, 4:08:21 PM8/7/12
to django...@googlegroups.com
Thanks for the quote, was unaware of the convention.

Melvyn Sopacua

unread,
Aug 7, 2012, 7:34:06 PM8/7/12
to django...@googlegroups.com
On 7-8-2012 17:08, Demian Brecht wrote:

> 1. Copy/paste the entire model, changing the attribute of the one field.
> 2. User._meta.fields[4].null = true
3. Override the __new__ method in your subclassed model and remove the
email field definition from the class attributes to the meta class
before you call super(). This does involve a bit of a copying from
db/models/ModelBase.__new__ but it's cleaner as __new__ is meant exactly
for this purpose.


--
Melvyn Sopacua

Demian Brecht

unread,
Aug 9, 2012, 11:12:46 AM8/9/12
to django...@googlegroups.com
Thanks for the feedback guys..

What I ended up doing was adding the following lines to my models module:

from django.contrib.auth.models import User as BaseUser

BaseUser._meta.get_field("username")._unique = False
BaseUser._meta.get_field("email").null = True

Melvin: I tried your suggestion and it worked like a charm for the email field. However, it didn't work for the username. I'm assuming that ORM introspection during syncdb doesn't use an instantiated model and as such, the "UNIQUE" attribute was still applied to the auth User model. Doing it this way allows me to override the default behavior during database creation.
Reply all
Reply to author
Forward
0 new messages