I am stumped!
I am building a form that allows the user to fill in profile fields and user fields at the same time. There are examples all over the web for this and a number on this site (eg How to create a UserProfile form in Django with first_name, last_name modifications?)
however, try as i might, i keep on getting a none type user in my form.py
some code: forms.py
class ProfileForm(ModelForm):
first_name = forms.CharField(label="First name")
last_name = forms.CharField(label="Last name")
def __init__(self, *args, **kwargs):
super(ProfileForm, self).__init__(*args, **kwargs)
print self.instance #profile does not exist here
self.fields['first_name'].initial = self.instance.user.first_name
self.fields['last_name'].initial = self.instance.last_name
def save(self, *args, **kwargs):
super(ProfileForm, self).save(*args, **kwargs)
self.instance.user.first_name = self.cleaned_data.get('first_name')
self.instance.user.last_name = self.cleaned_data.get('last_name')
self.instance.user.save()
class Meta:
model = UserProfile
exclude = ('user')
urls.py
url(r'^profiles/edit/', 'profiles.views.edit_profile', {'form_class': ProfileForm}, name='edit_profile' ),
template.html
<div class="clearfix">
<legend>Edit your profile details</legend>
</div>
{% include 'profiles/profile_form.html' with user=user %}
the view is coming from django-profiles, but i have even tried pulling into an app and seen that my user exists and is being pulled into an instance in the view, the instance is devoid of user in the form!
other things of note: i am using email as my authentication method other than username, but still have a text based random username (because i understand there are issues with emails as usernames in django-profiles). Could this still be my issue?
if its helpful, here is my authenticate def:
def authenticate(self, username=None, password=None):
""" Authenticate a user based on email address as the user name. """
try:
user = User.objects.get(email=username)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
def get_user(self, user_id):
""" Get a User object from the user_id. """
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
this is references as a custom backend, and i have confirmed that it works.
I hope someone has some insight!
Edits:
my full exception:
Exception Type: TemplateSyntaxError
Exception Value: Caught AttributeError while rendering: 'NoneType' object has no attribute 'first_name'
Exception Location:/Users/willcadell/placespeak/webapps/place/../place/accounts/forms.py in __init__, line 13
view (from django-profiles):
def edit_profile(request, form_class=None, success_url=None,
template_name='profiles/edit_profile.html',
extra_context=None):
try:
profile_obj = request.user.get_profile()
print profile_obj #profile is good here
except ObjectDoesNotExist:
return HttpResponseRedirect(reverse('profiles_create_profile'))
if success_url is None:
success_url = reverse('profiles_profile_detail', kwargs={ 'username': request.user.username })
if form_class is None:
form_class = utils.get_profile_form()
if request.method == 'POST':
form = form_class(data=request.POST, files=request.FILES, instance=profile_obj)
if form.is_valid():
form.save()
return HttpResponseRedirect(success_url)
else:
form = form_class(instance=profile_obj)
if extra_context is None:
extra_context = {}
context = RequestContext(request)
for key, value in extra_context.items():
context[key] = callable(value) and value() or value
return render_to_response(template_name,
{ 'form': form,
'profile': profile_obj,},
context_instance=context)
I have also added two comments indicating where the profile exists and where it does not, ie it is in the view as profile_obj but does not appear in the form as self.instance.
Another (possibly unrelated) symptom is that for this exception page, django toolbar does not show up... weird!
This is what i ended up doing:
view.py:
def edit_profile(request):
profile_obj = request.user.get_profile()
print dir(profile_obj.profileasset_set)
asset_obj = profile_obj.
user_obj = request.user
if request.method == 'POST':
form = ProfileForm(request.POST, )
if form.is_valid():
profile_obj.twitter = form.cleaned_data['twitter']
profile_obj.about = form.cleaned_data['about']
profile_obj.url = form.cleaned_data['url']
profile_obj.save()
profile
user_obj.first_name = form.cleaned_data['first_name']
user_obj.last_name = form.cleaned_data['last_name']
user_obj.save()
form.save()
return HttpResponseRedirect('/profiles/profile')
else:
form = ProfileForm(instance=user_obj,
initial={
'first_name':user_obj.first_name,
'last_name':user_obj.last_name,
'twitter':profile_obj.twitter,
'url':profile_obj.url,
'about':profile_obj.about,
}
)
template = 'profiles/edit_profile.html'
data = {'form': form, }
return render_to_response(template, data, context_instance=RequestContext(request))
forms.py:
class ProfileForm(ModelForm):
first_name = forms.CharField(label="First name")
last_name = forms.CharField(label="Last name")
twitter = forms.CharField(label="Twitter")
about = forms.CharField(label="About", widget=forms.Textarea)
url = forms.CharField(label="URL")
class Meta:
model = UserProfile
fields = ('url', 'twitter', 'about')
hope this helps someone!