Re: auth.user refactor: the profile aproach

2012-04-03 Thread Tai Lee
I like this proposal because I am a big fan of a stripped down `User` model 
which is basically just an ID, whic provides a common hook into 
groups/permissions and other django and 3rd party profiles.

What I don't like is the magical `data` bag (accessing `User.data` and 
filter lookups), the new `AUTH_PROFILES` setting, and the idea of Django 
automagically or lazily creating profiles for me. I would rather see Django 
rely solely on its `OneToOneField` field to access user profile data.

Any pluggable app (app1) will know what fields it's own profile model has 
and how to access them, relative to the central `User` object.

If app1 relies on fields defined by another app (app2), that other app 
should be a requirement of app1 and app1 would know how to access app2's 
fields.

I am happy to use project-level signals for everything else (syncing common 
profile data from app1 and app2, or auto-creating user profiles), because 
project-level signals give me explicit control over what is going to happen 
and when. I don't need any more magic here.

Cheers.
Tai.


On Tuesday, 3 April 2012 10:35:41 UTC+10, Jacob Kaplan-Moss wrote:
>
>  Hi folks -- 
>
> I've written up a proposal for how *I* would like to address refactoring 
> auth.user: https://gist.github.com/2245327.
>
> In essence, this does two things:
>
> * Vastly "prunes" the required fields on auth.user. The only things left 
> are an "identifier" (which could be username, email, url, uuid, whatever), 
> and a password.
> * Introduces a new "profile" system that provides a way to contribute 
> extra related fields. Multiple profiles are supported, along with some 
> syntactic sugar for dealing with multiple profiles in a reasonably reusable 
> way.
>
> And that's about it. I'm deliberately trying to find a middle ground 
> between "do the minimum to allow people to move on" and "throw out and 
> rewrite django.contrib.auth entirely". I'm not expecting everyone to be 
> thrilled by this idea, but I'm hoping that this is "Good Enough" for almost 
> everyone.
>
> For more please see the document. Please do try to read the whole thing: 
> I've had a few rounds of feedback incorporated already, and there's even an 
> FAQ at the end.
>
> I'm not using BDFL fiat here, at least not yet. This is a proposal, and I 
> very much want to hear feedback, objections, and alternatives. I'm 
> particularly interested in hearing from people who've got complicated auth 
> needs and think this absolutely won't work for them. 
>
> I *have* reviewed all the other proposals and I'm between -0 and -1 on all 
> of them. This means that if you don't like my proposal, you'll probably 
> have to come up with a complete *new* idea to have any chance of getting my 
> vote.
>
> Thanks!
>
> Jacob
>  

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/django-developers/-/PMpcPCKgTuoJ.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: auth.user refactor: the profile aproach

2012-04-03 Thread Donald Stufft
On Tuesday, April 3, 2012 at 3:37 AM, Tai Lee wrote:
> I like this proposal because I am a big fan of a stripped down `User` model 
> which is basically just an ID, whic provides a common hook into 
> groups/permissions and other django and 3rd party profiles.
> 
> What I don't like is the magical `data` bag (accessing `User.data` and filter 
> lookups), the new `AUTH_PROFILES` setting, and the idea of Django 
> automagically or lazily creating profiles for me. I would rather see Django 
> rely solely on its `OneToOneField` field to access user profile data.
> 
> Any pluggable app (app1) will know what fields it's own profile model has and 
> how to access them, relative to the central `User` object.
> 
> If app1 relies on fields defined by another app (app2), that other app should 
> be a requirement of app1 and app1 would know how to access app2's fields.
> 
> I am happy to use project-level signals for everything else (syncing common 
> profile data from app1 and app2, or auto-creating user profiles), because 
> project-level signals give me explicit control over what is going to happen 
> and when. I don't need any more magic here.
> 
> Cheers.
> Tai.
Without the `data` bag we've done nothing except rename the username field and 
make it longer really. Everything else that you define can already be achieved 
by ignoring the fields already on User and using OneToOneFields. With the 
`data` bag we allow a pattern kinda similar to class inheritance.

I think you also mistake the use case, it's not app1 relies on app2, it's app1 
relies on _a_ field called email that provides an email address. It doesn't 
care where it comes from. If we do not provide a common way to access this data 
with this proposal, than a large number of apps are going to depend on the 
default profile, and we are stuck again here where everything depends on what 
Django Core decides for "first_name", "last_name", email length, etc.
> 
> 
> On Tuesday, 3 April 2012 10:35:41 UTC+10, Jacob Kaplan-Moss wrote:
> > Hi folks -- 
> > 
> > I've written up a proposal for how *I* would like to address refactoring 
> > auth.user: https://gist.github.com/2245327.
> > 
> > In essence, this does two things:
> > 
> > * Vastly "prunes" the required fields on auth.user. The only things left 
> > are an "identifier" (which could be username, email, url, uuid, whatever), 
> > and a password.
> > * Introduces a new "profile" system that provides a way to contribute extra 
> > related fields. Multiple profiles are supported, along with some syntactic 
> > sugar for dealing with multiple profiles in a reasonably reusable way.
> > 
> > And that's about it. I'm deliberately trying to find a middle ground 
> > between "do the minimum to allow people to move on" and "throw out and 
> > rewrite django.contrib.auth entirely". I'm not expecting everyone to be 
> > thrilled by this idea, but I'm hoping that this is "Good Enough" for almost 
> > everyone.
> > 
> > For more please see the document. Please do try to read the whole thing: 
> > I've had a few rounds of feedback incorporated already, and there's even an 
> > FAQ at the end.
> > 
> > I'm not using BDFL fiat here, at least not yet. This is a proposal, and I 
> > very much want to hear feedback, objections, and alternatives. I'm 
> > particularly interested in hearing from people who've got complicated auth 
> > needs and think this absolutely won't work for them. 
> > 
> > I *have* reviewed all the other proposals and I'm between -0 and -1 on all 
> > of them. This means that if you don't like my proposal, you'll probably 
> > have to come up with a complete *new* idea to have any chance of getting my 
> > vote.
> > 
> > Thanks!
> > 
> > Jacob 
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Django developers" group.
> To view this discussion on the web visit 
> https://groups.google.com/d/msg/django-developers/-/PMpcPCKgTuoJ.
> To post to this group, send email to django-developers@googlegroups.com 
> (mailto:django-developers@googlegroups.com).
> To unsubscribe from this group, send email to 
> django-developers+unsubscr...@googlegroups.com 
> (mailto:django-developers+unsubscr...@googlegroups.com).
> For more options, visit this group at 
> http://groups.google.com/group/django-developers?hl=en.

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: auth.user refactor: the profile aproach

2012-04-03 Thread Bruno Renié
Hi Jacob,

Thanks for taking the time to tackle this issue!

