我正在创建一个Django WebApp,允许通过django- allauth 使用表单和社交身份验证进行注册和登录。
通过表单注册工作正常。
您可以在https://github.com/ralfillo/social_django_website
上查看整个项目当用allauth(Facebook帐户)创建用户时,登录有效,但当我想编辑用户的帐户时,Django会抛出此错误:
/ account / edit /上的RelatedObjectDoesNotExist没有个人资料。
请求方法: GET
请求网址 https://development.com:8000/account/edit/
Django版本: 2.0.4
异常类型: RelatedObjectDoesNotExist异常值:用户没有 轮廓。在控制台上: django.db.models.fields.related_descriptors.RelatedObjectDoesNotExist: 用户没有个人资料。
帐户应用 models.py 如下所示:
from django.conf import settings
from django.contrib.auth.models import User
from django.db import models
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
date_of_birth = models.DateField(blank=True, null=True)
photo = models.ImageField(upload_to='users/%Y/%m/%d', blank=True)
def __str__(self):
return 'Profile for user {}'.format(self.user.username)
views.py 的一部分:
from django.contrib import messages
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
from django.shortcuts import render, redirect
#-----
from .forms import LoginForm, UserRegistrationForm, UserEditForm, ProfileEditForm
from .models import Profile
@login_required
def edit(request):
if request.method == 'POST':
user_form = UserEditForm(instance=request.user,
data=request.POST)
profile_form = ProfileEditForm(instance=request.user.profile,
data=request.POST,
files=request.FILES)
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
messages.success(request, 'Profile updated successfully')
else:
messages.error(request, 'Error updating your profile')
else:
user_form = UserEditForm(instance=request.user)
profile_form = ProfileEditForm(instance=request.user.profile)
return render(request, 'account/edit.html', {'user_form': user_form,
'profile_form': profile_form})
settings.py 的一部分,您可以检查github上的整个文件(上面提供的链接):
import os
import json
from django.core.exceptions import ImproperlyConfigured
from django.urls import reverse_lazy
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Import JSON secrets module
with open(BASE_DIR + '/secrets.json') as f:
secrets = json.loads(f.read())
def get_secret(setting, secrets=secrets):
"""Get the secret variable or return explicit exception"""
try:
return secrets[setting]
except KeyError:
error_msg = 'Set the {0} environment variable'.format(setting)
raise ImproperlyConfigured(error_msg)
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = get_secret('SECRET_KEY')
ALLOWED_HOSTS = ['development.com']
# Application definition
INSTALLED_APPS = [
# My Apps
'account',
# Django Apps
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
# Third party Apps
'sslserver',
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.facebook',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'django_social_website.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')]
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
# allauth specific context processors
# "allauth.account.context_processors.account",
# "allauth.socialaccount.context_processors.socialaccount",
],
},
},
]
WSGI_APPLICATION = 'django_social_website.wsgi.application'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Redirect login urls
LOGIN_REDIRECT_URL = reverse_lazy('account:dashboard')
LOGIN_URL = reverse_lazy('account:login')
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'account.authentication.EmailAuthBackend',
# `allauth` specific authentication methods, such as login by e-mail
"allauth.account.auth_backends.AuthenticationBackend",
)
SITE_ID = 1
SOCIALACCOUNT_PROVIDERS = {
'facebook': {
'METHOD': 'oauth2',
'SCOPE': ['email', 'public_profile', 'user_friends'],
'AUTH_PARAMS': {'auth_type': 'reauthenticate'},
'INIT_PARAMS': {'cookie': True},
'FIELDS': [
'id',
'email',
'name',
'first_name',
'last_name',
'verified',
'locale',
'timezone',
'link',
'gender',
'updated_time',
],
'EXCHANGE_TOKEN': True,
'LOCALE_FUNC': 'path.to.callable',
'VERIFIED_EMAIL': False,
'VERSION': 'v2.12',
}
}
# facebook
SOCIAL_AUTH_FACEBOOK_KEY = get_secret('SOCIAL_AUTH_FACEBOOK_KEY') # App ID
SOCIAL_AUTH_FACEBOOK_SECRET = get_secret('SOCIAL_AUTH_FACEBOOK_SECRET') # app key
# little options for your page's signup.
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_USERNAME_REQUIRED = True
看起来如果使用表单和django-allauth的注册和登录不能作为一个整体工作。
当我检查在两种模式下创建的用户时,他们在Django的管理区域看起来是一样的,但看起来allauth没有创建一个我认为无法交替使用任何登录系统的配置文件。
我知道这个问题很长,感谢您通过它:)
答案 0 :(得分:0)
用户注册时似乎没有创建profile
记录,或者至少它对于您当前的用户不存在(可能是在shell上创建的超级用户?或者是由用户创建的用户)管理员?或在添加profile
逻辑之前创建的?如果profile
只在register
视图中创建,则会显示。)
可以解决您的问题的解决方案是使用信号来检测用户的创建时间,然后创建profile
,这样就无需创建用户的位置。例如,models.py
就是这样的:
@receiver(post_save, sender=User, dispatch_uid="something_here")
def create_profile(sender, **kwargs):
if kwargs.get('created', False):
Profile.objects.create(user=kwargs['instance'])
对于缺少配置文件的现有用户,您应该将其添加到django管理中。