extending the user model

83 views
Skip to first unread message

li

unread,
Jun 24, 2011, 8:34:01 AM6/24/11
to tipfy
Hello,

I'm playing with appengine and I spent the last two days trying to
solve what should have been a <simple> task: add an extra property to
a user record. I'm very new to python and appengine and for sure there
is something I'm missing; I read all the docs/posts/discussions I
could find on the subject but with no success.
This is a common operation, it should have been documented somewhere,
right?

this is (the crap?) what I have for now (not working). It's based
mainly on the article http://www.b-list.org/weblog/2006/jun/06/django-tips-extending-user-model/

in config.py:
AUTH_PROFILE_MODULE = 'myapp.UserProfile'

in apps/myapp/mymodels.py
from django.db import models
#from django.contrib.auth.models import User
from tipfy.ext.auth.model import User

class UserProfile(models.Model):
user = models.ForeignKey('tipfy.ext.auth.model.User',
unique=True, related_name='profile')
bipme = models.IntegerField(default=2)


in apps/myapp/handlers.py
...
from apps.myapp.mymodels import UserProfile
...
class RegisterHandler(BaseHandler):
def post(self, **kwargs):
redirect_url = self.redirect_path()

if self.auth_current_user:
# User is already registered, so don't process the signup
form.
return redirect(redirect_url)


if self.form.validate():
username = self.form.username.data
email = self.form.email.data
password = self.form.password.data
password_confirm = self.form.password_confirm.data


if password != password_confirm:
self.set_message('error', "Password confirmation
didn't match.",
life=None)
return self.get(**kwargs)

auth_id = 'own|%s' % username
user = self.auth_create_user(username, auth_id,
password=password, email=email)
if user:
self.auth_set_session(user.auth_id, user.session_id,
'1')
profile = UserProfile(user=user, bipme=2)
profile.save()
self.set_message('success', 'You are now registered. '
'Welcome!', flash=True, life=5)
return redirect(redirect_url)
else:
self.set_message('error', 'This nickname is already '
'registered.', life=None)
return self.get(**kwargs)


self.set_message('error', 'A problem occurred. Please correct
the '
'errors listed in the form.', life=None)
return self.get(**kwargs)
############

The last error is: Invalid value: 'user' should be a
tipfy.ext.auth.model.User instance, not a <class
'tipfy.ext.auth.model.User'> (for line reading "profile =
UserProfile(user=user, bipme=2)")
but "user" IS an instance, right?

What is the best method to solve this problem?
Thanks,
Li

Kyle Finley

unread,
Jun 25, 2011, 5:41:48 AM6/25/11
to ti...@googlegroups.com
Li,

Your on the right track.

By default tipfy uses Google App Engine models not Django Models which can be a little confusing.

Here's the changes you would need to make:

Existing Code

# in config.py:
## this is not need with tipfy
#AUTH_PROFILE_MODULE = 'myapp.UserProfile'

# in apps/myapp/mymodels.py
## this is not need
#from django.db import models
# use App Engine Models instead
from google.appengine.ext import db
#from django.contrib.auth.models import User
from tipfy.ext.auth.model import User

class UserProfile(db.Model):
    # Use ReferenceProperty Here
    user = db.ReferenceProperty(User)
    bipme = db.IntegerProperty(default=2)

My Recommendation
Instead of creating another entity group for
the profile You can actually just extend the
User Class then you would import your User.

# in apps/myapp/mymodels.py
from tipfy.ext.auth.model import User

class MyUser(User):
    # All of the Properies from
    # tipfy.ext.auth.model.User will be
    # included all you need to add is your
    # bipme property.
    bipme = db.IntegerProperty(default=2)

    
# in apps/myapp/handlers.py
from apps.myapp.mymodels import MyUser

# ... ...
-----------------------------------------------------------------------

Another option
If you really want to use Django Models on
App Engine. Check out django-nonrel
This allows use of native Django Models in 
App Engine ( What you were doing ). 

Also with tipfy I recommend using 1.0b. 
There have been substancial changes and it
woud be worth it to upgrade before you get to
far into your project.


Let me know if you have any questions,

Kyle Finley


Liviu Văsuț

unread,
Jun 27, 2011, 10:39:46 AM6/27/11
to ti...@googlegroups.com
Thanks Kyle for your answer,

I can live without django, I guess. Like I said, as far as
appengine/python goes, I'm a noob; any framework I'll choose will require
some learning effort :).
I did update both tipfy and appengine sdk. Sadly, the update broke a lot
of things; I solved a lot of them today (found a good migration guide here
http://tipfy.googlecode.com/hg/docs/source/guide/migrating.rst) but I'm
currently stuck with something I can't fix...

I worked on the multi auth example
(http://code.google.com/p/tipfy/source/browse/examples/?r=7ef044524a3087ffcdc865b30e0c87478877db4a#examples%2Fauth),
and there is a _form_macros.html that is giving me the blues :). I get

File "/home/li/dev/myapp/app/templates/_form_macros.html", line 4, in
template
<abbr title="{{ _('This field is required.') }}">*</abbr>
UndefinedError: '_' is undefined

I did some google-ing but no luck so far.

So I can't tell if the corrections you suggested work although I'm looking
forward to test them. I'll try to fix the macro issue and get back to you.

Thanks again for your help,
Li


--
Using Opera's revolutionary email client: http://www.opera.com/mail/ on
Fedora 15

Kyle Finley

unread,
Jun 27, 2011, 4:02:36 PM6/27/11
to ti...@googlegroups.com
Li,

Try Adding this:

# config.py

config['tipfyext.jinja2'] = {
    'environment_args': {
        'autoescape': True,
        'extensions': [
            'jinja2.ext.autoescape',
            'jinja2.ext.i18n',
            'jinja2.ext.with_'
        ],
    },
}


#####

This will add translation support http://jinja.pocoo.org/docs/extensions/#i18n-extension and define _() in Jinja2 templates and macros.

If that doesn't work let me know, 


Kyle

Liviu Văsuț

unread,
Jun 28, 2011, 3:10:30 AM6/28/11
to ti...@googlegroups.com
Hi Kyle,

your code works ( thanks :) ), but I'm a little confused. Translation is
applied both in the template and the program code? I'm not going to
implement translation probably, but I'd just like to know. And these
extensions, like jinja2, can be used only with tipfy or they are
independent modules that can be used in any project through an interface
of some kind?