On Tue, Apr 3, 2012 at 2:35 AM, Jacob Kaplan-Moss  wrote:
> Hi folks --
>
> I've written up a proposal for how *I* would like to address refactoring
> auth.user: https://gist.github.com/2245327.
>
> In essence, this does two things:
>
> * Vastly "prunes" the required fields on auth.user. The only things left are
> an "identifier" (which could be username, email, url, uuid, whatever), and a
> password.
> * Introduces a new "profile" system that provides a way to contribute extra
> related fields. Multiple profiles are supported, along with some syntactic
> sugar for dealing with multiple profiles in a reasonably reusable way.

I very much like the idea of stripping down the user fields. I am
currently using an approach that's very similar to your proposal in
all my projects, except that instead of creating several profiles, I
directly add fields to the User model using this snippet:

https://gist.github.com/1283969 (I am not the initial author)

With this, adding a field to the user model is as simple as:

class MyUser(models.Model):
newsletter = models.BooleanField()

class Meta:
abstract = True
contribute_to_model(MyUser, User)

I already use this to patch the email field in the User model or make
group names not unique for instance.

The only issue is that the contributed models need to be registered as
early as possible. Currently I import them in my urls.py, but we can
imagine adding hooks for such things that need to be done at startup
time (app-refactor? :) or use your AUTH_PROFILES setting for this (not
enthusiastic about this one).

I am fully aware that this can be abused a lot. However this makes a
couple of things simpler:

* No need to proxy fields on the User model, it stays a normal model
with no special treatment
* Conflicts are simply resolved: if two models contribute the same
field, the last one registered wins
* No need for a special-cased form for editing profile-related fields,
a simple ModelForm with includes = ['fields', 'to', 'include'] works.

This is the technique I will use anyway if your proposal is
implemented, and I don't see anything that would prevent this from
working with the new auth so I'm mainly posting this because I haven't
seen this approach in the different proposals for the auth refactor.

-Bruno

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: [GSOC 2012] Customizable serialization

2012-04-03 Thread Tom Christie
Hi Piotr,

  I'd really like to see something along these lines making it into Django.
I worked on this during the 2011 DjangoCon.eu sprints, which I posted about 
a while 
back
.
That work made it into Django REST framework's 
serializer,
 
but never back into Django,
mostly due to never being fully satisfied with a corresponding 
deserialization API.
(REST framework uses forms for deserialization, but that gets awkward for 
deserializing nested models.)
I've been meaning to follow up on my post for a while now.

As regards your proposal

In general...

  I'm really pleased to see that you've taken on board the previous 
comments and opted for a 2-stage approach - I think it's absolutely the 
right thing to do.
It breaks the problem down into two very well defined tasks.

1. Convert native datatypes to/from data streams.  (eg. Tastypie's 
serializers,
 
REST framework's 
renderers&
 
parsers
)
2. Convert complex objects to/from native datatypes. (eg. Tastypie's 
hydrate/dehydate, REST frameworks 
serializer
, form based 
deserialization
)

In your proposal you've understandably addressed model serialization in 
detail, but I (personally) think it'd be worthwhile breaking things down a 
little bit more.
For example, you might consider the following:

1. Define a base API for part (1).  Is it handled by a single class with 
instance methods for converting in each direction, or by 
two separate classes?
What about formats that are one direction only? (eg. You might want to 
parse HTTP form data, but you're unlikely to want to render it.)
Are formats that are not fully reversible an issue? (eg. Some formats 
[eg csv?] might not have native representations of all the python 
datatypes, and only have string representations.)
Exactly what subset of types do we consider 'native'  - should it be 
strictly python native datatypes, or would we use the set of types covered 
by 'django.utils.encoding.is_protected_type'?
2. Define a base API for the components of part (2) that doesn't include 
the implementation or related specifically to Django models/querysets.
Are the serialization and deserialization handled by the same class? 
 What about serializations that aren't reversible?  [eg only include a 
subset of information]
3. Consider given your general API what interface you'd need for a 
serializer that worked with arbitrary python objects.
4. Given the API for an arbitrary object serializer what else do you need 
to provide in the API to deal with querysets/model instances specifically? 
5. Are object fields handled with a subclass of the Serializer class, or do 
they need a different API?  If they're a subclass what extra information do 
they need?
6. When looking at deserialization is it worth considering mirroring any 
aspects of the form APIs?  How do you treat deserialization errors?
7. Is the deserializer creating saved or unsaved model instances?  How do 
you handle saving the instances, and how do you deal with deserializing 
data where some parts of the object might be implicit?  (Eg deserializing 
data from an API request, where the pk of the model is given in the URL of 
the request?)

If you break it right down like that I think it'd help make sure you get 
the fundamentals right.
I'd expect to see some base classes without implementation, and 
serialization of Django objects tackled purely as a subset of the general 
case.

Some things I was slightly confused by in your proposal as it stands...

* JSONSerializer subclassing Serializer. (and XMLSerializer subclassing 
JSONSerializer.)
  I'd have thought that if you're using a two phase approach you'd keep the 
complex<->native and native<->data stream APIs totally decoupled.
  JSON serialization doesn't itself have anything to do with how you choose 
to structure the serialization of a complex object, so why should it 
subclass the implementation of that part?
* "dehydrate__value__", "hydrate__value__" - what's with the double 
underscore naming?
* I don't get the '@attribute' decorator.  I think it'd be simpler to just 
have 'fields', 'include', 'exclude'.  If fields is None then use the 
'default set of fields' + 'include' - 'exclude'.  If fields is not None, 
use that and ignore include/exclude.
* I wouldn't consider specia

Re: auth.user refactor: the profile aproach

2012-04-03 Thread Alex Ogier
Hi developers,

I have written up a little bit about the alternate proposal that I made a
while ago, Solution 2a from
https://code.djangoproject.com/wiki/ContribAuthImprovements

In addition to other arguments, there is a point-by-point breakdown of what
I feel are the weaknesses in Jacob's proposal.

You can find it at  https://gist.github.com/2289395

Best,
Alex Ogier

On Mon, Apr 2, 2012 at 8:35 PM, Jacob Kaplan-Moss wrote:

>  Hi folks --
>
> I've written up a proposal for how *I* would like to address refactoring
> auth.user: https://gist.github.com/2245327.
>
> In essence, this does two things:
>
> * Vastly "prunes" the required fields on auth.user. The only things left
> are an "identifier" (which could be username, email, url, uuid, whatever),
> and a password.
> * Introduces a new "profile" system that provides a way to contribute
> extra related fields. Multiple profiles are supported, along with some
> syntactic sugar for dealing with multiple profiles in a reasonably reusable
> way.
>
> And that's about it. I'm deliberately trying to find a middle ground
> between "do the minimum to allow people to move on" and "throw out and
> rewrite django.contrib.auth entirely". I'm not expecting everyone to be
> thrilled by this idea, but I'm hoping that this is "Good Enough" for almost
> everyone.
>
> For more please see the document. Please do try to read the whole thing:
> I've had a few rounds of feedback incorporated already, and there's even an
> FAQ at the end.
>
> I'm not using BDFL fiat here, at least not yet. This is a proposal, and I
> very much want to hear feedback, objections, and alternatives. I'm
> particularly interested in hearing from people who've got complicated auth
> needs and think this absolutely won't work for them.
>
> I *have* reviewed all the other proposals and I'm between -0 and -1 on all
> of them. This means that if you don't like my proposal, you'll probably
> have to come up with a complete *new* idea to have any chance of getting my
> vote.
>
> Thanks!
>
> Jacob
>
> --
> You received this message because you are subscribed to the Google Groups
> "Django developers" group.
> To post to this group, send email to django-developers@googlegroups.com.
> To unsubscribe from this group, send email to
> django-developers+unsubscr...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/django-developers?hl=en.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



