且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何使用modelformset上传多个图像 - Django

更新时间:2023-01-15 13:18:49

当您调用 VegetableForm时。 save(),它返回实例,所以你应该做

  vegetable = AddVegetableForm.save )

在表单集中保存对象建议调用 formset.save(),它返回一个实例列表。您可以使用 commit = False 调用 save(),设置蔬菜,然后保存到数据库。

  images = formset.save(commit = False)
图像中的图像:
image.vegetable =蔬菜
image.save()


I am trying to create a system which allows a user to be able to add a new Vegetable object, upload a thumbnail and multiple images and files - all from the AddVegetable page, and be able to output this easily as the vegetable types are filtered to display on different pages

I'm trying to achieve this with the code below but it won't work and I cant figure out why exactly, as it stands I'm getting a KeyError 'image', but I don't know why. I am going about this the right way at all?

I am ignoring image processing for the moment,

models.py

class Vegetable(models.Model):
    title = models.CharField(max_length=0)
    category = models.CharField(max_length=50,
                                choices=CATEGORY_CHOICES)
    description = models.CharField(max_length=1000, null=True)
    thumbnail = models.ImageField(upload_to = 'uploaded_images/')
    attachments = models.FileField(upload_to = uploaded_files/)
    date_added = models.DateTimeField('Date Added', default=datetime.datetime.now)

class VegetableImage(models.Model):
    vegetable = models.ForeignKey(Vegetable, default=None)
    image = models.ImageField(upload_to='images/vegetable',
                             verbose_name='image',)

forms.py

Class AddVegetable(ModelForm):
    class Meta:
          model = Vegetable
          fields = ['title', 'category', 'description', 'thumbnail',
                    'images', 'attachments', 'date_added',]

class ImageForm(ModelForm):
    image = ImageField(label='image')
    class Meta:
        model = VegetableImage
        fields = ['image',]

views.py

def AddVegetable(request):

ImageFormSet = modelformset_factory(VegetableImage,
                                    form=ImageForm, extra=4)

if request.method == 'POST':

    VegetableForm = AddVegetableForm(request.POST)
    formset = ImageFormSet(request.POST, request.FILES,
                           queryset=VegetableImage.objects.none())

    if VegetableForm.is_valid() and formset.is_valid():

        VegetableForm.save()

        for form in formset.cleaned_data:
            image = form['image']
            picture = VegetableImage(vegetable=VegetableForm, image=image)
            picture.save()

        return HttpResponseRedirect('/vegetable/')
    else:
        print (VegetableForm.errors, formset.errors)

else:
    VegetableForm = AddVegetableForm()
    formset = ImageFormSet(queryset=VegetableImage.objects.none())

return render(request, 'vegetable/add.html',
              {'VegetableForm': VegetableForm, 'formset': formset},
              context_instance=RequestContext(request))

template.html

<form action="/vegetable/add/" method="POST" enctypr="multipart/form-data"> 
{% csrf_token %}
    <table>

            <p> {{ VegetableForm.as_ul }}</p>

            {{ formset.management_form }}
            {% for form in formset %}
            {{ form }}
            {% endfor %}

    </table>

    <input type="submit" value="Post">
</form>

When you call VegetableForm.save(), it returns the instance, so you should do

vegetable = AddVegetableForm.save()

The docs on saving objects in a formset suggest calling formset.save(), which returns a list of instances. You can call save() with commit=False, set the vegetable, then save to the database.

images = formset.save(commit=False)
for image in images:
    image.vegetable = vegetable
    image.save()