모델수정, 이미지 추가
190409
fake-insta2
- 포스트 하나에 이미지 여러개 : 1대n관계
- 모델 수정
1
2
3
| # models.py
## column 추가
image = models.ImageField(blank=True)
|
1
2
| # form.html
<form action="" method="post" enctype="multipart/form-data">
|
-
이미지 저장
- 이미지는 Files에 image라는 변수로 저장되기 때문에 코드를 수정
- 경로수정 (django media file settings)
1
2
3
| # views.py
## 이미지 코드수정
form = PostForm(request.POST, request.FILES)
|
1
2
3
4
| # setting.py
## 이미지 저장결로 수정을 위해 코드 추가
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
1
2
3
4
5
6
7
8
9
| # insta-urls.py
## django media url
### settings.py의 여러 변수들을 접근 하려면
from django.conf import settings
### 정적파일을 넣으려면
from django.conf.urls.static import static
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
1
2
3
4
5
6
| # _post.html
{% if post.image %}
<img src="" class="card-img-top" alt="...">
{% else %}
<img src="..." class="card-img-top" alt="...">
{% endif %}
|
1
2
| $ pip install pilkit
$ pip install django-imagekit
|
1
2
3
4
5
6
| # setting.py
## imagekit을 사용하기위해 pilkit을 설치함 (의존성)
### 그래서 installed_app에는 imagekit만 추가해주면 됨
INSTALLED_APPS = [
'imagekit',
]
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # models.py
from imagekit.models import ProcessedImageField
from imagekit.processors import ResizeToFill
class Post(models.Model):
content = models.CharField(max_length=100)
# image = models.ImageField(blank=True)
image = ProcessedImageField(
upload_to='posts/images', # 저장위치
processors=[ResizeToFill(600,600)], # 크기 지정
format='JPEG', # 확장자 변경
options={'quality':90}, # 원본의 90퍼센트 품질로 저장
)
|
- 폼에 이미지를 업로드할 때 가려서 받는 방법 : accept 설정
1
2
| # form.html
<form action="" method="post" enctype="multipart/form-data" accept="image/*">
|
resize to fill ? resize to fit?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| # model.py
from django.db import models
from imagekit.models import ProcessedImageField
from imagekit.processors import ResizeToFill
class Post(models.Model):
content = models.CharField(max_length=100)
# image = models.ImageField(blank=True)
class Image(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE) # 1인 친구가 지워지면 n인친구까지 같이 지울 때 cascade
file = ProcessedImageField(
upload_to='posts/images', # 저장위치
processors=[ResizeToFill(600,600)], # 크기 지정
format='JPEG', # 확장자 변경
options={'quality':90}, # 원본의 90퍼센트 품질로 저장
)
|
1
2
3
4
5
6
7
| # form.py (모델폼 정의)
from .models import Post, Image ## 위에서 만든 이미지클래스 불러옴
class ImageForm(forms.ModelForm):
class Meta:
model = Image
fields = '__all__'
|
-
현재 postform과 imageform을 분리시켰기 때문에 imageform이 출력이 안되어 있음
-
1
2
3
4
5
6
7
| # views.py
from .forms import PostForm, ImageForm
# create로직에
## post_form과 image_form을 인스턴스화 시켜서 저장
post_form = PostForm()
image_form = ImageForm()
|
1
2
3
4
| # form.html
{% bootstrap_form post_form %}
{% bootstrap_form image_form %}
|
1
2
3
4
5
6
| # forms.py
class ImageForm(forms.ModelForm):
class Meta:
model = Image
fields = ['file',] # 여기를 수정
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # views.py
## create로직
def creat(request):
if(request.method == "POST"):
### 내용과 이미지를 각각 저장
post_form = PostForm(request.POST)
# 이미지폼에도 csrf토큰을 넣어주기위해 두개 다 필요
image_form = ImageForm(request.POST, request.FILES)
if(post_form.is_valid()):
post = post_form.save()
image = image_form.save(commit=False) # 저장하지말고 기다려
image.post = post # 저장된 게시물 post를 1:n관계로 설정한 post에 저장함
image.save()
|
1
2
3
4
5
6
7
8
9
10
| # forms.py
## 이미지 폼 수정
class ImageForm(forms.ModelForm):
class Meta:
model = Image
fields = ['file',]
#
widgets = {
'file' : forms.FileInput(attrs={'multiple':True}),
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| # views.py
def create(request):
if(request.method == "POST"):
post_form = PostForm(request.POST)
image_form = ImageForm(request.POST, request.FILES)
if(post_form.is_valid()):
post = post_form.save()
## 이부분 수정
for image in request.FILES.getlist('file'):
request.FILES['file'] = image
image_form = ImageForm(request.POST, request.FILES)
if(image_form.is_valid()):
image = image_form.save(commit=False)
image.post = post
image.save()
return redirect("posts:list")
else:
post_form = PostForm()
image_form = ImageForm()
return render(request, "posts/form.html", {"post_form":post_form, "image_form":image_form})
|
- 이미지 여러개 출력(Carousel사용)
- carousel의 active 설정은 1개여야 사진이 움직임
- id수정해야 여러개의 글이 입력 되어도 각각이 움직임
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
| # _post.html
<div class="card">
{% if post.image_set %}
<div id="post" class="carousel slide" data-ride="carousel">
<div class="carousel-inner">
{% for image in post.image_set.all %}
<div class="carousel-item {% if forloop.counter == 1 %} active {% endif %}">
<img src="" class="d-block w-100" alt="...">
</div>
{% endfor %}
</div>
<a class="carousel-control-prev" href="#post{{post.id}}" role="button" data-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="carousel-control-next" href="#post{{post.id}}" role="button" data-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
{% raw %}{% else %}
<img src="..." class="card-img-top" alt="...">
{% endif %}
<div class="card-body">
<p class="card-text"></p>
<a href="{% url 'posts:update' post.id %}" class="btn btn-warning">수정</a>
<a href="{% url 'posts:delete' post.id %}" class="btn btn-danger">삭제</a>
</div>
</div>
|
- update도 위에서 수정한 것 처럼 바꿔줘야 함
- 실제 인스타는 사진 수정이 x : 사실 사진 수정은 너무 어려움 ㅎㅎ…
- 기존에 있는 사진을 선택적으로 몇개를 삭제 / 변경해야 하기 때문에 일단은 제외
- 내용수정만 가능하게
1
2
3
4
5
6
7
8
9
10
11
12
| def update(request, id):
post = Post.objects.get(id=id)
if(request.method == "POST"):
post_form = PostForm(request.POST, instance=post)
if(post_form.is_valid()):
post_form.save()
return redirect("posts:list")
else:
# post를 인스턴스로
post_form = PostForm(instance=post)
return render(request, 'posts/form.html', {"post_form":post_form})
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # forms.py
{% extends "base.html" %}
{% load bootstrap4 %}
{% block body %}
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{% bootstrap_form post_form %}
{% if image_form %}
{% bootstrap_form image_form %}
{% endif %}
<input type="submit">
</form>
{% endblock %}
|