Proyecto Django_googleapi_project: Error de atributo en /perfil. Valor de excepción: El objeto ‘User’ no tiene el atributo ‘userprofile’.
He estado siguiendo este video para aprender Django: https://www.youtube.com/watch?v=_vCT42vDfgw.
He seguido hasta el final, he ejecutado el servidor en localhost
en el puerto 8000. Puedo registrar usuarios, pero cuando intento actualizar el perfil de un usuario (haciendo clic en el enlace 'Update User Profile'
en la vista), obtengo un AttributeError en/profile
, que no he podido resolver a pesar de verificar el código fuente del tutor (todo parece igual) y buscar respuestas a preguntas similares en stack overflow aquí.
Cualquier ayuda sería muy apreciada…
Aquí está la prueba de error:
Environment:
Request Method: GET
Request URL: http://localhost:8000/profile
Django Version: 3.2.9
Python Version: 3.10.0
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'main',
'users']
Installed 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']
Traceback (most recent call last):
File "C:\Users\Toshiba\Envs\django-googleapi-project\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "C:\Users\Toshiba\Envs\django-googleapi-project\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "c:\django-googleapi-project\users\views.py", line 48, in profile_view
up = user.userprofile
AttributeError: 'User' object has no attribute 'userprofile'
Aquí está la muestra de código en el archivo users\views.py
que contiene el objeto userprofile
:
from django.shortcuts import render, redirect, reverse
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.contrib.auth import login, logout, authenticate
from django.conf import settings
from django.http import JsonResponse
from django.views.generic.edit import FormView
from django.views.generic.base import TemplateView
from django.utils.decorators import method_decorator
from django-googleapi-project.mixins import (
AjaxFormMixin,
reCAPTCHAValidation,
FormErrors,
RedirectParams,
)
from .forms import (
UserForm,
UserProfileForm,
AuthForm,
)
result = "Error"
message = "There was an error, please try again"
class AccountView(TemplateView):
'''
Generic FormView with our mixin to display user account page
'''
template_name = "users/account.html"
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super().dispatch(*args, **kwargs)
@login_required
def profile_view(request):
'''
function view to allow users to update their profile
'''
user = request.user
up = user.userprofile
form = UserProfileForm(instance = up)
if request.is_ajax():
form = UserProfileForm(data = request.POST, instance = up)
if form.is_valid():
obj = form.save()
obj.has_profile = True
obj.save()
result = "Success"
message = "Your profile has been updated"
else:
message = FormErrors(form)
data = {'result': result, 'message': message}
return JsonResponse(data)
else:
context = {'form': form}
context['google_api_key'] = settings.GOOGLE_API_KEY
context['base_country'] = settings.BASE_COUNTRY
return render(request, 'users/profile.html', context)
class SignUpView(AjaxFormMixin, FormView):
'''
Generic FormView with our mixin for user sign-up with reCAPTURE security
'''
template_name = "users/sign_up.html"
form_class = UserForm
success_url = "/"
#reCAPTURE key required in context
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["recaptcha_site_key"] = settings.RECAPTCHA_PUBLIC_KEY
return context
#over write the mixin logic to get, check and save reCAPTURE score
def form_valid(self, form):
response = super(AjaxFormMixin, self).form_valid(form)
if self.request.is_ajax():
token = form.cleaned_data.get('token')
captcha = reCAPTCHAValidation(token)
if captcha["success"]:
obj = form.save()
obj.email = obj.username
obj.save()
up = obj.userprofile
up.captcha_score = float(captcha["score"])
up.save()
login(self.request, obj, backend='django.contrib.auth.backends.ModelBackend')
#change result & message on success
result = "Success"
message = "Thank you for signing up"
data = {'result': result, 'message': message}
return JsonResponse(data)
return response
class SignInView(AjaxFormMixin, FormView):
'''
Generic FormView with our mixin for user sign-in
'''
template_name = "users/sign_in.html"
form_class = AuthForm
success_url = "/"
def form_valid(self, form):
response = super(AjaxFormMixin, self).form_valid(form)
if self.request.is_ajax():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
#attempt to authenticate user
user = authenticate(self.request, username=username, password=password)
if user is not None:
login(self.request, user, backend='django.contrib.auth.backends.ModelBackend')
result = "Success"
message = 'You are now logged in'
else:
message = FormErrors(form)
data = {'result': result, 'message': message}
return JsonResponse(data)
return response
def sign_out(request):
'''
Basic view for user sign out
'''
logout(request)
return redirect(reverse('users:sign-in'))
Aquí está el archivo users.models; tengo una clase UserProfile
. He intentado cambiar esto a userprofile
, pero el error persiste. ¿Tal vez no he hecho las importaciones correctas?
“`
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
”’
Our UserProfile model extends the built-in Django User Model
”’
timestamp = models.DateTimeField(auto_now_add = True)
updated = models.DateTimeField(auto_now = True)
user = models.OneToOneField(User, related_name=’profile’, on_delete = models.CASCADE)
address = models.CharField(verbose_name = "Address", max_length=100, null=True, blank=True)
town = models.CharField(verbose_name = "Town/City", max_length=100, null=True, blank=True)
county = models.CharField(verbose_name = "County", max_length=100, null=True, blank=True)
post_code = models.CharField(verbose_name = "Post Code", max_length=8, null=True, blank=True)
country = models.CharField(verbose_name = "Country", max_length=100, null=True, blank=True)
longitude = models.CharField(verbose_name = "Longitude",
davy.ai
El mensaje de error indica que hay un error de atributo en la línea 48 del archivo
users/views.py
. El error está relacionado con el hecho de que el objetoUser
no tiene un atributo llamadouserprofile
.Esto sugiere que hay un problema con la clase
UserProfile
enusers/models.py
. Parece que el atributouserprofile
no está siendo vinculado adecuadamente al modeloUser
.Una solución potencial podría ser cambiar el atributo
related_name
en el campouser
del modeloUserProfile
de'profile'
a'userprofile'
para que coincida con el código en la funciónprofile_view
.Otra posible solución podría ser comprobar las importaciones en el archivo
users/models.py
para asegurarse de que el modeloUser
se esté importando correctamente.Si estas soluciones no resuelven el problema, puede ser útil revisar cualquier modificación realizada en el código en el archivo
users/views.py
y asegurarse de que no hayan interferido con el comportamiento esperado del modeloUserProfile
.