Tony Sherman Tony Sherman -4 years ago 33
Python Question

Django not committing form to database

The use case is that a logged in use, can call up their profile into a form, edit it and it gets updated in the database.

With the code below the correct Profile data can be viewed. It can also be called up into an editable form. The form allows the data to be edited , but when it is submitted, the database is NOT updated and the original profile is displayed.

I’ve tried everything, including console print statements so I know that it is getting to the POST portion of the code, is a valid form and doing the initial save().

Any insights would be appreciated (I am using Django 1.11). I do not want to start a rabbit running but the only thing I have not tried is breakink the OneToOne relationship with User and using a foriegnkey because I want the profile entry creaed when the user registers.

Notes:
When I popped this in for testing purposes: save_data.user = request.user
I get the error: Exception Value:'User' object has no attribute 'cleaned_data'`from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save

Models.py

from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save

class UserProfile(models.Model):
user = models.OneToOneField(User)
description = models.CharField(max_length=100, default='')
city = models.CharField(max_length=100, default='')
website = models.URLField(default='')
phone = models.IntegerField(default=0)
balance = models.FloatField(default=0)
bank = models.FloatField(default=0)
image = models.ImageField(upload_to='profile_image', blank=True)

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

def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = UserProfile.objects.create(user=kwargs['instance'])

post_save.connect(create_profile, sender=User)


Forms.py

from django import forms
from django.contrib.auth.models import User
from .models import UserProfile

class ProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('description', 'city', 'phone', 'balance', 'bank', 'website', 'image')


Views.py

from __future__ import unicode_literals
from django.core.urlresolvers import reverse
from django.contrib.auth import login, authenticate, update_session_auth_hash
from django.contrib.auth.forms import (
UserCreationForm,
UserChangeForm,
PasswordChangeForm
)
from django.contrib.auth.models import User
from django.shortcuts import render, redirect
from core.forms import ( EditAccountForm, SignUpForm,
ProfileForm
)
from core.models import UserProfile
from django.views.generic import (TemplateView,ListView,
DetailView,CreateView,
UpdateView,DeleteView)

# Create your views here.
def edit_profile(request):
if request.method == 'POST':
form = ProfileForm(request.POST, instance=request.user)
if form.is_valid():
save_data = form.save()
save_data.user = request.user
print(save_data)
save_data.save()
return redirect(reverse('core:profile'))
else:
udata = UserProfile.objects.get(user=request.user)
form = ProfileForm(instance=udata)
args = {'form': form}
return render(request, 'core/test.html', args)


urls.py

from django.conf.urls import url
from django.contrib import admin
#from playme.core import views as core_views
from core import views as core_views
from django.contrib.auth import views as auth_views

# SET THE NAMESPACE!
app_name = 'core'


urlpatterns = [
url(r'^$', core_views.index, name='index'),
url(r'signup/$', core_views.signup, name='signup'),
url(r'^account/$', core_views.account, name='account'),
url(r'^profile/$', core_views.view_profile, name='profile'),
url(r'^login/$', auth_views.login, {'template_name': 'core/login.html'}, name='user_login'),
url(r'^logout/$', auth_views.logout, {'next_page': '/play/'}, name='logout'),
url(r'^edit_account/$', core_views.edit_account, name='edit_account'),
url(r'^edit_profile/$', core_views.edit_profile, name='edit_profile'),
url(r'^change_password/$', core_views.change_password, name='change_password'),
]


The URL I am hitting is:
http://127.0.0.1:8000/play/profile/
Which then goes to :
http://127.0.0.1:8000/play/edit_profile/

The form loads up but when submitted goes back to:
http://127.0.0.1:8000/play/profile/

With no database update.

Answer Source

I'm surprised this doesn't give an error.

When you instantiate the form on a GET, you correctly pass the UserProfile object as the instance parameter - this is correct because the form has that as its model. But when you instantiate on POST, you incorrectly pass the User object - request.user. You should pass the profile, as you do in the other branch.

Note, in both cases you can get the profile more simply by just doing request.user.userprofile.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download