Reputation: 888
I have a Django ModelForm where I want to set a ForeignKey with a user instance when validating, it's hidden on the template so the user can't set this.
The view:
def view1(request):
if request.method == "POST":
model1form = Model1Form(request.POST, request.FILES, user=request.user)
if model1form.is_valid(): # fails here
print "is valid"
Form:
class Model1Form(forms.ModelForm):
class Meta:
model = Model1
fields = ['person_id', 'start_date', 'end_date']
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(Model1Form, self).__init__(*args, **kwargs)
def clean(self):
cleaned_data = super(Model1Form, self).clean()
start_date = cleaned_data.get("start_date")
end_date = cleaned_data.get("end_date")
username = self.user
person = Person.objects.get(username_field=username)
person_id = person.id
print person_id # this prints fine
# custom validation
return cleaned_data
This clean method fails when I run is_valid(). But runs fine without the person_id stuff. What am I doing wrong?
Models:
class Model1(models.Model):
person_id = models.ForeignKey(Person, null=True)
start_date = models.DateField(null=True, blank=True)
end_date = models.DateField(null=True, blank=True)
class Person(models.Model):
first_name = models.CharField(max_length=15, default='')
surname = models.CharField(max_length=30, default='')
def __unicode__ (self):
return self.first_name + ' ' + self.surname
Is this the wrong approach to this?
Upvotes: 0
Views: 151
Reputation: 2288
First let's change your model a bit
class Model1(models.Model):
person = models.ForeignKey(Person, null=True)
start_date = models.DateField(null=True, blank=True)
end_date = models.DateField(null=True, blank=True)
Previously you had person_id
as the foreign key which meant you would have a field person_id_id
which is just weird to read.
Now for the form. You need to make sure your fk is part of the cleaned data.
class Model1Form(forms.ModelForm):
class Meta:
model = Model1
fields = ['start_date', 'end_date']
...
def clean(self):
cleaned_data = super(Model1Form, self).clean()
...
username = self.user
person = Person.objects.get(username_field=username)
cleaned_data["person_id"] = person.id
# if that doesn't work try cleaned_data["person"] = person
...
return cleaned_data
Upvotes: 0
Reputation: 309049
There's no need for a hidden field here. Leave the field out of the model form:
class Model1Form(forms.ModelForm):
class Meta:
model = Model1
fields = ['start_date', 'end_date']
Then in your view, save with commit=False
, then set the person
on the instance.
if request.method == "POST":
model1form = Model1Form(request.POST, request.FILES, user=request.user)
if model1form.is_valid(): # fails here
instance = model1form.save(commit=False)
instance.person = Person.objects.get(username_field=request.user)
instance.save()
See the docs on the model form's save()
method for more info.
Once you have made this change, you may find that you can remove user
from the form's __init__
method.
Upvotes: 2