Good day again django enthusiasts.
@KenWhitesell my apologies for putting this in the wrong forum.
I’m trying to extend my website’s profile functionality by adding some additional forms to the profile. I’ve been using the book Django for Professionals by william vincent which uses user creation sing allauth. The book however does not say anything regarding adding additional profile fields. CoreyMS published a nice tutorial. I’m trying to configure both methods to be able to give a registered user the option to fill in some additional profile information.
So far this is what I’ve come up with. I’m now getting errors that there is something wrong with my p_form. I’ve retraced all routes to that object, it seems to me as it’s all connected as it should. I think my problem arises form the fact that I’m trying to create Profile without correctly referencing to allauth’s custom profile.
any help is greatly appreciated.
Thank you in advance.
This is my code:
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser, User
from django_countries.fields import CountryField
from django.conf import settings
# Create your models here.
class CustomUser(AbstractUser):
pass
class Profile(models.Model):
#user = models.OneToOneField(User, on_delete=models.CASCADE)
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
bio = models.TextField(max_length=500, blank=True)
birth_date = models.DateField(null=True, blank=True)
country = CountryField()
city = models.CharField(max_length=50, blank=True)
group = models.CharField(max_length=50, blank=True)
image = models.ImageField(upload_to='profile_pics', default='default.jpg')
def __str__(self):
return f'{self.user.username} Profile'
forms.py
# accounts/forms.py
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import Profile
from django import forms
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = get_user_model()
fields = ('username', 'email')
class CustomUserChangeForm(UserChangeForm):
class Meta(UserChangeForm.Meta):
model = get_user_model()
fields = ('username', 'email')
class ProfileUpdateForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('bio', 'birth_date', 'country', 'city', 'group', 'image')
views.py
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from .forms import CustomUserChangeForm, ProfileUpdateForm
@login_required
def ProfileUpdateView(request):
u_form = CustomUserChangeForm(instance=request.user)
p_form = ProfileUpdateForm(instance=request.user.profile)
context = {
'u_form': u_form,
'p_form': p_form
}
return render(request, 'account/update_profile.html', context)
urls.py
# accounts/urls.py
from django.urls import path
from .views import ProfileUpdateView
urlpatterns = [
path("update_profile/", ProfileUpdateView, name="update_profile"),
]
signals.py
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import Profile
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
apps.py
from django.apps import AppConfig
class AccountsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'accounts'
def ready(self):
import accounts.signals
and finally my html template:
<!-- templates/account/signup.html -->
{% extends "_base.html" %}
{% load static %}
{% load crispy_forms_tags %}
{% block title %}Update profile{% endblock title %}
{% block content %}
<!-- Form -->
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ u_form|crispy }}
{{ p_form|crispy }}
<button class="btn btn-primary mb-2" type="submit">Update account</button>
</form>
{% endblock content %}
The error is as follows:
RelatedObjectDoesNotExist at /accounts/update_profile/
CustomUser has no profile.
Request Method: GET
Request URL: http://localhost:8000/accounts/update_profile/
Django Version: 4.2.4
Exception Type: RelatedObjectDoesNotExist
Exception Value:
CustomUser has no profile.
Exception Location: /usr/local/lib/python3.10/site-packages/django/db/models/fields/related_descriptors.py, line 492, in __get__
Raised during: accounts.views.ProfileUpdateView
Python Executable: /usr/local/bin/python
Python Version: 3.10.4
Python Path:
['/websiteV2',
'/usr/local/lib/python310.zip',
'/usr/local/lib/python3.10',
'/usr/local/lib/python3.10/lib-dynload',
'/usr/local/lib/python3.10/site-packages']
Server time: Tue, 29 Aug 2023 21:05:25 +0000
Traceback Switch to copy-and-paste view
/usr/local/lib/python3.10/site-packages/django/core/handlers/exception.py, line 55, in inner
response = get_response(request) …
Local vars
Variable Value
exc
RelatedObjectDoesNotExist('CustomUser has no profile.')
get_response
<bound method BaseHandler._get_response of <django.core.handlers.wsgi.WSGIHandler object at 0x7fd421b43070>>
request
<WSGIRequest: GET '/accounts/update_profile/'>
/usr/local/lib/python3.10/site-packages/django/core/handlers/base.py, line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs) …
Local vars
Variable Value
callback
<function ProfileUpdateView at 0x7fd41efe3250>
callback_args
()
callback_kwargs
{}
middleware_method
<bound method CsrfViewMiddleware.process_view of <CsrfViewMiddleware get_response=convert_exception_to_response.<locals>.inner>>
request
<WSGIRequest: GET '/accounts/update_profile/'>
response
None
self
<django.core.handlers.wsgi.WSGIHandler object at 0x7fd421b43070>
wrapped_callback
<function ProfileUpdateView at 0x7fd41efe3250>
/usr/local/lib/python3.10/site-packages/django/contrib/auth/decorators.py, line 23, in _wrapper_view
return view_func(request, *args, **kwargs) …
Local vars
Variable Value
args
()
kwargs
{}
login_url
None
redirect_field_name
'next'
request
<WSGIRequest: GET '/accounts/update_profile/'>
test_func
<function login_required.<locals>.<lambda> at 0x7fd41efe3130>
view_func
<function ProfileUpdateView at 0x7fd41efe30a0>
/websiteV2/accounts/views.py, line 17, in ProfileUpdateView
p_form = ProfileUpdateForm(instance=request.user.profile) …
Local vars
Variable Value
request
<WSGIRequest: GET '/accounts/update_profile/'>
u_form
<CustomUserChangeForm bound=False, valid=Unknown, fields=(username;email;password)>