【问题标题】:RelatedObjectDoesNotExist - User has no profileRelatedObjectDoesNotExist - 用户没有个人资料
【发布时间】:2020-08-02 00:27:00
【问题描述】:

我是新来的,你好。到目前为止,构建我的第一个 Django 应用程序做得很好。现在我有一个小问题我自己无法解决。

当我尝试创建新用户时,没有创建关联的个人资料。

RelatedObjectDoesNotExist at /login/
User has no profile.
Request Method: POST
Request URL:    http://127.0.0.1:8000/login/
Django Version: 3.0.7
Exception Type: RelatedObjectDoesNotExist
Exception Value:    
User has no profile.
Exception Location: /Users/dmszanowski/PycharmProjects/django_to_dos/venv/lib/python3.8/site-packages/django/db/models/fields/related_descriptors.py in __get__, line 420

非常感谢您的帮助。

输出

[02/Aug/2020 02:20:14] "GET / HTTP/1.1" 200 5034
[02/Aug/2020 02:20:14] "GET /static/list/main.css HTTP/1.1" 304 0
[02/Aug/2020 02:20:16] "GET /register/ HTTP/1.1" 200 6400
[02/Aug/2020 02:20:33] "POST /register/ HTTP/1.1" 200 6571
[02/Aug/2020 02:20:43] "POST /register/ HTTP/1.1" 302 0
[02/Aug/2020 02:20:43] "GET /login/ HTTP/1.1" 200 5944
Internal Server Error: /login/
Traceback (most recent call last):
  File "/Users/dmszanowski/PycharmProjects/django_to_dos/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/Users/dmszanowski/PycharmProjects/django_to_dos/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/Users/dmszanowski/PycharmProjects/django_to_dos/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/dmszanowski/PycharmProjects/django_to_dos/django_project/users/views.py", line 30, in login_view
    login(request, user)
  File "/Users/dmszanowski/PycharmProjects/django_to_dos/venv/lib/python3.8/site-packages/django/contrib/auth/__init__.py", line 131, in login
    user_logged_in.send(sender=user.__class__, request=request, user=user)
  File "/Users/dmszanowski/PycharmProjects/django_to_dos/venv/lib/python3.8/site-packages/django/dispatch/dispatcher.py", line 173, in send
    return [
  File "/Users/dmszanowski/PycharmProjects/django_to_dos/venv/lib/python3.8/site-packages/django/dispatch/dispatcher.py", line 174, in <listcomp>
    (receiver, receiver(signal=self, sender=sender, **named))
  File "/Users/dmszanowski/PycharmProjects/django_to_dos/django_project/users/signals.py", line 21, in got_online
    user.profile.is_online = True
  File "/Users/dmszanowski/PycharmProjects/django_to_dos/venv/lib/python3.8/site-packages/django/db/models/fields/related_descriptors.py", line 420, in __get__
    raise self.RelatedObjectDoesNotExist(
django.contrib.auth.models.User.profile.RelatedObjectDoesNotExist: User has no profile.
[02/Aug/2020 02:21:17] "POST /login/ HTTP/1.1" 500 90315

apps.py

from django.apps import AppConfig


class UsersConfig(AppConfig):
    name = 'users'

    def ready(self):
        import users.signals

forms.py

from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Fieldset, ButtonHolder, Submit


class UserRegisterForm(UserCreationForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.layout = Layout(
            Fieldset('Register', 'username', 'email', 'password1', 'password2', css_class='text-white'),
            ButtonHolder(Submit('submit', 'Submit', css_class='btn-dark mb-3')))

    class Meta:
        model = User
        fields = ['username', 'email', 'password1', 'password2']

models.py

from django.contrib.auth.models import User
from django.db import models
import os
from PIL import Image
from .validators import validate_image_file_extension
from .storage import OverwriteFile


class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    is_private = models.BooleanField(default=0)
    is_online = models.BooleanField(default=0)
    image = models.ImageField(default='profile_pics/default.jpg', upload_to='profile_pics', blank=True, storage=OverwriteFile(), validators=[validate_image_file_extension])

    def __str__(self):
        return f'{self.user.username}'

    def save(self, *args, **kwargs):
        # image_path = os.path.join('profile_pics/', self.image.path)
        img = Image.open(self.image.path)
        if img.height > 300 or img.width > 300:
            output_size = (300, 300)
            img.thumbnail(output_size)
        img = img.convert('RGB')
        if 'default.jpg' not in self.image.name:
            os.remove(self.image.path)
            self.image.name = 'profile_pics/' + str(self.user_id) + "." + self.image.name.split(".", 2)[1]
        img.save(self.image.path, "JPEG")

signals.py

from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth.models import User
from .models import Profile


@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)


@receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
    instance.profile.save()

storage.py

from django.core.files.storage import FileSystemStorage
from django.conf import settings
import os


class OverwriteFile(FileSystemStorage):
    def get_available_name(self, name, max_length=None):
        if self.exists(name):
            os.remove(os.path.join(settings.MEDIA_ROOT, name))
        return name

views.py

from django.shortcuts import render, redirect
from django.contrib import messages
from .forms import UserRegisterForm
from .models import User, Profile


def register_view(request):
    if request.method == 'POST':
        user_register_form = UserRegisterForm(request.POST)
        if user_register_form.is_valid():
            user = user_register_form.save()
            Profile.objects.create(**{'user': user})
            messages.success(request, f'Your account has been created! You are now able to log in')
            return redirect('login')
    else:
        user_register_form = UserRegisterForm()
    return render(request, 'users/register.html', {'user_register_form': user_register_form})

validators.py

import os
from django.core.exceptions import ValidationError


def validate_image_file_extension(value):
    ext = os.path.splitext(value.name)[1]
    valid_ext = ['.png', '.jpg', '.jpeg']
    if not ext.lower() in valid_ext:
        raise ValidationError('Unsupported image file extension. Allowed vales %(value)s', params={'value': valid_ext})

settings.py

INSTALLED_APPS = [
    'users.apps.UsersConfig',
    'list.apps.ListConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'crispy_forms',
]

STATICFILES_DIRS = (
    os.path.join('static'),
)
STATIC_URL = '/static/'

CRISPY_TEMPLATE_PACK = 'bootstrap4'

LOGIN_REDIRECT_URL = ''
LOGIN_URL = 'login'

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

【问题讨论】:

  • 可以添加views.py文件吗?
  • @ItsMilann 已编辑。我不知何故错过了第一次包含它,对不起。

标签: python python-3.x django


【解决方案1】:

重点是profile 对象默认不会出现。您必须添加如下内容:

if form.is_valid():
    user = form.save()
    Profile.objects.create(**{'user': user})

是的,将其添加到您的 views.py 文件(您没有提供)中。还可以将“form”替换为您使用的任何表单名称。

Reference

【讨论】:

  • 它对我不起作用,同样的事情。你现在可以查看我的views.py,我编辑了帖子。
  • 很抱歉我之前没有使用过这个对象。 this thread 会帮助你吗?
【解决方案2】:

我想通了。我不小心删除了我的Profile Model 中的super().save()。重新添加后,完美运行!

固定模型.py

from django.contrib.auth.models import User
from django.db import models
import os
from PIL import Image
from .validators import validate_image_file_extension
from .storage import OverwriteFile


class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    is_private = models.BooleanField(default=0)
    is_online = models.BooleanField(default=0)
    image = models.ImageField(default='profile_pics/default.jpg', upload_to='profile_pics', blank=True, storage=OverwriteFile(), validators=[validate_image_file_extension])

    def __str__(self):
        return f'{self.user.username}'

    def save(self, *args, **kwargs):
        super().save()
        img = Image.open(self.image.path)
        if img.height > 300 or img.width > 300:
            output_size = (300, 300)
            img.thumbnail(output_size)
        img = img.convert('RGB')
        if 'default.jpg' not in self.image.name:
            os.remove(self.image.path)
            self.image.name = 'profile_pics/' + str(self.user_id) + "." + self.image.name.split(".", 2)[1]
        img.save(self.image.path, "JPEG")

【讨论】:

    猜你喜欢
    • 2020-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-01
    • 2013-05-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多