views:

114

answers:

1

I have a Model Formset that should take files sent via POST and add them to the database.

However, the form includes the IDs of files already in the database, which leads to information being overwritten. For example, the HTML output for the form looks like this:

<label for="id_files-0-theFile">File:</label> 
    <input type="file" name="files-0-theFile" id="id_files-0-theFile" />
    <input type="hidden" name="files-0-id" value="1" id="id_files-0-id" />
.... and so on, for each entry form 0 .. 10

That third line -- the files-0-id -- is what I believe leads to the overwriting, but I don't know how to fix this. I want the system to create new File objects for each submission, not use existing IDs.

My template prints the form information like so:

 <form action=... >
 {{ fileform.management_form }} 

 {% for form in fileform.forms %}
  {{ form.as_p }}
 {% endfor %}
 </form>

And the relevant parts of the model, form, and view are:

class File(models.Model):
    theFile = models.FileField("File", upload_to='files/%Y/%m/%d')
    entry = models.ForeignKey(Entry)
    size = models.CharField(blank=True, max_length=100)
    name = models.CharField(blank=True, max_length=150)


class FileForm(forms.ModelForm):
    class Meta:
        model = File
        exclude = ('entry', 'size')


def add(request):

FileFormSetFactory = modelformset_factory(File, form=FileForm, extra=8,
                                    exclude=file_forms_excludes,)
file_formset = FileFormSetFactory(prefix='files')

if request.method == 'POST':

    file_formset = FileFormSetFactory(request.POST, request.FILES, 
                                      prefix='files')

    if file_formset.is_valid():

        for f in file_formset.save(commit=False):                
            f.name = f.theFile.name.split("/")[-1]
            f.size = convert_bytes(f.theFile.size)
            f.entry = entry #primary key to another object, removed for clarity



            f.save()

        ...

        return HttpResponseRedirect('/doc/' + str(entry.id)) 

else:
    context = {}
    context['fileform'] = file_formset
    context['entryform'] = entry_form
    context['entities'] = entities()
    return render_to_response('add.html', context)
A: 

The answer is in the docs:

By default, when you create a formset from a model, the formset will use a queryset that includes all objects in the model (e.g., Author.objects.all()). You can override this behavior by using the queryset argument

Just use ObjectName.objects.none()

Odd default behavior, but there you go.

Matt Hampel