Question

I am trying to create a ModelForm for the student class. this uses the currently logged in user as the one to one relationship between Django's auth system and my model. I can not get this to validate to save my life. Here are the relevant models:

class student(models.Model):
    user_id =  models.OneToOneField(User,unique=True)
    first_name = models.CharField(max_length=45)
    last_name = models.CharField(max_length=45)
    #enrolled_classes = models.ManyToManyField('agility_class')
    #completed_classes =    models.ManyToManyField('agility_class')
    email_address = models.EmailField()
    phone_number = PhoneNumberField()
    training_experience = models.CharField(max_length=500)
    #training_materials = 



    def __unicode__(self):
        return self.first_name + " " + self.last_name;


class studentForm(ModelForm):
    class Meta:
        model = student

My views looks like this:

def profile_creation(request):
    if request.method == 'POST':
        thisform = studentForm(request.POST)
        if thisform.is_valid():
            thisform.save()
            return HttpResponseRedirect('/about')

    return render(request, 'profile_registration.html') 

Here is what the form from my template looks like:

<form class="form-horizontal" method = 'POST'>
{%csrf_token%}
<fieldset>

<!-- Form Name -->
<legend>Profile</legend>

<!-- Text input-->
<div class="control-group">
  <label class="control-label" for="first_name">First Name</label>
  <div class="controls">
    <input id="first_name" name="first_name" type="text" placeholder="" class="input-large">

  </div>
</div>

<!-- Text input-->
<div class="control-group">
  <label class="control-label" for="last_name">Last Name</label>
  <div class="controls">
    <input id="last_name" name="last_name" type="text" placeholder="" class="input-large">

  </div>
</div>

<!-- Text input-->
<div class="control-group">
  <label class="control-label" for="email">Email</label>
  <div class="controls">
    <input id="email_address" name="email_address" type="text" placeholder="" class="input-large">

  </div>
</div>

<!-- Text input-->
<div class="control-group">
  <label class="control-label" for="phone_number">Phone Number</label>
  <div class="controls">
    <input id="phone_number" name="phone_number" type="text" placeholder="" class="input-large">
    <p class="help-block">Format: 123-456-7890</p>
  </div>
</div>

<!-- Textarea -->
<div class="control-group">
  <label class="control-label" for="training_experience">Training Experience</label>
  <div class="controls">                     
    <textarea id="training_experience" name="training_experience"></textarea>
  </div>
</div>
<input type="hidden" name= "user_id" value ="{{ user.username }}">
<input type="submit" value="submit">

</fieldset>
</form>

Maybe I am missing something drastic....Thanks in advance for your help.

Was it helpful?

Solution

Your form is posting the value request.user.username, which is not an instance of a User object. To make your code work as-is, you would have to first retrieve the user by username, then assign the property as such:

def profile_creation(request):
    student_form = StudentForm(request.POST or None)
    if request.method == 'POST':
        username = request.POST.get('username')
        try:
            user = User.objects.get(username=username)
            student = StudentForm.save(commit=False)
            student.user = user
            student.save()
        except User.DoesNotExist:
            # handle the exception
        ...

You have to populate user_id, which btw I would simply name user, because "user_id" is misleading imo, with a user instance. Instead of doing that in the view, which in the above sample is getting messy, you'd be better off assigning that value in your form class to keep your view clean.

# classes ALWAYS start with a capital letter in Python
class Student(models.Model):
    user_id =  models.OneToOneField(User,unique=True)
    ...

class StudentForm(ModelForm):
    class Meta:
        model = student

    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user')
        super(StudentForm, self).__init__(*args, **kwargs)
        self.fields['user'] = user

# views.py
from django.core.urlresolvers import reverse

def profile_creation(request):
    # Assumes the user is authenticated, otherwise request.user
    # will be an AnonymousUser instance...
    student_form = StudentForm(request.POST or None, user=request.user)
    if request.method == 'POST':
        if student_form.is_valid():
            student_form.save()
            # don't hard-code urls - use reverse lookups
            return HttpResponseRedirect(reverse('about'))

    return render(request, 'profile_registration.html',
        {'student_form': student_form}) 

OTHER TIPS

Yes, You need to get User object by username.

user = request.POST.get(username=username)

And then you can save user object into OneToOneField.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top