title: Django - How to do a transaction when saving a form?
body: <p>I'm saving a form, but there is one save() method that is outside the transaction. The save() method outside a transaction is the save() on the "BicycleAdCategoryForm".</p>
  
  <p>Here is the code:</p>
  
  <p>models.py</p>
  
  <pre><code>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
  
      # To order in the admin by name of the section
      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)
  
      # To order in the admin by name of the section
      class Meta:
          ordering = ['date_inserted']   
  
  
  class BicycleAdCategoryType(models.Model):
      n_bicycle_ad_category_type = models.CharField(max_length=100) # COMPRA, VENDA, TROCA
      date_inserted              = models.DateTimeField(auto_now_add=True)
      date_last_update           = models.DateTimeField(auto_now=True)
  
      def __unicode__(self):
          return self.n_bicycle_ad_category_type
  
      # To order in the admin by name of the section
      class Meta:
          ordering = ['n_bicycle_ad_category_type'] 
  </code></pre>
  
  <p>forms.py</p>
  
  <pre><code>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') # DPS RETIRAR DAQUI A "CITY"
  
  class BicycleAdCategoryForm(forms.ModelForm):
      bicycleadcategorytype = forms.ModelMultipleChoiceField(queryset=BicycleAdCategoryType.objects.all(), required=False, widget=forms.CheckboxSelectMultiple) # Se retirar o widget fico uma SELECT box em q posso selecionar varias opcoes
  
      class Meta:
          model = BicycleAdCategory
          exclude = ('bicyclead',)
  
      def save(self, commit, rel_obj):
          data = self.data.getlist('bicycleadcategorytype')
          for item in data:
              obj_bicycleadcategory = BicycleAdCategory()
              obj_bicycleadcategory.bicyclead = rel_obj
              obj_bicycleadcategory.bicycleadcategorytype = BicycleAdCategoryType.objects.get(pk=item)
              obj_bicycleadcategory.save()
  
      def clean_bicycleadcategorytype(self):
          data = self.cleaned_data['bicycleadcategorytype']
          try:
              for item in data:
                  bicycleadcategorytype = BicycleAdCategoryType.objects.get(pk=item.pk)
              return bicycleadcategorytype
          except (KeyError, BicycleAdCategoryType.DoesNotExist):
              raise forms.ValidationError('Invalid Bicycle Ad Category Type. Please try again.')    
  </code></pre>
  
  <p>views.py</p>
  
  <pre><code>def submit_ad_view(request):
      if request.method == 'POST':      
          model_main = Main()
          model_main.section = Section.objects.get(pk=request.POST['section'])
          model_main.user = request.user
  
          model_bicyclead = BicycleAd()
          model_bicyclead.bicycleadtype = BicycleAdType.objects.get(pk=2)
          model_bicyclead.bicycleaditemkind = BicycleAdItemKind.objects.get(pk=4)
          model_bicyclead.bicycleadcondition = BicycleAdCondition.objects.get(pk=2)
          model_bicyclead.city = GeonamesLocal.objects.get(pk=4803854)
  
  
          form_main = MainForm(request.POST, instance = model_main)
          form_bicyclead = BicycleAdForm(request.POST, instance = model_bicyclead)
          form_bicycleadcategory = BicycleAdCategoryForm(request.POST)
  
          if form_main.is_valid() and form_bicyclead.is_valid() and form_bicycleadcategory.is_valid():
              main_f = form_main.save()
  
              bicyclead_f = form_bicyclead.save(commit=False)
              bicyclead_f.main = main_f
              bicyclead_f.save()
  
              bicycleadcategory_f = form_bicycleadcategory.save(commit=False, rel_obj=model_bicyclead)
  
  
              resultado = 'valid'
          else:
              resultado = 'n_valid'
  
  
      return render_to_response('app/submit_ad.html', {'resultado': resultado}, context_instance=RequestContext(request))
  </code></pre>
  
  <p>I think main_f and bicyclead_f are inside a transaction but bicycleadcategory_f is outside a transaction. When bicycleadcategory_f fails, main_f and bicyclead_f are stored in the database.</p>
  
  <p>Any clue on what I'm doing wrong?</p>
  
  <p>Best Regards,</p>