更新 我尝试用以下内容替换自定义管理器中的所有内容:
def create_user(self, username, email):
return self.model._default_manager.create(username=username)
这会引发错误。然后我尝试从我的自定义用户管理器返回用户,我得到“无法分配”:“UserSocialAuth.user”必须是“Barbuser”实例。从 associate_user 抛出。它来自 django.db.models.fields.related.py 的内部。基本上,我坚持知道如何从我的自定义模型经理中正确创建用户。我直接离开了导致我从 django 内置的 ModelManager 中复制所有内容的文档。帮助? 更新
我在配置 django-social-auth 时遇到问题。我已经在这里待了 3-4 天,我正准备认输。我安装了一个可用的现有用户注册应用程序,然后我安装并遵循了 django-social-auth github 站点上的文档。我将以下内容添加到我的 settings.py
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
# Uncomment the next line to enable the admin:
'django.contrib.admin',
# Uncomment the next line to enable admin documentation:
# 'django.contrib.admindocs',
'polls',
'barbuser',
'social_auth',
)
AUTHENTICATION_BACKENDS = (
'social_auth.backends.facebook.FacebookBackend',
'django.contrib.auth.backends.ModelBackend',
)
FACEBOOK_APP_ID = os.environ.get('FACEBOOK_APP_ID')
FACEBOOK_API_SECRET = os.environ.get('FACEBOOK_SECRET')
TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth',
'social_auth.context_processors.social_auth_by_type_backends',
)
#SOCIAL_AUTH_ENABLED_BACKENDS = ('facebook',)
SOCIAL_AUTH_DEFAULT_USERNAME = 'new_social_auth_user'
LOGIN_URL = '/login/'
LOGIN_REDIRECT_URL = '/profile/'
LOGIN_ERROR_URL = '/login-error/'
SOCIAL_AUTH_USER_MODEL = 'barbuser.Barbuser'
我的 models.py 看起来像:
from datetime import date
from django.db import models
from django.contrib.auth.models import User
from django.db.models import BooleanField
from django.db.models.fields import DateTimeField
from django.utils import timezone
from django.utils.crypto import get_random_string
class BarbuserManager(models.Manager):
@classmethod
def normalize_email(cls, email):
"""
Normalize the address by converting the domain part of the email address to lowercase.
"""
email = email or ''
try:
email_name, domain_part = email.strip().rsplit('@', 1)
except ValueError:
pass
else:
email = '@'.join([email_name, domain_part.lower()])
return email
def create_user(self, username, email=None, password=None):
"""
Creates and saves a User with the given username, email and password.
"""
email = 'you@email.com' if email.strip() == '' else email
now = timezone.now()
if not username:
raise ValueError('The given username must be set')
email = BarbuserManager.normalize_email(email)
user = User(username=username, email=email,
is_staff=False, is_active=True, is_superuser=False,
last_login=now, date_joined=now)
user.set_password(password)
user.save()
barbuser = Barbuser(user=user, birthday=date.today(), last_login=user.last_login, name=username)
barbuser.save()
return barbuser
def create_superuser(self, username, email, password):
u = self.create_user(username, email, password)
u.is_staff = True
u.is_active = True
u.is_superuser = True
u.save(using=self._db)
return u
def make_random_password(self, length=10,
allowed_chars='abcdefghjkmnpqrstuvwxyz'
'ABCDEFGHJKLMNPQRSTUVWXYZ'
'23456789'):
""" Generates a random password with the given length and given allowed_chars. Note that the default value of allowed_chars does not have "I" or "O" or letters and digits that look similar -- just to avoid confusion. """
return get_random_string(length, allowed_chars)
def get_by_natural_key(self, username):
return self.get(username=username)
class Barbuser(models.Model):
user = models.OneToOneField(User)
username = models.CharField(max_length=200)
last_login = DateTimeField(blank=True)
is_active = BooleanField(default=True)
birthday = models.DateField()
name = models.CharField(max_length=200)
objects = BarbuserManager()
def __init__(self, *args, **kwargs):
me = super(Barbuser, self).__init__(*args, **kwargs)
barbuser = me
return me
def __unicode__(self):
return self.name
def is_authenticated(self):
return self.user.is_authenticated()
我已经更新了我的 urls.py 以包含“social_auth.urls”,并且在身份验证后,用户从我的 views.py 被重定向到 ViewProfile 视图:
# Create your views here.
from barbuser.forms import RegistrationForm, LoginForm
from barbuser.models import Barbuser
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.models import User
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template.context import RequestContext
def create_Barbuser(form):
user = User.objects.create_user(form.cleaned_data['username'], form.cleaned_data['email'], form.cleaned_data['password'])
user.save()
barbuser = Barbuser(user=user, name=form.cleaned_data['name'], birthday=form.cleaned_data['birthday'])
barbuser.save()
def process_form(form, request_context):
if form.is_valid():
create_Barbuser(form)
return HttpResponseRedirect('/profile/')
else:
return render_to_response('register.html', {'form': form}, context_instance=request_context)
def render_blank_registration_form(request):
'''When the user is not submitting the form, show them the blank registration form.'''
form = RegistrationForm()
context = {'form': form}
return render_to_response('register.html', context, context_instance=RequestContext(request))
def BarbuserRegistration(request):
"""
Handles the registration of new Barbwire users.
"""
if request.user.is_authenticated():
return HttpResponseRedirect('/profile/')
if request.method == "POST":
return process_form(RegistrationForm(request.POST), RequestContext(request))
else:
return render_blank_registration_form(request)
def LoginRequest(request):
'''
Handles Login requests.
'''
if request.user.is_authenticated():
return HttpResponseRedirect('/profile/')
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
barbuser = authenticate(username=username, password=password)
if barbuser is not None:
login(request, barbuser)
return HttpResponseRedirect('/profile/')
else:
return render_to_response('login.html', {'form' : form}, context_instance=RequestContext(request))
else:
return render_to_response('login.html', {'form' : form}, context_instance=RequestContext(request))
else:
form = LoginForm()
return render_to_response('login.html', {'form' : form}, context_instance=RequestContext(request))
def LoginError(request):
return render_to_response('login.html', {'form' : LoginForm()}, context_instance=RequestContext(request))
def LogoutRequest(request):
logout(request)
return HttpResponseRedirect('/')
def ViewProfile(request):
if not request.user.is_authenticated():
return HttpResponseRedirect('/login/')
else:
return render_to_response('profile.html',{'barbuser' : request.user.barbuser }, context_instance=RequestContext(request))
我的问题是 2 倍。当我在我的 models.py 中添加这些额外的东西时:
def facebook_extra_values(sender, user, response, details, **kwargs):
return False
from social_auth.signals import pre_update
from social_auth.backends.facebook import FacebookBackend
pre_update.connect(facebook_extra_values, sender=FacebookBackend)
我在服务器启动时遇到错误:assert isinstance(to, basestring), "%s(%r) is invalid. ForeignKey 的第一个参数必须是模型、模型名称或字符串 %r" % ( self.class ._ name _, to, RECURSIVE_RELATIONSHIP_CONSTANT) AssertionError: ForeignKey(None) 无效。ForeignKey 的第一个参数必须是模型、模型名称或字符串“self”
当我删除它时,我可以通过 facebook 流程登录,但我得到:/complete/facebook/ 'NoneType' 对象的 AttributeError 没有属性 'extra_data'
我不确定我错过了什么或哪里出错了。有人可以帮助解释我哪里出错了吗?
更新 我已经在调试中跟踪了这个问题,显然当它尝试“UserSocialAuth.objects.create”时,我在 associate_user 函数中的 social_auth.backends.pipeline.social.py 中得到了一个 IntegrityError。然后它回退到调用 social_auth_user() 的 except 块中,并且此函数为 social_user 返回 None。我得到的 IntegrityError 是:
insert or update on table "social_auth_usersocialauth" violates foreign key constraint "social_auth_usersocialauth_user_id_fkey"
DETAIL: Key (user_id)=(17) is not present in table "auth_user".
我不够熟悉,不知道如何、在哪里或为什么将 social_user 与在我的 models.py 中的 CustomUserManager 中创建的用户相关联。此外,我还删除了 models.py 底部的 facebook_extra_values、额外导入和 preupdate.connect 内容,因为我真的不明白它的作用或用途。我只是从示例应用程序中复制东西,试图解决我的第一个问题,即缺少关联。帮助? 更新