Reputation: 25584
I'm trying to save a ModelForm, but I'm getting an error:
InternalError at /submeter/anuncio/
current transaction is aborted, commands ignored until end of transaction block
I will try to explain what I'm doing.
Ok, I have 5 Models that I need to save at once in one form. I'm testing to save on two models but as I said, I'm getting error on the save method. As a beginner I'm getting a little bit lost on the best way to achieve the task.
What I've done:
Template:
<form method="post" action="/submeter/anuncio/">{% csrf_token %}
{{form_main}}
{{form_bicyclead}}
<input type="hidden" name="section" value="5" />
<input type="submit">
</form>
Views.py:
def submit_data_entry_view(request):
if request.method == 'GET': #first time rendering the form
form_main = MainForm()
form_bicyclead = BicycleAdForm()
return render_to_response('app_t/submit_data_entry.html', {'form_main': form_main, 'form_bicyclead': form_bicyclead}, context_instance=RequestContext(request))
def submit_ad_view(request):
if request.method == 'POST':
post_values = request.POST.copy()
post_values['user'] = request.user.username
post_values['bicycleadtype'] = 2
post_values['bicycleaditemkind'] = 4
post_values['bicycleadcondition'] = 2
post_values['city'] = 4803854
form_main = MainForm(post_values)
form_bicyclead = BicycleAdForm(post_values)
if form_main.is_valid() and form_bicyclead.is_valid():
form_main.save()
#form_bicyclead.save()
resultado = 'valid'
else:
resultado = 'n_valid'
pdb.set_trace()
return render_to_response('app_t/submit_ad.html', {'resultado': resultado}, context_instance=RequestContext(request))
Forms.py:
class MainForm(forms.ModelForm):
class Meta:
model = Main
exclude = ('user', 'section')
class BicycleAdForm(forms.ModelForm):
class Meta:
model = BicycleAd
exclude = ('main', 'bicycleadtype', 'bicycleaditemkind', 'bicycleadcondition', 'city')
Models.py:
class Main(models.Model):
section = models.ForeignKey(Section)
user = models.ForeignKey(User)
title = models.CharField(max_length=250)
date_inserted = models.DateTimeField(auto_now_add=True)
date_last_update = models.DateTimeField(auto_now=True)
def __unicode__(self):
return self.title
class Meta:
ordering = ['date_inserted']
class BicycleAd(models.Model):
main = models.ForeignKey(Main)
bicycleadtype = models.ForeignKey(BicycleAdType)
bicycleaditemkind = models.ForeignKey(BicycleAdItemKind) # MPTT Model
bicycleadcondition = models.ForeignKey(BicycleAdCondition)
country = models.ForeignKey(GeonamesCountry)
city = models.ForeignKey(GeonamesLocal)
date_inserted = models.DateTimeField(auto_now_add=True)
date_last_update = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['date_inserted']
My question is: How can I "override" the form_main.save() in the views.py and tell them all the fields that I have in the model "section, user and title"? I think the error is because of the fields "section" and "user" that are not passing to the save method. How can I pass this values?
Another question: I'm doing this the right way or there are easier and simple ways to achieve what I'm trying to achieve?
Best Regards
Upvotes: 1
Views: 3641
Reputation: 39709
Modify your model form as:
class MainForm(forms.ModelForm):
def __init__(self, *args, **kw):
self.user = kw.pop('user')
self.section = kw.pop('section')
super(MainForm).__init__(*args, **kw)
class Meta:
model = Main
exclude = ('user', 'section')
def save(self, *args, **kw):
instance = super(MainForm).save(commit=False)
instance.user = self.user
instance.section = self.section
instance.save()
return instance
Now you need to pass the user
and section
when you are creating an intance of the form in your view:
form_main = MainForm(request.POST or None, user=request.user, section=section)
Upvotes: 3
Reputation: 51715
My approach is to replace this code:
def submit_ad_view(request):
if request.method == 'POST':
post_values = request.POST.copy()
post_values['user'] = request.user.username
post_values['bicycleadtype'] = 2
post_values['bicycleaditemkind'] = 4
post_values['bicycleadcondition'] = 2
post_values['city'] = 4803854
form_main = MainForm(post_values)
by:
def submit_ad_view(request):
if request.method == 'POST':
model = Main() #if model exists get it!
#Notice, Main is the name of your model.
model.user = request.user.username
...
model.bicycleaditemkind = 4
...
form_main = MainForm(request.POST, instance = model )
You can learn more on Creating forms from models django doc.
Upvotes: 2