Объект Django 'User' не имеет атрибута 'userprofile'

Я использую Django allauth для аутентификации и создал модель UserProfile для хранения дополнительной информации, которую пользователь может обновить на более поздней стадии. Я пытаюсь использовать сигналы, чтобы экземпляр UserProfile создавался каждый раз, когда пользователь впервые создается, и обновлять UserProfile только если он уже существует.

Проблема заключается в том, что экземпляр UserProfile не создается, выдавая такую ошибку:

Я понимаю, что у объекта User нет атрибута 'userprofile', но я не уверен, как это преодолеть. Я просмотрел похожие решения здесь, здесь и здесь, но, должно быть, я что-то упускаю.

models.py:

from django.db import models
from django.conf import settings
from django.contrib.auth.models import User
from datetime import date, datetime
from django.utils import timezone
from django.db.models.signals import post_save
from django.dispatch import receiver


# Create your models here.
class UserProfile(models.Model):
    user = models.OneToOneField(User, related_name='profile', unique=True, on_delete=models.CASCADE)
    sex = models.CharField(max_length=1, default='M', blank=True, null=True)
    date_of_birth = models.DateField(default=date.today, blank=True, null=True)
    date_joined = models.DateField(editable=False, auto_now_add=True, blank=True, null=True)
    # durationfield
    max_streak = models.PositiveSmallIntegerField(default=0, blank=True, null=True)
    curr_streak = models.PositiveSmallIntegerField(default=0, blank=True, null=True)
    total_days_clean = models.PositiveSmallIntegerField(default=0, blank=True, null=True)
    streak_start_date = models.DateTimeField(editable=True, default=timezone.now, blank=True, null=True)
    streak_end_date = models.DateTimeField(editable=True, default=timezone.now, blank=True, null=True)
    last_streak_end_date = models.DateTimeField(editable=True, default=timezone.now, blank=True, null=True)
    curr_rank = models.CharField(max_length=150, default='n00b', blank=True, null=True)
    highest_rank = models.CharField(max_length=150, default='n00b', blank=True, null=True)
    bio = models.TextField(default='text', blank=True, null=True)
    display_name = models.CharField(max_length=30, default='John Smith', blank=True, null=True)
    REQUIRED_FIELDS = ('user',)
    email = models.EmailField(blank=True, null=True)
    # USERNAME_FIELD = 'username'
    # username = models.CharField(max_length = 25, unique=True)

    def __str__(self):
        return self.user.email

    @property
    def is_anonymous(self):
        """
        Always return False. This is a way of comparing User objects to
        anonymous users.
        """
        return False
    
    @property
    def is_authenticated(self):
        """
        Always return True. This is a way of comparing User objects to
        anonymous users.
        """
        return True

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


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

forms.py:

from allauth.account.forms import SignupForm
from django import forms
from .models import User, UserProfile
from django.forms.widgets import NumberInput
import datetime

class UpdateUserProfileForm(forms.ModelForm):
    class Meta:
        model = UserProfile
        # fields to be added in this form
        fields = ['display_name', 'date_of_birth', 'bio']

views.py:

from django.shortcuts import render, redirect, get_object_or_404
from django.contrib import messages
from django.http import HttpResponse
from .models import User, UserProfile
from .forms import UpdateUserProfileForm

def update_user_profile(request):
    # form = UpdateUserProfileForm(request.POST or None)
    form = UpdateUserProfileForm(request.POST, instance=request.user.userprofile)
    if form.is_valid():
        form.save()
        return redirect('profile')
        messages.success(request, ('Your profile was successfully updated!'))
    else:
        messages.error(request, ('Please correct the error below.'))
         
    context = {
        'form': form
    }    
    return render(request, 'update_profile.html', context)   

Любая помощь будет принята с благодарностью, спасибо.

Это происходит, потому что вы устанавливаете related_name='profile', а затем вызываете его с помощью instance.userprofile.save(). Измените это на:

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

и все должно работать гладко :)

Вернуться на верх