S
S
S Pankov2011-04-30 19:54:32
Django
S Pankov, 2011-04-30 19:54:32

Django User Model Extension - AUTH_PROFILE_MODULE

There is a model.
class Team(models.Model):
name = models.CharField(max_length=25, unique=True)

def __unicode__(self):
return self.name

class UserProfile(models.Model):
user = models.ForeignKey(User, unique= True)
team = models.ForeignKey(Team, unique=True)

settings.py:
AUTH_PROFILE_MODULE = 'project.pm.UserProfile'

views.py
if request.method == 'POST':
r = RegisterForm(request.POST)
if r .is_valid():
team = Team(name=request.POST.get('team'))
team.save()
user = User.objects.create_user(username=request.POST.get('email'),
email= request.POST.get('email'),
password=request.POST.get('password'
user.get_profile.team = team.id
user.save()

Fails with an error while saving team
AttributeError at /register
'instancemethod' object has no attribute 'team'

There are actually two questions. The first is how to run normally what I gave above, and the second is how to make it more beautiful in django style.
ps Well, I'm new to Django, I've only read the docs and looked at a couple of tutorials.

Answer the question

In order to leave comments, you need to log in

5 answer(s)
M
marazmiki, 2011-04-30
@marazmiki

I do not advise you to normally run what you wrote: there are too many ideological errors.
First, you are not validating user input. Two examples: you have a Teamunique index on the field in your model name. If the user enters a command name in the POST form that already exists, a database error will be thrown. A similar situation with User.
Second, you create User, but you don't create UserProfile. It will not be created itself, therefore, the call user.get_profile()(by the way, you didn’t have parentheses, hence AttributeError).
Thirdly, you tried in the foreign key field, which should take the model object, trying to pass an integer value. It should have been like this:

user.get_profile().team = team

How right? Use ModelForm . They will take over the routine work of competent data validation and will return the constructed model instances.
Although specifically in this case, ModelForm is not very suitable, because the data is stored in several different models. In such cases, you have to use a Form and do a little bit of programming, namely, to describe non-standard validation logic where it is required (the method describes custom field validation , details in the Form and field validation section of the documentation). The form code (forms.py) will be something like this (it was written offhand and not tested, no need to mindlessly copy-paste):clean_somethingsomething
# -*- coding: utf-8 -*-
from django import forms
from django.contrib.auth.models import User

class RegisterForm(forms.Form):
    username = forms.CharField()
    email    = forms.EmailField()
    password = forms.CharField()
    teamname = forms.CharField()

    def clean_username(self):
        """
        Проверим уникальность юзернейма
        """
        username = self.cleaned_data.get('username')

        if User.objects.filter(username=username).count() > 0:
            raise forms.ValidationError, 'User %s is already exists' % username
        return username

    def clean_team(self):
        """
        Проверим уникальность имени команды
        """
        name = self.cleaned_data.get('teamname')

        if Team.objects.filter(name=name).count() > 0:
            raise forms.ValidationError, 'Team %s is already exists' % name
        return name
    
    def clean(self):
        """
        Подготовка чистых данных для вставки в модель
        """
        data = super(RegisterForm, self).clean()

        data['user'] = User.objects.create_user(
            username = data['username'],
            password = data['password'],
            email    = data['email'],
        )
        data['team'] = Team.objects.create(
            name = data['teamname'],
        )

        return data

And the piece with the registration itself in views.py will look something like this:
form = RegisterForm(request.POST or None)
if form.is_valid():
    data = form.cleaned_data
    profile, created = UserProfile.objects.get_or_create(
        user = data['user'], # user - модель, а не строка
        team = data['team'], # team тоже модель
    )

You can optionally encapsulate creation UserProfilein a form class. This is even more correct, but in this case it is not fundamental :)
If I made a mistake somewhere or it is not clear - ask and welcome to the club :)

F
Fak3, 2011-04-30
@Fak3

1) before accessing the profile, you need to create it (after creating and saving user and team):
UserProfile.objects.create(user=user, team=team)
this will create and save a profile with the necessary parameters in the database.
2) There is an error -
user.get_profile.team = team.id
get_profile is a function, you need to access it like this:
user.get_profile().team = team
but in your case - this line is not needed at all if you created a profile, as I wrote above.

U
un1t, 2011-04-30
@un1t

It is necessary to make the profile automatically created when creating a user coderiver.ru/2011/01/avtomaticheskoe-sozdanie-profilej-pri-sozdanii-yuzera/
from django.db.models.signals import post_save
def create_profile(sender, **kwargs):
__user = kwargs['instance']
__if kwargs["created"]:
____profile = UserProfile(user=user)
____profile.save()
post_save.connect(create_profile, sender=User)

M
marazmiki, 2011-05-01
@marazmiki

And I, perhaps, will leave here a link to a topic related topics

S
S Pankov, 2011-04-30
@seocoder

Hm. It turns out that in general there is little sense in such binding, since everything is done by hand.
Is it possible to re-inherit the basic authorization model by adding the necessary attributes, without an intermediate table and inheriting to change the creation of the user and the authorization check?

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question