Django 2.0 + django-allauth:/ accounts / edit /中的RelatedObjectDoesNotExist(用户没有个人资料)

时间:2018-04-11 20:57:30

标签: python django authentication facebook-login django-allauth

我正在创建一个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没有创建一个我认为无法交替使用任何登录系统的配置文件。

我知道这个问题很长,感谢您通过它:)

1 个答案:

答案 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管理中。