django admin missing meta tag for charcter encoding in the head

2012-04-03 Thread Ric
hi,

the default django template need a meta tag for character encoding in
the head



-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: django admin missing meta tag for charcter encoding in the head

2012-04-03 Thread Daniel Moisset
On Tue, Apr 3, 2012 at 12:37 PM, Ric  wrote:
> hi,
>
> the default django template need a meta tag for character encoding in
> the head
>
> 
>

why? the Content-Type should be properly served in the HTTP headers...
(if it isn't, then you have a genuine bug)

Regards,
   D.

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: auth.user refactor: the profile aproach

2012-04-03 Thread Andre Terra
DISCLAIMER: I'm just a hobbyist posting to an experienced developers' list.

I for one really like Jacob's approach.

I may be missing something, but my only concern right now is being able to
infer which profiles are attached to the User model at any given point.
Moreover, I'd like to be able to catch that KeyError exception (which I
would prefer to be wrapped in something more specific like
"MultipleDataError") and handle it appropriately.

For example, drawing from the example in the gist, say I want to allow the
user to change his 'name' for every associated profile he has.
user.data.dict('name').keys() will show me the existing profiles, and I
guess I could use these keys to access every profile... but it doesn't seem
like the ideal solution.

I can see the need for something like user.data.update({'name': 'Joe K.
Smith'}) to forcefully update the name in every profile. In my humble
newbie opinion, there's a lot of syntactic sugar to be added here to make
working with multiple profiles as sweet as we want it to be. Things like
user.profiles, or even defining a 'default' profile that point how
MultipleDataErrors should be resolved.



Cheers,
AT


On Tue, Apr 3, 2012 at 11:28 AM, Alex Ogier  wrote:

> Hi developers,
>
> I have written up a little bit about the alternate proposal that I made a
> while ago, Solution 2a from
> https://code.djangoproject.com/wiki/ContribAuthImprovements
>
> In addition to other arguments, there is a point-by-point breakdown of
> what I feel are the weaknesses in Jacob's proposal.
>
> You can find it at  https://gist.github.com/2289395
>
> Best,
> Alex Ogier
>
>
> On Mon, Apr 2, 2012 at 8:35 PM, Jacob Kaplan-Moss wrote:
>
>>  Hi folks --
>>
>> I've written up a proposal for how *I* would like to address refactoring
>> auth.user: https://gist.github.com/2245327.
>>
>> In essence, this does two things:
>>
>> * Vastly "prunes" the required fields on auth.user. The only things left
>> are an "identifier" (which could be username, email, url, uuid, whatever),
>> and a password.
>> * Introduces a new "profile" system that provides a way to contribute
>> extra related fields. Multiple profiles are supported, along with some
>> syntactic sugar for dealing with multiple profiles in a reasonably reusable
>> way.
>>
>> And that's about it. I'm deliberately trying to find a middle ground
>> between "do the minimum to allow people to move on" and "throw out and
>> rewrite django.contrib.auth entirely". I'm not expecting everyone to be
>> thrilled by this idea, but I'm hoping that this is "Good Enough" for almost
>> everyone.
>>
>> For more please see the document. Please do try to read the whole thing:
>> I've had a few rounds of feedback incorporated already, and there's even an
>> FAQ at the end.
>>
>> I'm not using BDFL fiat here, at least not yet. This is a proposal, and I
>> very much want to hear feedback, objections, and alternatives. I'm
>> particularly interested in hearing from people who've got complicated auth
>> needs and think this absolutely won't work for them.
>>
>> I *have* reviewed all the other proposals and I'm between -0 and -1 on
>> all of them. This means that if you don't like my proposal, you'll probably
>> have to come up with a complete *new* idea to have any chance of getting my
>> vote.
>>
>> Thanks!
>>
>> Jacob
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "Django developers" group.
>> To post to this group, send email to django-developers@googlegroups.com.
>> To unsubscribe from this group, send email to
>> django-developers+unsubscr...@googlegroups.com.
>> For more options, visit this group at
>> http://groups.google.com/group/django-developers?hl=en.
>>
>
>  --
> You received this message because you are subscribed to the Google Groups
> "Django developers" group.
> To post to this group, send email to django-developers@googlegroups.com.
> To unsubscribe from this group, send email to
> django-developers+unsubscr...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/django-developers?hl=en.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: [GSOC 2012] Customizable serialization

2012-04-03 Thread Piotr Grabowski

W dniu 03.04.2012 15:55, Tom Christie pisze:

It breaks the problem down into two very well defined tasks.

1. Convert native datatypes to/from data streams.  (eg. Tastypie's 
serializers 
, 
REST framework's renderers 
 
& parsers 
)
2. Convert complex objects to/from native datatypes. (eg. Tastypie's 
hydrate/dehydate, REST frameworks serializer 
, 
form based deserialization 
)


In your proposal you've understandably addressed model serialization 
in detail, but I (personally) think it'd be worthwhile breaking things 
down a little bit more.

For example, you might consider the following:

1. Define a base API for part (1).  Is it handled by a single class 
with instance methods for converting in each direction, or by 
two separate classes?
I read your code from last year. We have different aproach to 
serialization. Mayby I am wrong with my understanding of two phase 
serialization. You in part (1) don't think about target format 
(xml/json/...). I assumed you have API in part (2) to deal with it.


In my solution user should (but it is not reguired) think about format 
in first phase:


e.g
In present django serialization we have:

For json
fields : {
first_field : ...
second_field : ...

 }

But in xml:
...
..

I don't see how you do it in your proposal. You only specify 'fields' in 
Meta.fields.


In my proposal there is need for two Serializers definition but it's 
simple and one can inherite from other.

I specify JSONSerializer and XMLSerializer for backward compatibility.

In my solution I can provide one Serializer for all formats:

class PKField(Field):

def dehydrate__value__(self, field):
return smart_unicode(self.instance._get_pk_val(), 
strings_only=True)


def hydrate__value__(self, field):
self.instance.set_pk_val(field)


class ModelField(Field):
def dehydrate__value__(self, field):
return smart_unicode(obj._meta)


class AllSerializer(ModelSerializer):
pk = PKField()
model = ModelField()

class Meta:
aliases = {'__fields__' : 'fields'}
relation_serializer = FlatSerializer

If we render it to json we get:
{
pk : ... ,
model : ...,
fields : {

}
}

It's what we want. But in xml:

...
...
only_field_value
...
...


Ups :/


What about formats that are one direction only? (eg. You might 
want to parse HTTP form data, but you're unlikely to want to render it.)
Are formats that are not fully reversible an issue? (eg. Some 
formats [eg csv?] might not have native representations of all the 
python datatypes, and only have string representations.)
Present django solution support only xml json and yaml, so far I 
consider only these formats. If other format can be serialized from my 
native types or deserialized to it, it can be handled.
If some information about object are losed in 
serialization-deserialization then I try construct model only from what 
I get. I won't save it. It's user problem. Mayby he wants to add some 
other informations from request (you mention it in point 7)



Some things I was slightly confused by in your proposal as it stands...

* JSONSerializer subclassing Serializer. (and XMLSerializer 
subclassing JSONSerializer.)
  I'd have thought that if you're using a two phase approach you'd 
keep the complex<->native and native<->data stream APIs totally decoupled.
  JSON serialization doesn't itself have anything to do with how you 
choose to structure the serialization of a complex object, so why 
should it subclass the implementation of that part?

   I hope it's clear now?

* "dehydrate__value__", "hydrate__value__" - what's with the double 
underscore naming?
It should be __value__ - default value returns by field. It is 
special method. If you do in field:

def some_name(...):
return "test"
Then you get field_name : { some_name : test}

But __value__ is special:
field_name : return_of__value__
or field_name : {
some_name : test,
return_of__name__ : return_of __value__
}

But this is theory. I have dehydrate__xxx for serialization xxx 
value. So I should have dehydratevalue__. Ugly :/ So there is value__

It should be rewrite.

* I don't get the '@attribute' decorator.  I think it'd be simpler to 
just have 'fields', 'include', 'exclude'.  If fields is None then use 
the 'default set of fields' + 'include' - 'exclude'.  If fields is not 
None, use that and ignore include/exclude.

Attribute is for xml attribute ...

* I

Re: auth.user refactor: the profile aproach

2012-04-03 Thread Luke Sneeringer
So, after reading this, I think I really only have a couple questions/concerns:

1. What, if anything, is the primary key on the base User model? Is it the 
identifier? If so, can it be specified as the primary key, rather than 
unique=True, db_index=True? If it's not the primary key, is it the usual 
magical id = models.AutoField()?

2. I'm a little nervous about the magical installation of Profile modules -- 
specifically, what happens once this system has been around for one to two 
years and we have a ton of these? I'm imagining a situation where there are 
lots of apps floating around, each with their own Profile subclasses that 
install behind the scenes when you install the app (and which you may or may 
not actually realize up front -- yes, a good developer *should* be aware of 
that, but that doesn't mean they will be...). What happens if a beginner writes 
everything against user.data['name'], and then installs an app that adds a new 
name, which is unordered and magically ends up on top, and therefore introduces 
new, unexpected, and, most importantly, extremely difficult to debug logic 
errors?

I agree with some of the criticisms of swappable user models, but at least the 
developer always knows what he is doing in that case. In this case, the 
behavior of your user model can change in unexpected ways when you do something 
that seems totally unrelated; some code that previously worked might either (1) 
return different data or (2) suddenly raise KeyError.

Perhaps this is the best of bad options. I agree there's a decent bit to be 
argued in favor of it, but can we figure out a less error-prone way for 
user.data to work? Honestly, I think it would be less risky to force everyone 
to write user.admin_profile.name -- it's more typing, but at least it's 
explicit. The current proposal for user.data doesn't actually pass "refuse the 
temptation to guess", because it glosses over the fact that developers *will 
guess* and then their code will stop working after what feels like a completely 
unrelated change.

3. Might I suggest that the Profile model that the admin requires be called 
AdminProfile and not DefaultProfile? It's really an admin need more than 
anything else.


Best Regard,
Luke



On April 2, 2012, at 19:35 , Jacob Kaplan-Moss wrote:

> Hi folks --
> 
> I've written up a proposal for how *I* would like to address refactoring 
> auth.user: https://gist.github.com/2245327.
> 
> In essence, this does two things:
> 
> * Vastly "prunes" the required fields on auth.user. The only things left are 
> an "identifier" (which could be username, email, url, uuid, whatever), and a 
> password.
> * Introduces a new "profile" system that provides a way to contribute extra 
> related fields. Multiple profiles are supported, along with some syntactic 
> sugar for dealing with multiple profiles in a reasonably reusable way.
> 
> And that's about it. I'm deliberately trying to find a middle ground between 
> "do the minimum to allow people to move on" and "throw out and rewrite 
> django.contrib.auth entirely". I'm not expecting everyone to be thrilled by 
> this idea, but I'm hoping that this is "Good Enough" for almost everyone.
> 
> For more please see the document. Please do try to read the whole thing: I've 
> had a few rounds of feedback incorporated already, and there's even an FAQ at 
> the end.
> 
> I'm not using BDFL fiat here, at least not yet. This is a proposal, and I 
> very much want to hear feedback, objections, and alternatives. I'm 
> particularly interested in hearing from people who've got complicated auth 
> needs and think this absolutely won't work for them. 
> 
> I *have* reviewed all the other proposals and I'm between -0 and -1 on all of 
> them. This means that if you don't like my proposal, you'll probably have to 
> come up with a complete *new* idea to have any chance of getting my vote.
> 
> Thanks!
> 
> Jacob
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Django developers" group.
> To post to this group, send email to django-developers@googlegroups.com.
> To unsubscribe from this group, send email to 
> django-developers+unsubscr...@googlegroups.com.
> For more options, visit this group at 
> http://groups.google.com/group/django-developers?hl=en.

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Proposal: upgrading the choices machinery for Django

2012-04-03 Thread Łukasz Langa
A nice HTML rendering of this proposal is available at:
http://lukasz.langa.pl/2/upgrading-choices-machinery-django/



==
Upgrading the choices machinery for Django
==

Specifying choices for form fields and models currently does not do much justice
to the `DRY
`_
philosophy Django is famous for. Everybody seems to either have their own way of
working around it or live with the suboptimal tuple-based pairs. This Django
enhancement proposal presents a comprehensive solution based on an existing
implementation, explaining reasons behind API decisions and their implications
on the framework in general.

Current status
--

The current way of specifying choices for a field is as follows::

  GENDER_CHOICES = (
  (0, 'male'),
  (1, 'female'),
  (2, 'not specified'),
  )

  class User(models.Model):
  gender = models.IntegerField(choices=GENDER_CHOICES)
  
When I then want to implement behaviour which depends on the ``User.gender``
value, I have a couple of possibilities. I've seen all in production code which
makes it all the more scary.

Way 1
~

Use ``get_FIELD_display``::

  GENDER_CHOICES = (
  (0, 'male'),
  (1, 'female'),
  (2, 'not specified'),
  )

  class User(models.Model):
  gender = models.IntegerField(choices=GENDER_CHOICES)

  def greet(self):
  gender = self.get_gender_display()
  if gender == 'male':
  return 'Hi, boy.'
  elif gender == 'female':
  return 'Hello, girl.'
  else:
  return 'Hey there, user!'

This will fail once you start translating the choice descriptions or if you
rename them and is generally brittle. So we have to improve on it by using the
numeric identifiers.

Way 2
~

Use numeric IDs::

  GENDER_CHOICES = (
  (0, _('male')),
  (1, _('female')),
  (2, _('not specified')),
  )

  class User(models.Model):
  gender = models.IntegerField(choices=GENDER_CHOICES,
  default=2)

  def greet(self):
  if self.gender == 0:
  return 'Hi, boy.'
  elif self.gender == 1:
  return 'Hello, girl.'
  else:
  return 'Hey there, user!'

This is just as bad because once the identifiers change, it's not trivial to
grep for existing usage, let alone 3rd party usage. This looks less wrong when
using ``CharFields`` instead of ``IntegerFields`` but the problem stays the
same.  So we have to improve on it by explicitly naming the options.

Way 3
~

Explicit choice values::

  GENDER_MALE = 0
  GENDER_FEMALE = 1
  GENDER_NOT_SPECIFIED = 2

  GENDER_CHOICES = (
  (GENDER_MALE, _('male')),
  (GENDER_FEMALE, _('female')),
  (GENDER_NOT_SPECIFIED, _('not specified')),
  )

  class User(models.Model):
  gender = models.IntegerField(choices=GENDER_CHOICES,
  default=GENDER_NOT_SPECIFIED)

  def greet(self):
  if self.gender == GENDER_MALE:
  return 'Hi, boy.'
  elif self.gender == GENDER_NOT_SPECIFIED:
  return 'Hello, girl.'
  else: return 'Hey there, user!'

This is a saner way but starts getting overly verbose and redundant. You can
improve encapsulation by moving the choices into the ``User`` class but that on
the other hand beats reusability.

The real problem however is that there is no `One Obvious Way To Do It
`_ and newcomers are likely to choose
poorly.

tl;dr or The Gist of It
---

My proposal suggests embracing a solution that is already implemented and tested
with 100% statement coverage. It's easily installable::

  pip install dj.choices

and lets you write the above example as::

  from dj.choices import Choices, Choice

  class Gender(Choices):
  male = Choice("male")
  female = Choice("female")
  not_specified = Choice("not specified")

  class User(models.Model):
  gender = models.IntegerField(choices=Gender(),
  default=Gender.not_specified.id)

  def greet(self):
  gender = Gender.from_id(self.gender)
  if gender == Gender.male:
  return 'Hi, boy.'
  elif gender == Gender.female:
  return 'Hello, girl.'
  else:
  return 'Hey there, user!'

or using the provided ``ChoiceField`` (fully compatible with
``IntegerFields``)::

  from dj.choices import Choices, Choice
  from dj.choices.fields import ChoiceField

  class Gender(Choices):
  male = Choice("male")
  female = Choice("female")
  not_specified = Choice("not specified")

  class User(models.Model):
  gender = ChoiceField(choices=Gender,
  default=Gender.not_specified)

  def greet(self):
  if self.gender == Gender.male:
  return 'Hi, boy.'
  elif self.gende

Re: auth.user refactor: the profile aproach

2012-04-03 Thread Carl Meyer
On 04/03/2012 08:28 AM, Alex Ogier wrote:
> I have written up a little bit about the alternate proposal that I made
> a while ago, Solution 2a
> from https://code.djangoproject.com/wiki/ContribAuthImprovements
> 
> In addition to other arguments, there is a point-by-point breakdown of
> what I feel are the weaknesses in Jacob's proposal.
> 
> You can find it at  https://gist.github.com/2289395 

Since I weighed in with a +1 on the linked-profiles approach, I should
say that I also find this proposal pretty compelling, and would be happy
to see us go either way. After reflecting on it a bit I think on balance
I prefer this proposal, for the following reasons:

1. Requires zero migration from people with existing projects who are
happy with the existing contrib.auth.User model. I think this is a big
plus: all the other proposals require every single installed Django
codebase to perform a migration.

2. Introduces fewer new-and-different one-off concepts into Django (the
data__ ORM special case, the automatic select_related special case, the
automatic collection of profile fields into user.data...). This also
translates into significantly less implementation work and less new
code, which is another big plus - we want something that'll actually get
done and not introduce a bunch of new code we need to maintain.

By the way, I took the liberty of removing from the wiki page the
references to models/settings circular dependencies, because AFAIK the
statements made about it on the wiki page were simply incorrect.
Importing settings does _not_ immediately loop through INSTALLED_APPS
and load every models file (that only happens if you run a management
command that performs model validation, and even then it happens only
after settings are fully loaded). And "from django.db import models"
itself imports settings, so if there were such a circular dependency
problem, every models.py in existence would already be suffering from
it. I frequently refer to settings in models.py and it does not cause a
problem. If anyone can provide sample code demonstrating that this is
actually a problem, feel free to correct me!

Carl



signature.asc
Description: OpenPGP digital signature


Re: auth.user refactor: the profile aproach

2012-04-03 Thread Adrian Holovaty
On Tue, Apr 3, 2012 at 9:28 AM, Alex Ogier  wrote:
> I have written up a little bit about the alternate proposal that I made a
> while ago, Solution 2a
> from https://code.djangoproject.com/wiki/ContribAuthImprovements

I just now got around to reading Jacob's solution and Alex's solution.
Thanks to everybody for the thoughts and impassioned debate so far.
Here's my take on it.

First, some background: I haven't used the built-in User module in
several years. I always write my own User model from scratch -- it's
so nice and clean. Want a twitter_username field? Just add it. No need
to add a convoluted foreign key or (oh god) one-to-one relationship to
some other table.

To me, this is the Right Way to do things. The framework should bend
to my needs, I shouldn't bend to the framework's needs.

Also, profile modules need to die. They needed to die circa 2006.

So, with that in mind, I've got to say I prefer Alex's solution. I
really think the right way to do it is:

1. Let you create your own User model, with whichever fields you want.

2. Provide a way to tell Django which model you're using for that.

3. In your own code, just deal with that model like you deal with any
other one. No need to jump through hoops.

4. Third-party models should be changed to use something like "user =
UserField()", which would automatically create a foreign key to the
registered User model. If you change your registered User model after
you've created those third-party tables, you're in for trouble. Don't
do that.

5. Django provides some generic APIs for getting at the registered
user. Example: a middleware that sets request.user based on the
current session.

6. Given that some third-party apps will likely want to get access to
common attributes of a User -- notably, email address -- there could
be some sort of standard interface that User models need to adhere to
(duck typing). So, a custom User model would say "for this User model,
the email address is stored in the database field called 'email'" --
or "this User model doesn't have email addresses."

I chatted about this with Jacob on IRC, and we reached consensus on
this approach. I'd like to get moving on this and would be happy to
take it on myself, starting next week.

Adrian

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: auth.user refactor: the profile aproach

2012-04-03 Thread Daniel Sokolowski
Alex I have looked over your proposal and I agree on both your concerns with 
LFK, and Jacob’s approach; however I still find the profile approach is the 
most flexible solution. 

Correct me if I’m wrong but both LFK or a swappable user model approach like 
your fail to address issue of extensibility. If today my project is authorizing 
with username and password and tomorrow I wish to add OpenAuth then my User 
model is replaced, whereas with Jacobs approach I add another profile model, 
yes? What about auth apps, you could only use one, with profiles many could co 
exist; one for Facebook, Twitter, etc. 

Your point 4 claiming it’s undiscoverable is not entirely true, AUTH_PROFILE 
setting can be examined just as apps examine INSTALLED_APPS settings at run 
time. Your point 2 that being able to change the functionality so quickly is 
actually superior in my mind, it’s a lot more work to do a schema migration 
then the creation a of  new profile table.  Points 5 and 3 are good points and 
remind that there is no perfect solution to new auth.

To sum up I am curious to know how your approach handles additional user data 
and authorization schemes. 

From: Alex Ogier 
Sent: Tuesday, April 03, 2012 10:28 AM
To: django-developers@googlegroups.com 
Subject: Re: auth.user refactor: the profile aproach

Hi developers, 

I have written up a little bit about the alternate proposal that I made a while 
ago, Solution 2a from 
https://code.djangoproject.com/wiki/ContribAuthImprovements

In addition to other arguments, there is a point-by-point breakdown of what I 
feel are the weaknesses in Jacob's proposal.

You can find it at  https://gist.github.com/2289395 

Best,
Alex Ogier


On Mon, Apr 2, 2012 at 8:35 PM, Jacob Kaplan-Moss  wrote:

  Hi folks -- 

  I've written up a proposal for how *I* would like to address refactoring 
auth.user: https://gist.github.com/2245327.


  In essence, this does two things:


  * Vastly "prunes" the required fields on auth.user. The only things left are 
an "identifier" (which could be username, email, url, uuid, whatever), and a 
password.
  * Introduces a new "profile" system that provides a way to contribute extra 
related fields. Multiple profiles are supported, along with some syntactic 
sugar for dealing with multiple profiles in a reasonably reusable way.


  And that's about it. I'm deliberately trying to find a middle ground between 
"do the minimum to allow people to move on" and "throw out and rewrite 
django.contrib.auth entirely". I'm not expecting everyone to be thrilled by 
this idea, but I'm hoping that this is "Good Enough" for almost everyone.


  For more please see the document. Please do try to read the whole thing: I've 
had a few rounds of feedback incorporated already, and there's even an FAQ at 
the end.


  I'm not using BDFL fiat here, at least not yet. This is a proposal, and I 
very much want to hear feedback, objections, and alternatives. I'm particularly 
interested in hearing from people who've got complicated auth needs and think 
this absolutely won't work for them. 


  I *have* reviewed all the other proposals and I'm between -0 and -1 on all of 
them. This means that if you don't like my proposal, you'll probably have to 
come up with a complete *new* idea to have any chance of getting my vote.


  Thanks!


  Jacob
  -- 
  You received this message because you are subscribed to the Google Groups 
"Django developers" group.
  To post to this group, send email to django-developers@googlegroups.com.
  To unsubscribe from this group, send email to 
mailto:django-developers%2bunsubscr...@googlegroups.com.
  For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.


-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: auth.user refactor: the profile aproach

2012-04-03 Thread Donald Stufft
Like Carl I was +1 on Profiles and I'm now leaning towards the Swappable User 
Models.  

It's explicit (it only changes when you change the USER_MODEL setting).

It's Duck Typing which is Idiomatic in Python. ("This app depends on a user 
model that defines ``email`").

If you wish to add OpenID you'd make your UserModel quack like an OpenID Duck, 
as well as Quack like a Username/Password Duck.  


On Tuesday, April 3, 2012 at 4:34 PM, Daniel Sokolowski wrote:

> Alex I have looked over your proposal and I agree on both your concerns with 
> LFK, and Jacob’s approach; however I still find the profile approach is the 
> most flexible solution.  
>   
> Correct me if I’m wrong but both LFK or a swappable user model approach like 
> your fail to address issue of extensibility. If today my project is 
> authorizing with username and password and tomorrow I wish to add OpenAuth 
> then my User model is replaced, whereas with Jacobs approach I add another 
> profile model, yes? What about auth apps, you could only use one, with 
> profiles many could co exist; one for Facebook, Twitter, etc.  
>   
> Your point 4 claiming it’s undiscoverable is not entirely true, AUTH_PROFILE 
> setting can be examined just as apps examine INSTALLED_APPS settings at run 
> time. Your point 2 that being able to change the functionality so quickly is 
> actually superior in my mind, it’s a lot more work to do a schema migration 
> then the creation a of  new profile table.  Points 5 and 3 are good points 
> and remind that there is no perfect solution to new auth.
>   
> To sum up I am curious to know how your approach handles additional user data 
> and authorization schemes.  
>   
> From: Alex Ogier (mailto:alex.og...@gmail.com)  
> Sent: Tuesday, April 03, 2012 10:28 AM
> To: django-developers@googlegroups.com 
> (mailto:django-developers@googlegroups.com)  
> Subject: Re: auth.user refactor: the profile aproach
>  
>  
>   
>  
> Hi developers,  
>   
> I have written up a little bit about the alternate proposal that I made a 
> while ago, Solution 2a from 
> https://code.djangoproject.com/wiki/ContribAuthImprovements
>   
> In addition to other arguments, there is a point-by-point breakdown of what I 
> feel are the weaknesses in Jacob's proposal.
>   
> You can find it at  https://gist.github.com/2289395  
>   
> Best,
> Alex Ogier
>  
> On Mon, Apr 2, 2012 at 8:35 PM, Jacob Kaplan-Moss  (mailto:ja...@jacobian.org)> wrote:
> > Hi folks --  
> >   
> > I've written up a proposal for how *I* would like to address refactoring 
> > auth.user: https://gist.github.com/2245327.
> >  
> > In essence, this does two things:  
> >  
> > * Vastly "prunes" the required fields on auth.user. The only things left 
> > are an "identifier" (which could be username, email, url, uuid, whatever), 
> > and a password.  
> > * Introduces a new "profile" system that provides a way to contribute extra 
> > related fields. Multiple profiles are supported, along with some syntactic 
> > sugar for dealing with multiple profiles in a reasonably reusable way.
> >  
> > And that's about it. I'm deliberately trying to find a middle ground 
> > between "do the minimum to allow people to move on" and "throw out and 
> > rewrite django.contrib.auth entirely". I'm not expecting everyone to be 
> > thrilled by this idea, but I'm hoping that this is "Good Enough" for almost 
> > everyone.  
> >  
> > For more please see the document. Please do try to read the whole thing: 
> > I've had a few rounds of feedback incorporated already, and there's even an 
> > FAQ at the end.  
> >  
> > I'm not using BDFL fiat here, at least not yet. This is a proposal, and I 
> > very much want to hear feedback, objections, and alternatives. I'm 
> > particularly interested in hearing from people who've got complicated auth 
> > needs and think this absolutely won't work for them.  
> >  
> > I *have* reviewed all the other proposals and I'm between -0 and -1 on all 
> > of them. This means that if you don't like my proposal, you'll probably 
> > have to come up with a complete *new* idea to have any chance of getting my 
> > vote.  
> >  
> > Thanks!  
> >  
> > Jacob --  
> > You received this message because you are subscribed to the Google Groups 
> > "Django developers" group.
> > To post to this group, send email to django-developers@googlegroups.com 
> > (mailto:django-developers@googlegroups.com).
> > To unsubscribe from this group, send email to 
> > mailto:django-developers%2bunsubscr...@googlegroups.com.
> > For more options, visit this group at 
> > http://groups.google.com/group/django-developers?hl=en.
>  --  
> You received this message because you are subscribed to the Google Groups 
> "Django developers" group.
> To post to this group, send email to django-developers@googlegroups.com 
> (mailto:django-developers@googlegroups.com).
> To unsubscribe from this group, send email to 
> django-developers+unsubscr...@googlegroups.com 
> (mailto:django-developers+unsub

Re: auth.user refactor: the profile aproach

2012-04-03 Thread Carl Meyer
On 04/03/2012 02:34 PM, Daniel Sokolowski wrote:
> Correct me if I’m wrong but both LFK or a swappable user model approach
> like your fail to address issue of extensibility. If today my project is
> authorizing with username and password and tomorrow I wish to add
> OpenAuth then my User model is replaced, whereas with Jacobs approach I
> add another profile model, yes? What about auth apps, you could only use
> one, with profiles many could co exist; one for Facebook, Twitter, etc.

You would add whatever authorization fields you need to your single user
model. If you add new kinds of authorization that require new fields on
the user model, you'd do a schema migration (just like with any other
modification to any other model).

A third-party app that wants to provide, say, Facebook integration,
could either do its own model with a one-to-one to user (nothing is
going to suddenly prevent that approach, it just won't have any extra
sugar around it), or could provide an abstract base class that your user
model can inherit from that includes the needed fields, or could just
document "to use this app, your user model must have these fields: ..."
and let you do it yourself.

Carl



signature.asc
Description: OpenPGP digital signature


Re: auth.user refactor: the profile aproach

2012-04-03 Thread Luke Sneeringer
+1. Also, I'd like to help. :)

L

On April 3, 2012, at 15:34 , Adrian Holovaty wrote:

> On Tue, Apr 3, 2012 at 9:28 AM, Alex Ogier  wrote:
>> I have written up a little bit about the alternate proposal that I made a
>> while ago, Solution 2a
>> from https://code.djangoproject.com/wiki/ContribAuthImprovements
> 
> I just now got around to reading Jacob's solution and Alex's solution.
> Thanks to everybody for the thoughts and impassioned debate so far.
> Here's my take on it.
> 
> First, some background: I haven't used the built-in User module in
> several years. I always write my own User model from scratch -- it's
> so nice and clean. Want a twitter_username field? Just add it. No need
> to add a convoluted foreign key or (oh god) one-to-one relationship to
> some other table.
> 
> To me, this is the Right Way to do things. The framework should bend
> to my needs, I shouldn't bend to the framework's needs.
> 
> Also, profile modules need to die. They needed to die circa 2006.
> 
> So, with that in mind, I've got to say I prefer Alex's solution. I
> really think the right way to do it is:
> 
> 1. Let you create your own User model, with whichever fields you want.
> 
> 2. Provide a way to tell Django which model you're using for that.
> 
> 3. In your own code, just deal with that model like you deal with any
> other one. No need to jump through hoops.
> 
> 4. Third-party models should be changed to use something like "user =
> UserField()", which would automatically create a foreign key to the
> registered User model. If you change your registered User model after
> you've created those third-party tables, you're in for trouble. Don't
> do that.
> 
> 5. Django provides some generic APIs for getting at the registered
> user. Example: a middleware that sets request.user based on the
> current session.
> 
> 6. Given that some third-party apps will likely want to get access to
> common attributes of a User -- notably, email address -- there could
> be some sort of standard interface that User models need to adhere to
> (duck typing). So, a custom User model would say "for this User model,
> the email address is stored in the database field called 'email'" --
> or "this User model doesn't have email addresses."
> 
> I chatted about this with Jacob on IRC, and we reached consensus on
> this approach. I'd like to get moving on this and would be happy to
> take it on myself, starting next week.
> 
> Adrian
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Django developers" group.
> To post to this group, send email to django-developers@googlegroups.com.
> To unsubscribe from this group, send email to 
> django-developers+unsubscr...@googlegroups.com.
> For more options, visit this group at 
> http://groups.google.com/group/django-developers?hl=en.
> 

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: auth.user refactor: the profile aproach

2012-04-03 Thread Alex Ogier
Thanks for the response, Adrian.


> 4. Third-party models should be changed to use something like "user =
> UserField()", which would automatically create a foreign key to the
> registered User model. If you change your registered User model after
> you've created those third-party tables, you're in for trouble. Don't
> do that.
>
> 5. Django provides some generic APIs for getting at the registered
> user. Example: a middleware that sets request.user based on the
> current session.
>

I think convenience methods are nice and all, but we should be careful of
making "The Registered User(tm)" too much of a baked-in concept. Ian Lewis
made a great point a few weeks ago: There are domains in which it is
frankly inappropriate for various authenticated users to mix in the same
database table with the same uniqueness constraints. Maybe you run a
medical record management site, and some of your users are administrative
staff and doctors, and some are patients. Sure, you could manage this by
having a unified model containing everything, and carefully validating with
an "is_doctor" field the way contrib.admin handles "is_admin," but it might
be more appropriate to have separate models. It becomes much easier to
express authorization constraints such as, "As a hospital administrator,
Ms. Sally Johnson is authorized to view the patient list of Dr. John Smith,
but *absolutely not* his record as a patient himself," or "Patients like
Dr. John Smith can be authenticated via Facebook Connect, but doctors need
to be authenticated via our internal LDAP." You can have login ModelForms
for doctors that log in to doctor records and the Django admin site, and
login ModelForms for patients that let them view their own records through
the frontend.

Obviously supporting multiple user models isn't something that should be a
priority for Django, but locking people out of the choice seems unwise,
when we can get the option "for free": just let authentication backends
return any authenticated object at all to add as request.user. Python's
duck typing will get you the rest of the way, except for those persnickety
tables that absolutely must have a specific concrete table to foreignkey
on. We already do something similar for AnonymousUsers, exposing a common
interface at request.user that isn't backed up by the canonical User table.
Generalizing that is A Good Idea in my opinion.

Anyways I look forward to seeing how this progresses. I'd love to be a part
of making this happen. Would you like me to turn my work on breaking up
auth.User into reusable chunks into a ticket on trac? I think it makes
sense to merge no matter what we decide on for specific settings and access
mechanisms to developer-defined users.

Best,
Alex Ogier

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: auth.user refactor: the profile aproach

2012-04-03 Thread Russell Keith-Magee

On 04/04/2012, at 4:31 AM, Carl Meyer wrote:
> 
> By the way, I took the liberty of removing from the wiki page the
> references to models/settings circular dependencies, because AFAIK the
> statements made about it on the wiki page were simply incorrect.
> Importing settings does _not_ immediately loop through INSTALLED_APPS
> and load every models file (that only happens if you run a management
> command that performs model validation, and even then it happens only
> after settings are fully loaded). And "from django.db import models"
> itself imports settings, so if there were such a circular dependency
> problem, every models.py in existence would already be suffering from
> it. I frequently refer to settings in models.py and it does not cause a
> problem. If anyone can provide sample code demonstrating that this is
> actually a problem, feel free to correct me!

Those comments were my doing. I swear that at some point in Django's past, 
importing settings in models was a source of problems. However, the fact that 
django.db.models clearly imports settings indicates that regardless of whether 
this problem existed in the past, it certainly isn't the case any more.

Yours,
Russ Magee %-)

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: auth.user refactor: the profile aproach

2012-04-03 Thread Russell Keith-Magee

On 04/04/2012, at 4:42 AM, Carl Meyer wrote:

> On 04/03/2012 02:34 PM, Daniel Sokolowski wrote:
>> Correct me if I’m wrong but both LFK or a swappable user model approach
>> like your fail to address issue of extensibility. If today my project is
>> authorizing with username and password and tomorrow I wish to add
>> OpenAuth then my User model is replaced, whereas with Jacobs approach I
>> add another profile model, yes? What about auth apps, you could only use
>> one, with profiles many could co exist; one for Facebook, Twitter, etc.
> 
> You would add whatever authorization fields you need to your single user
> model. If you add new kinds of authorization that require new fields on
> the user model, you'd do a schema migration (just like with any other
> modification to any other model).
> 
> A third-party app that wants to provide, say, Facebook integration,
> could either do its own model with a one-to-one to user (nothing is
> going to suddenly prevent that approach, it just won't have any extra
> sugar around it), or could provide an abstract base class that your user
> model can inherit from that includes the needed fields, or could just
> document "to use this app, your user model must have these fields: ..."
> and let you do it yourself.

Extending on this -- User model requirements should be encoded as part of an 
integration test suite. 

As an example of best practice, django.contrib.admin should implement a 
UserPropertiesTest that checks that the current USER_MODEL has an email field, 
and a get_permissions method, and so on. That way, if you swap in a user model 
that doesn't have the properties that the admin requires, it will get flagged 
as a issue during testing.

This should, of course, be backed up with a clear documentation of exactly what 
type of User-duck Django's admin requires.

Yours,
Russ Magee %-)

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: auth.user refactor: the profile aproach

2012-04-03 Thread Russell Keith-Magee

On 04/04/2012, at 4:34 AM, Adrian Holovaty wrote:

> On Tue, Apr 3, 2012 at 9:28 AM, Alex Ogier  wrote:
>> I have written up a little bit about the alternate proposal that I made a
>> while ago, Solution 2a
>> from https://code.djangoproject.com/wiki/ContribAuthImprovements
> 
> ...
> 4. Third-party models should be changed to use something like "user =
> UserField()", which would automatically create a foreign key to the
> registered User model. If you change your registered User model after
> you've created those third-party tables, you're in for trouble. Don't
> do that.
> 

My only concern about this approach is making a special case of swappable 
Users. There's at least one other example of a swappable model in Django's core 
-- the Comments model -- and I have no doubt that we could find other examples 
with a quick survey.

If we're going down the path of swappable models, I'd rather set up the 
infrastructure to solve the *general* problem of swappable models, rather than 
just swappable *user* models specifically. 

If this required a massive increase in the effort required, I can see how 
practicality would determine that we just solve the immediate problem. However, 
in this case, it's really just a matter of avoiding User-specific naming on 4 
features:

 a) Specifying the model that can be swapped. 

This is just the name of the setting. USER_MODEL is fine by itself, and has 
obvious analogs with other models. However, an alternate way of spelling the 
same thing would be to have a single setting for all swappable models:

SWAPPABLE_MODELS = {
'user': 'myauth.SuperDuperUser',
'comment': 'comments.Comment',
}

in which you can define any extensible model, and provide a convenient key 
(e.g., 'user') to identify the value for that model.

 b) Preventing the "default" model from being added to the app cache, or 
synchronized to the database

contrib.auth is going to need ship with a User model, but we really don't want 
an auth_user table to be created, or get_model(auth,'User') to resolve, if the 
default User isn't being used. Same goes for any other swappable model.

Rather than make a special case of User inside syncdb, or nesting model 
definitions in if blocks, lets add a "swappable" attribute to Meta. If 
swappable is defined, syncdb checks the contents of SWAPPABLE_MODELS to see if 
this model has been substituted; if it has, then the table isn't created, and 
the model isn't added to the app cache. The value of pluggable can match the 
key in SWAPPABLE_MODELS (so auth.User would define swappable='user', following 
the previous example)

This can also act as a safety mechanism; if a developer has an app that 
contains a ForeignKey(User), and the User model has been swapped out, this can 
now raise a validation warning (notifying the developer that the User model 
could potentially be swapped out) or error (in the case where the model *has* 
been swapped out).

 c) Providing a way to specify foreign keys to that model

Rather than introduce a User-specific UserField(), introduce a generic 
LazyForeignKey('user') - both of which are effectively just 
ForeignKey(settings.) anyway.

 d) Provide a way to discover the current user model

Rather than have auth.get_user_model(), leverage the existing app cache. We 
already have get_model(); it wouldn't be too hard to add a 
get_swappable_model('user'). 

> 6. Given that some third-party apps will likely want to get access to
> common attributes of a User -- notably, email address -- there could
> be some sort of standard interface that User models need to adhere to
> (duck typing). So, a custom User model would say "for this User model,
> the email address is stored in the database field called 'email'" --
> or "this User model doesn't have email addresses."
> 

As I've noted elsewhere, this can be both a documentation issue, and backed up 
by an integration test. As a longer term goal, if someone ever takes the bait 
and does the Validation refactor for the GSoC (hint hint), it could also be 
extracted as a validation condition for an app.

Yours,
Russ Magee %-)


-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: auth.user refactor: the profile aproach

2012-04-03 Thread Eric Florenzano
I completely agree with Adrian's proposal, with these amendments suggested 
by Russell in order to build something slightly more generic, like 
LazyForeignKey, instead of UserField.  In fact, a UserField coud end up 
being provided as a subclass of LazyForeignKey with a default name provided 
(e.g. 'user') and any other user-domain-specific customizations needed.

Thanks,
Eric Florenzano

>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/django-developers/-/h1uVd02e7owJ.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.