"save and add more" in Django (not admin): submit then pre-fill one form field

I have a form, "results" where one of the "subjectID" fields is "many-to-many" because there is more than one result for each subject. I want one of the submit buttons to allow me to save what I entered and then redirect to the same form, now unbound, except that the "subjectID" field is many-to-many the same so I can enter more results for this object.

Edit . It should have been clear to me that I wanted the instance I selected in the subjectID field to remain the same. I posted below code which seems to work for me

from models.py

 class ResultsForm(forms.Modelform):
     class Meta:
         model = models.Results
         fields = ['subjectID', # this is the field want
      # to populate the form with when I "save and add another"
              'slideNum', # IntegerField
              'resultType' ] # ForeignKey

      

from views.py

def addResults(request):
    if request.method == 'POST'
         form = ResultsForm(request.POST)
         if form.is_valid():
             form.save()
         if 'Save_and_add_another' in request.POST:
            subjectID = form.fields['subjectID']
            prepop = {'subjectID' : subjectID}
            form = ResultsForm(initial=prepop)
            return render(request, 'slideAdmin/addResults.html', {'form': form})
        elif 'Save_and_return' in request.POST:
            return HttpResponseRedirect('/home/')    
    else:
        form = ResultsForm()
    return render(request, 'slideAdmin/addResults.html', {'form': form})

      

Right now, when I click Save and Add Other from my addResults form, I get this error:

TypeError at /slidebox/addResults

'ModelMultipleChoiceField' object is not iterable

      

which happens when {{form.as_p}} is rendered in the template.

Edit: Changes made to views.py

    if 'Save_and_add_another' in request.POST:
        subjectID = form.cleaned_data.get('subjectID')
        form = ResultsForm(initial={'subjectID': subjectID})
        return render(request, 'slideAdmin/addResults.html', {'form': form})

      

As far as I can tell, this change works. Thanks again

+3


source to share


2 answers


You should always use form.cleaned_data.get('subjectID')

against pulling fields directly from the message data. You need to pass the pk list for the M2M field.

You can also use cleanup in your view:



from django.core.urlresolvers import reverse


def addResults(request):
    form = ResultsForm(request.POST or None)

    if request.method == 'POST' and form.is_valid():
        form.save()

        if 'Save_and_add_another' in request.POST:
            subjectID = form.cleaned_data.get('subjectID', [])
            if subjectID:
                subjectID = subjectIDs.split(',')
            form = ResultsForm(initial={'subjectID': subjectID})

        elif 'Save_and_return' in request.POST:
            return HttpResponseRedirect(reverse('home'))  # don't hard code

    return render(request, 'slideAdmin/addResults.html', {'form': form})

      

0


source


I'm not sure if you will be able to keep the unbound form on initialization.

Your form.fields are the ordered type of django.forms.fields objects. You just need the IDs, not all the other information that meets it.

Get data straight from the POST dictionary.

subjectID = request.POST.get('subjectID', '')

      

If it is a model for many models. You need to make sure the data is configured correctly for initialization.

# We have to special-case M2Ms as a list of comma-separated PKs.
if isinstance(f, models.ManyToManyField):
    initial[k] = initial[k].split(",")

      



Here is the initialization method from django source code for Admin (or, as I call it, my super verbose and complex Django cheat sheet, I'm being pedantic)

def get_changeform_initial_data(self, request):
    """
    Get the initial form data.
    Unless overridden, this populates from the GET params.
    """
    initial = dict(request.GET.items())
    for k in initial:
        try:
            f = self.model._meta.get_field(k)
        except FieldDoesNotExist:
            continue
        # We have to special-case M2Ms as a list of comma-separated PKs.
        if isinstance(f, models.ManyToManyField):
            initial[k] = initial[k].split(",")
    return initial

      

Some PEP8 bug as well

classes are the case of camel ex: class MyAwesomeClass(object):

everything else below is underlined. ex:awesome_id = awesome1245

Good luck !!

0


source







All Articles