I am following a Django tutorial on Youtube, I added a bio field in the UserUpdateForm. There is a slot for me to edit the bio on change_profile.html but when I press the update button it updates everything else except for the bio.
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import Profile
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
class UserUpdateForm(forms.ModelForm):
email = forms.EmailField()
# What I added
bio = forms.CharField(required=False)
class Meta:
model = User
fields = ['username', 'email', 'bio']
class ProfileUpdateForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['image']
The function that saves the forms
@login_required
def change_profile(request):
if request.method == 'POST':
u_form = UserUpdateForm(request.POST, instance=request.user)
p_form = ProfileUpdateForm(request.POST, request.FILES, instance=request.user.profile)
if u_form.is_valid() and p_form.is_valid():
u_form.save()
p_form.save()
messages.success(request, 'Profile Updated')
return redirect('profile')
else:
u_form = UserUpdateForm(instance=request.user)
p_form = ProfileUpdateForm(instance=request.user.profile)
context = {
'u_form' : u_form,
'p_form' : p_form
}
return render(request, 'users/change_profile.html', context)
The change_profile.html
{% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% block title %}Change Profile{% endblock title %}
{% block content %}
<div >
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<fieldset >
<legend >Edit Profile</legend>
{{ u_form|crispy }}
{{ p_form|crispy }}
</fieldset>
<div >
<button type="submit">Update</button>
</div>
</form>
</div>
{% endblock content %}
And the profile.html
{% extends "blog/base.html" %}
{% block title %}Profile{% endblock title %}
{% block content %}
<div >
<div >
<img src="{{ user.profile.image.url }}">
<div >
<h2 >{{ user.username }}</h2>
<p >{{ user.email }}</p>
<p >{{ user.bio }}</p>
</div>
</div>
<a href="{% url 'change_profile' %}">Edit Profile</a>
{% endblock content %}
CodePudding user response:
It's because the default User model has no attribute called bio, so there's nowhere to store the value you're getting from the form. You need to add it to the model first. You can create a custom user model, but since you already have a Profile model, you can store bio along with image:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField()
bio = models.CharField(max_length=225, blank=True, null=True)
And in forms.py add the new field to the field list:
class ProfileUpdateForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('image', 'bio')
CodePudding user response:
You could have simply override the the User model and add your custom fields, then you don't need to add extra fields in your form. Check this example:
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User)
bio = models.TextField()
def __str__(self):
return unicode(self.user)
Make sure you add mention your custom User model in settings:
AUTH_USER_MODEL ='your_app.UserProfile'
