장고 - Multi image upload 학습
- 이번 포스트에서는 한번에 여러 이미지들을 업로드하는 방법에 대해 학습해볼 것이다.
ex) yanolja_project
1. 모델 작성
- 경로 : stay(앱) > models.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20from django.db import models
from django.contrib.auth.models import get_user_model
from django.template.defaultfilters import slugify
class Stay(models.Model):
name = models.CharField(max_length=50)
username = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, related_name="stays")
...
def get_image_filename(instance, filename):
name = instance.stay.name
slug = slugify(name)
return "stay_images/%s-%s" % (slug, filename)
class Image(models.Model):
stay = models.ForeignKey(Stay, on_delete=models.CASCADE, related_name="images_stay")
image = models.ImageField(upload_to=get_image_filename, verbose_name="Image")
def __str__(self):
return self.stay.name + "image"
2. 폼 작성
- 경로 : stay > forms.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22from django import forms
from .models import *
class StayForm(forms.ModelForm):
class Meta:
model = Stay
fields = ('name', 'location', 'introduce', ...)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['name'].label = '상호명'
self.fields['location'].label = '위치'
self.fields['introduce'].label = '숙소 소개'
...
class ImageForm(forms.ModelForm):
image = forms.ImageField(label='')
class Meta:
model = Image
fields = ('image',)
3. 뷰 작성(객체 생성 시, 이미지 멀티 업로드)
- 경로 : stay > views.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36from django.shortcuts import render, redirect
from django.forms import modelformset_factory
from django.contrib.auth.decorators import login_required
from django.urls import reverse
from .forms import *
def stay_create(request):
# modelformset_factory 함수 사용(extra로 최대 업로드할 수 있는 이미지 개수 설정)
ImageFormSet = modelformset_factory(Image, form=ImageForm, extra=3)
if request.method == "POST":
stay_form = StayForm(request.POST, request.FILES)
formset = ImageFormSet(request.POST, request.FILES, queryset=Image.objects.none())
# form validation
if stay_form.is_valid() and formset.is_valid():
stay_form = stay_form.save(commit=False)
stay_form.username = request.user
stay_form.save()
for form in formset.cleaned_data:
# 유저가 모든 이미지들을 업로드하지 않았을 경우 crash 방지
if form:
image = form['image']
photo = Image(stay=stay_form, image=image)
photo.save()
# urls.py에서 app_name이 stay이고, name이 stay_list인 url로 이동
return redirect(reverse("stay:stay_list"))
else:
print(stay_form.errors, formset.errors)
else:
# method가 POST가 아닌 경우, 즉 처음 stay_create url로 이동한 경우
stay_form = StayForm()
formset = ImageFormSet(queryset=Image.objects.none())
return render(request, 'stay/stay_create.html', {'stay_form':stay_form, 'formset':formset})
4. 커스텀 템플릿 작성
- 경로 : stay > templates > stay > stay_create.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14{% block content %}
<div>
<form id="stay_form" method="post" action="" enctype="multipart/form-data">
{% csrf_token %}
{{ stay_form.as_p }}
{{ formset.management_form }}
{% for form in formset %}
{{ form }}
{% endfor %}
<div style="height:30px;"></div>
<input type="submit" name="submit" value="upload" />
</form>
</div>
{% endblock %}
Posted