Uploading multiple images in Django for a single p

2019-08-31 16:52发布

问题:

I am beginner in django . I would like to make an application that allows a user to record examinations and related images.

So i try to uploading multiple images in Django for a single post according this topic http://qasimalbaqali.com/uploading-multiple-images-in-django-for-a-single-post/.

But nothing happens when I press the button I explain my models. A document is a generic class. An exam is a document, a document contains files.

class Document(models.Model):

    class Meta:
        db_table = 'Document'

    slug = models.SlugField(max_length=100)
    user = models.ForeignKey(User)
    level = models.ForeignKey(ClassLevel, null=False, default=1)
    school = models.ForeignKey(School, null=False, default=1)
    nb_views = models.IntegerField(default=0)
    name = models.CharField(max_length=100)
    matter = models.ForeignKey(ClassTopic, null=False, default=1)
    status = models.IntegerField(choices=DOCUMENT_STATUS, default=1)
    creation_date = models.DateTimeField(auto_now_add=True)
    deletion_date = models.DateTimeField(auto_now_add=False, default=None, null=True)

    def __unicode__(self):
        return self.name + " (" + str(self.status) + ") " + self.school.name


class DocumentFile(models.Model):

    class Meta:
        db_table = 'DocumentFile'

    file = models.FileField(upload_to="photo/", null=True)
    document = models.ForeignKey(Document)

    def __unicode__(self):
        return self.file

class Exam(Document):

    class Meta:
        db_table = 'Exam'
    year_exam = models.IntegerField(choices=EXAM_YEAR_CHOICES, default=1)
    mock_exam = models.IntegerField(choices=EXAM_TYPE, default=1)

    def __unicode__(self):
        return self.name + " " + self.matter

I create two forms. For exam and for file.

class UploadFileForm(ModelForm):

    #description = forms.CharField(max_length=30)

    file = forms.FileInput()

    helper = FormHelper()
    helper.form_id = 'file-input'
    helper.form_show_labels = False
    helper.layout = Layout(PrependedText('file', "", placeholder=""))
    #helper.layout.insert(1, HTML("<input type='file' class='file' multiple data-show-upload='false' data-show-caption='true'>"))

    class Meta:
        model = DocumentFile
        fields = ('file',)
        #exclude = ("file_type", "file_path", "document")

class CreateExamForm(forms.ModelForm):

    helper = FormHelper()
    helper.form_id = 'CreateExam'
    helper.form_show_labels = False
    helper.layout = Layout(
        PrependedText("matter", "", ""),
        PrependedText("level", "<small class='text-warning'>Selectionner la classe. </small>", ""),
        PrependedText("school", "<pre><small>Selectionner l\'établissement. </small></pre>", css_class="selectpicker"),
        PrependedText("year_exam", ""),
        PrependedText("mock_exam", ""))

    class Meta:
        model = Exam
        exclude = ("slug", "user", "nb_views", "name", "status", "creation_date", "deletion_date")

My view

def createexam(request):

    # Creation du formulaire + upload des images
    doc_form = CreateExamForm(auto_id=True)

    # Création du formset avec n itération : extra=2
    file_form_set = modelformset_factory(DocumentFile, form=UploadFileForm, extra=1)

    # Récupération du formulaire géré par le mécanisme formset
    #formset = sortedfilesform()

    if request.method == "POST":

        doc_form = CreateExamForm(request.POST)
        files_form = file_form_set(request.POST, request.FILES, queryset=DocumentFile.objects.none())

        if doc_form.is_valid() and files_form.is_valid():
            doc_save = doc_form.save(commit=False)
            doc_save.user = request.user

            for fileform in files_form.cleaned_data:
                image = fileform['file']
                one_image = DocumentFile(document=doc_save, file_value=image)
                one_image.save(commit=False)
            transaction.commit()
            msg = FORM_PROPERTIES.FORM_EXAM_STORED.replace("user", request.user.nickname)
            messages.add_message(request, messages.SUCCESS, msg)
            form = LoginForm()
            context = {'form': form}
            return render_to_response(template_name='login.html', context=context, context_instance=RequestContext(request))
        else:
            messages.add_message(request, messages.SUCCESS, FORM_PROPERTIES.FORM_EXAM_ERROR)
            context = {'doc_form': doc_form, 'file_form_set': file_form_set, }
            return render(request, 'createexam.html', context)
    else:
        context = {'doc_form': doc_form, 'file_form_set': file_form_set, }
        return render(request, 'createexam.html', context)

my url.py

urlpatterns = [
    # Examples:
    url(r'^$', home, name='home'),
    url(r'^admin/', include(admin.site.urls)),
    url(r'^$', home),
    url(r'^home', home),
    url(r'^login', login),
    url(r'^logout', logout),
    url(r'^register$', register),
    url(r'^createexam$', createexam),
    url(r'^account/reset_password', reset_password, name="reset_password"),
]

My template is simple

<div id="login-overlay" class="modal-dialog">
<div class="row">
    <div class="panel panel-info" >
        <div class="panel-heading">
            <div class="panel-title">Créer un examen</div>
        </div>
        <div class="panel-body" >
            <div class="col-sm-12">
            <form id="post_form" method="POST" action='.'
                  enctype="multipart/form-data">

                {% csrf_token %}
                {% for hidden in doc_form.hidden_fields %}
                    {{ hidden }}
                {% endfor %}

                {% for field in doc_form %}
                    {{ field }} <br />
                {% endfor %}

                {{ file_form_set.management_form }}
                {% for form in file_form_set %}
                    {% crispy form %}
                {% endfor %}
                <input type="submit" value="Add recipe" class="submit" />
            </form>
            </div>
        </div>
    </div>
</div>

Everything seems good form me. But my submit does no think. I 'm on it for two days. I read and tried many things. Does anybody can help me please (Sorry for my english)

回答1:

There are a couple of things wrong here.

Firstly you are not showing the form errors in the template, so the user has no way of knowing why their submission is invalid. Make sure you either do {{ field.errors }} after every field, or do {{ form.errors }} for the whole form at once; and remember to do this both form the main form and the image formset.

Secondly, you're saving the forms with commit=False, so they are not persisted to the database. It's fine to do that if you want to add extra data not included in the form, but you then need to remember to actually persist the object by calling eg doc_save.save().



回答2:

I solved my problem when i put my main form body in <table> ... </table>

<form id="CreateExamForm" method="POST" enctypr="multipart/form-data">
                {% csrf_token %}
                <table>
                    <div class="panel panel-success">
                        <div class="panel-heading">
                            <h3 class="panel-title">Classe - Matière - Date</h3>
                            <span class="pull-right"><i class="glyphicon glyphicon-chevron-up"></i></span>
                        </div>
                        <div class="panel-body">
                            {% crispy doc_form %}

                            {{ file_form_set.management_form }}
                            {% for f_form in file_form_set %}
                                <div class="form-inline">
                                    {% crispy f_form %}
                                </div>
                            {% endfor %}
                        </div>
                    </div>
                </table>
                <input type="submit" value="Add recipe" class="submit" />
            </form>