2013-07-13 4 views
4

У меня есть Джанго custom user modelMyUser с одним дополнительным полем:Сохранение пользовательской модели пользователя с Джанго-allauth

# models.py 
from django.contrib.auth.models import AbstractUser 

class MyUser(AbstractUser): 
    age = models.PositiveIntegerField(_("age")) 

# settings.py 
AUTH_USER_MODEL = "web.MyUser" 

У меня также есть по to these instructions пользовательских allauth Signup form class:

# forms.py 
class SignupForm(forms.Form): 
    first_name = forms.CharField(max_length=30) 
    last_name = forms.CharField(max_length=30) 
    age = forms.IntegerField(max_value=100) 

    class Meta: 
     model = MyUser 

    def save(self, user): 
     user.first_name = self.cleaned_data['first_name'] 
     user.last_name = self.cleaned_data['last_name'] 
     user.age = self.cleaned_data['age'] 
     user.save() 

# settings.py 
ACCOUNT_SIGNUP_FORM_CLASS = 'web.forms.SignupForm' 

После подачи SignupForm (поле для свойства MyUser.age оказано corectly), я получаю эту ошибку:

IntegrityError at /accounts/signup/
(1048, "Column 'age' cannot be null")

Каков правильный способ хранения пользовательской модели пользователя?

django-allauth: 0.12.0; django: 1.5.1; Python 2.7.2

+0

Мои Угадайте, 'user.age = self.cleaned_data ['age'] 'оценивает' None' каким-то образом .. Вы можете проверить значение? и какой параметр 'user' отправляется в метод' save'? – karthikr

+0

Вы должны вернуть 'user' из' save' method также 'return user' –

+0

@karthikr Я обнаружил, что метод' save() 'не выполняется. Исключение выдается, когда новый пользователь создается в ['django-allauth/allauth/account/forms.py # 269'] (https://github.com/pennersr/django-allauth/blob/master/allauth/account /forms.py#L269). – illagrenan

ответ

6

Хотя это немного поздно, но на случай, если это поможет кому-то.

Вам нужно создать свой собственный пользовательский AccountAdapter на подклассы DefaultAccountAdapter и установка

class UserAccountAdapter(DefaultAccountAdapter): 

    def save_user(self, request, user, form, commit=True): 
     """ 
     This is called when saving user via allauth registration. 
     We override this to set additional data on user object. 
     """ 
     # Do not persist the user yet so we pass commit=False 
     # (last argument) 
     user = super(UserAccountAdapter, self).save_user(request, user, form, commit=False) 
     user.age = form.cleaned_data.get('age') 
     user.save() 

и вы также должны определить следующие в настройках:

ACCOUNT_ADAPTER = 'api.adapter.UserAccountAdapter' 

Это также полезно, если вы иметь пользовательскую учетную запись RegisterForm для создания других моделей во время регистрации пользователя, и вам необходимо сделать атомную транзакцию, которая предотвратила бы сохранение любых данных в базе данных, если все они не удастся.

DefaultAdapter для django-allauth сохраняет пользователя, поэтому, если у вас есть ошибка в методе вашей учетной записи RegistrationForm save, пользователь по-прежнему будет сохраняться в базе данных.

Так что для тех, кто сталкивается этот вопрос, ваш CustomAdpater будет выглядеть следующим образом

класса UserAccountAdapter (DefaultAccountAdapter):

def save_user(self, request, user, form, commit=False): 
     """ 
     This is called when saving user via allauth registration. 
     We override this to set additional data on user object. 
     """ 
     # Do not persist the user yet so we pass commit=False 
     # (last argument) 
     user = super(UserAccountAdapter, self).save_user(request, user, form, commit=commit) 
     user.age = form.cleaned_data.get('age') 
     # user.save() This would be called later in your custom SignupForm 

Затем вы можете украсить ваши пользовательские SignupForm с @transaction.atomic

@transaction.atomic 
def save(self, request, user): 
    user.save() #save the user object first so you can use it for relationships 
    ... 
+2

Теперь это правильный ответ – Jakobovski

+0

Отредактировано, чтобы добавить пример, где может быть полезно «CustomAdapter» :) – danidee

1

Примечание стороны

С Джанго 1,5 пользовательской модели пользователя, лучшая практика заключается в использовании get_user_model функции:

from django.contrib.auth import get_user_model 

# forms.py 
class SignupForm(forms.Form): 
    first_name = forms.CharField(max_length=30) 
    last_name = forms.CharField(max_length=30) 
    age = forms.IntegerField(max_value=100) 

    class Meta: 
     model = get_user_model() # use this function for swapping user model 

    def save(self, user): 
     user.first_name = self.cleaned_data['first_name'] 
     user.last_name = self.cleaned_data['last_name'] 
     user.age = self.cleaned_data['age'] 
     user.save() 

# settings.py 
ACCOUNT_SIGNUP_FORM_CLASS = 'web.forms.SignupForm' 

Может быть, это не имеет отношения, но я думал, что это было бы замечательно.

+0

Я хочу, чтобы свойство 'age' было обязательным, но django-allauth [пытается сохранить' MyUser'] (https://github.com/pennersr/django-allauth/blob/master/allauth/account/forms. py # L269) только с полями по умолчанию. И спасибо за функцию 'get_user_model', я этого не знал. – illagrenan

0

я думаю, вы должны определить поля свойство в классе Meta в SignupForm и установить список полей, содержащий возраст, как это:

class SignupForm(forms.Form): 
... 
    class Meta: 
     model = MyUser 
     fields = ['first_name', 'last_name', 'age'] 

и если это не работает, посмотрите на this

Смежные вопросы