User.get_profile

6 views
Skip to first unread message

Martin Matusiak

unread,
Jun 21, 2011, 8:04:49 AM6/21/11
to django-cou...@googlegroups.com
Alright guys, thanks for joining the group. I hope this will be helpful.

I'd like to point your attention to this:
http://www.b-list.org/weblog/2006/jun/06/django-tips-extending-user-model/

I've ported this to django-couchdb-utils, and the relevant method is
auth.User.get_profile. I'd like to be able to write a test for this,
but that is hard to do, because User and UserProfile are models in
different applications, django-couchdb-utils and the user app
respectively. It would mean adding a mock UserProfile class to
django-couchdb-utils.models just for this, and a view to couchdb. All
this seems rather exaggerated just for a test.

Still, the code works. If you have any thoughts about it let me know.


Martin

Stefan Kögl

unread,
Jun 21, 2011, 8:17:31 AM6/21/11
to django-cou...@googlegroups.com
Am 2011-06-21 14:04, schrieb Martin Matusiak:
> I'd like to point your attention to this:
> http://www.b-list.org/weblog/2006/jun/06/django-tips-extending-user-model/
>
> I've ported this to django-couchdb-utils, and the relevant method is
> auth.User.get_profile. I'd like to be able to write a test for this,
> but that is hard to do, because User and UserProfile are models in
> different applications, django-couchdb-utils and the user app
> respectively. It would mean adding a mock UserProfile class to
> django-couchdb-utils.models just for this, and a view to couchdb. All
> this seems rather exaggerated just for a test.
>
> Still, the code works. If you have any thoughts about it let me know.

I think that all this shouldn't be necessary when using a CouchDB
backend. The purpose of UserProfile was to store data that didn't fit
into User's schema -- however, we shouldn't have to worry about this at
all. With CouchDB in the backend, a user of our library could
dynamically extend a user and it's data would be stored within the
user's CouchDB document.

Although this should be conceptually easier, people using it need to be
aware of the differences. Instead of

>> profile = user.get_profile()
>> profile.foo = bar
>> profile.save()

one could simply write

>> user.foo = bar
>> user.save()

To ensure compatibility we could simple have the following method

def get_profile(self):
return self

What do you think?


-- Stefan

Martin Matusiak

unread,
Jun 21, 2011, 8:30:30 AM6/21/11
to django-cou...@googlegroups.com
2011/6/21 Stefan Kögl <ste...@skoegl.net>:

Looking at the big picture I don't think there is a really great
solution to this. The ideal (maybe) would be to have one Document that
stores all fields. The problem is that if you instantiate User, assign
to a "custom" field and save it, you don't get the model abstraction
features. You can't set a default value on the field, you can't set
any validation metadata and if you retrieve a document and try to read
a field for which *this* document doesn't have a value, you probably
get an AttributeError, because the field isn't declared on the class,
only on the instance you happen to be manipulating.

I've thought about adding fields to User conditionally, but the
metaclass you have to subclass from couchdbkit is not exported by
couchdbkit, whether by policy or not I don't know. Either way I think
that technique is overly complicated.

Furthermore, you can't really subclass User either, because then you
have to somehow tell django-couchdb-utils to use your subclass instead
and so on, which is a problem because the django-couchdb-utils app
gets loaded before your app etc.

I've come to think that implementing django's api is the best choice
here, the best compromise.


Martin

Stefan Kögl

unread,
Jun 22, 2011, 9:45:03 AM6/22/11
to django-cou...@googlegroups.com
Am 2011-06-21 14:30, schrieb Martin Matusiak:
> Looking at the big picture I don't think there is a really great
> solution to this. The ideal (maybe) would be to have one Document that
> stores all fields. The problem is that if you instantiate User, assign
> to a "custom" field and save it, you don't get the model abstraction
> features. You can't set a default value on the field, you can't set
> any validation metadata and if you retrieve a document and try to read
> a field for which *this* document doesn't have a value, you probably
> get an AttributeError, because the field isn't declared on the class,
> only on the instance you happen to be manipulating.

OK, that's a valid concern.


> Furthermore, you can't really subclass User either, because then you
> have to somehow tell django-couchdb-utils to use your subclass instead
> and so on, which is a problem because the django-couchdb-utils app
> gets loaded before your app etc.

That shouldn't be a problem, actually. We can easily add a setting that
django-couchdb-utils reads on startup. I think this option
exists/existed for django.contrib.auth, too.


-- Stefan

Reply all
Reply to author
Forward
0 new messages