Meanwhile, I'm still fixing errors after the upgrade...

Kyle Finley

unread,
Jun 28, 2011, 3:45:42 AM6/28/11
to ti...@googlegroups.com

Hi Li,

Response inline...


On Tuesday, June 28, 2011 2:10:30 AM UTC-5, li wrote:
Hi Kyle,

your code works ( thanks :) ), but I'm a little confused. Translation is  
applied both in the template and the program code? I'm not going to  
implement translation probably, but I'd just like to know.

Correct, the majority of translating occurs in the templates. I *believe* you can also translated in the handlers.py, then pass the translated text to the template. 

And these  
extensions, like jinja2, can be used only with tipfy or they are  
independent modules that can be used in any project through an interface  
of some kind?

Jinja2 (http://jinja.pocoo.org/), Werkzeurg (http://werkzeug.pocoo.org/), Bable (http://babel.edgewall.org/) among others, are independent modules  that a number of python web frameworks use. 

Meanwhile, I'm still fixing errors after the upgrade...

Good luck, if you get stuck on anything, be sure to post it, if I can help you out I will. 

Kyle 

Liviu Văsuț

unread,
Jun 30, 2011, 2:48:52 AM6/30/11
to ti...@googlegroups.com
Thanks for the clear-ups. Here comes another:

I downloaded a fresh copy of the auth example because every error I
managed to fix was followed by another. So, in this clean project I added
the file mymodels.py
### mymodels.py ###
from tipfy.appengine.auth.model import User
#from tipfy.ext.auth.model import User
from google.appengine.ext import db

class MyUser(User):
bipme = db.IntegerProperty(default=2)
####

Note that I replaced tipfy.ext.auth.model with the line recommended in the
migration instructions
(http://tipfy.googlecode.com/hg/docs/source/guide/migrating.rst)

Now, I thought the RegisterHandler should use the new model - MyUser - but
I have no idea how:
### handlers.py ###
...
class RegisterHandler(BaseHandler):
...
user = self.auth.create_user(username, auth_id, password=password) #
here, somehow, should MyUser be inserted, right??
###
And I'm guessing (from previous experience with other programming
languages) that everywhere else self.auth.user should be replaced somehow
by a reference to MyUser..., or self.auth.user should be pointing already
to a MyUser object?!

This is so confusing and hard to untangle without a proper documentation.
I sure did choose a good moment to learn this stuff, didn't I? :)

Kyle Finley

unread,
Jun 30, 2011, 4:02:07 AM6/30/11
to ti...@googlegroups.com
Your absolutely right, sorry I didn't include that part.

### config.py ###

# set this to the location of your model
config['tipfy.auth'] = {
    'user_model': 'path.to.mymodels.MyUser',
}

# Some additional setting just incase there not already in your config
config['tipfy'] = {
    'auth_store_class': 'tipfy.auth.MultiAuthStore',
}

config['tipfy.sessions'] = {
    'secret_key': 'CHANGE_THIS_TO_SOME_RANDOM_STRING',
}

###

Let me know if that doesn't work,

Kyle

Liviu Văsuț

unread,
Jul 1, 2011, 12:36:02 AM7/1/11
to ti...@googlegroups.com
Well Kyle,
that was it, everything works just fine now. MyUser appears correctly in
the datastore and I can access and modify the properties.

What can I say? You've been a real friend on this thread, thanks a bunch!

I see there is a lot of bubbling around moving tipfy forward. I'm very new
here, but I have already grew fond of it. So, I was thinking, if not too
bold, to contribute with a documentation page summing up your suggestions
about extending the user model. Many of the users complain about the
documentation in general and I myself haven't found answers for many of my
questions. There are few applications I wrote (not with tipfy :) ) where a
bare user model would have sufficed, so I believe, this being a frequent
operation, explaining it would help many newcomers to tipfy like me.

Thanks again for all your help, I really appreciate it.

Kyle Finley

unread,
Jul 1, 2011, 7:10:55 PM7/1/11
to ti...@googlegroups.com

Li,

I'm glad that you've gotten everything working.

Your right about custom users that would be a helpful wiki page.

- Kyle

Reply all
Reply to author
Forward
0 new messages