Beginner Django has a lot of trouble getting forms. Yes, I worked on the textbook and browsed the Internet many times - I have a mixture of what I find here and on other sites. I am using Python 2.7 and Django 1.5. (although the official documentation is extensive, it usually assumes that you know most of it — not very well, like a beginner’s guide or even an extended tutorial).
I am trying to create a form for "advanced" user details - for example. company name, street address, etc., but the form data is not stored in the database.
At first I tried to create a model that extends the standard User model, but I abandoned this - I had to modify too much, and it was part of nitty gritty, which was far beyond me at this stage. So instead, I created a new model called UserProfile :
class UserProfile(models.Model): user = models.ForeignKey(settings.AUTH_USER_MODEL, unique=True) company = models.CharField(max_length=50, blank=True) address1 = models.CharField(max_length=50, blank=True) address2 = models.CharField(max_length=50, blank=True) city = models.CharField(max_length=20, blank=True) region = models.CharField(max_length=20, blank=True) postcode = models.CharField(max_length=10, blank=True) country = models.CharField(max_length=20, blank=True) phone = models.CharField(max_length=30, blank = True)
I have seen various online links about whether I should reference the user model using ForeignKey (as mentioned above) or using OneToOne.
I am trying to use ModelForm (keep it simple for what should be a simple form). Here are my forms.py
from django.forms import ModelForm from .models import UserProfile class UserDetailsForm(ModelForm): class Meta: model = UserProfile fields = ['company','address1','address2','city','region', 'postcode','country','phone']
Here is my view:
def UserDetailsView(request): #f = 0 if request.method == 'POST': f = UserDetailsForm(request.POST, instance = request.user) if f.is_valid(): f.save() else: f = UserDetailsForm(request.POST , instance = request.user) print "UserDetails objects: ", (UserProfile.objects.all()) return render_to_response('plagweb/console/profile.html', { 'form': f}, context_instance=RequestContext(request))
(yes, there is inconsistency in UserProfile and UserDetail - this is the product of my entire hack and will be fixed after I receive it)
Diagnostics shows f.is_valid() returning True. Similarly, the diagnostics show UserProfile.objects.all() as empty. I tried this in the above view after saving (), and also in the Django console.
Here is my template:
<form method="POST" action=""> <table>{{ form }}</table> <input type="submit" value="Update" /> {% csrf_token %} </form>
At the moment, the main problem is that the form data is not stored in the database. I don't know if it is readable or not (when I have data in the database ...)
One thought is that a User connection might cause a problem?
Additions, following from Daniel Roseman helpful comment / help:
Now the form is saved correctly (confirmed by diagnostics and command line checks. However, when I return to the form, it does not display the existing data. The form is displayed with empty data fields. As far as I can tell, I am passing the instance data correctly.
Is there a ModelForm parameter that needs to be changed?
The view has been changed here:
def UserDetailsView(request): #print "request co:", request.user.profile.company f = UserDetailsForm(request.POST, instance = request.user.profile ) if request.method == 'POST': if f.is_valid(): profile = f.save(commit=False) profile.user = request.user profile.save() return render_to_response('plagweb/console/profile.html', { 'form': f}, context_instance=RequestContext(request))
Diagnostics show that request.user.profile set correctly (in particular, the company field). However, the form is displayed with empty fields. The HTML source also does not display data values. As an additional check, I also tried some diagnostic patterns:
<table border='1'> {% for field in form%} <tr> <td>{{field.label}}</td> <td>{{field.value}}</td> </tr> {% endfor%} </table>
This displays the field labels correctly, but all values are specified as None .
For completeness, the UserProfile user field is now defined as user = models.OneToOneField(settings.AUTH_USER_MODEL) , and the lambda User.profile expression does not change.