해리의 데브로그

Django 23 - 이미지 다루기 2 (Carousel)

|

이미지 다루기 2 (인스타그램)

Django17 미디어 파일 관리 및 업로드 구현 포스팅에서 이미지(미디어)파일을 어떻게 업로드하여 관리하고, 재가공하는지에 대해 정리해보았다. 추가로, 하나의 게시글(Post)에 여러 사진을 올리고, 또한 그사진들을 횡으로 보여지도록, 마치 인스타그램 처럼 기능하게끔 내용을 확장시켜보도록 하자.

사진 슬라이드 넘기기(Carousel 적용)

_post.html

인스타그램처럼 여러장의 사진을 하나의 템플릿안에서 슬라이드 처럼 횡으로 넘길 수 있게 코드를 구현해보자. 이를 위해서 부트스트랩의 carousel을 적절히 활용하면 됨.

  • 첫번째 사진만 active 속성을 부여하기 위해 아래의 장고템플릿 사용
  • ` <div class="carousel-item {% if forloop.counter == 1 %} active {% endif %}">`
    • 반복문(forloop)의 횟수(counter)가 1일경우, 즉 첫번째 사진인 경우 active 속성이 적용됨.
  • 어떤 사진을 보여주고 있고, previous/Next 에 이전/다음 사진이 가는지에 대한 기준을 설정해줘야함. 이러한 부분을 id 속성에 적용시킴.
    • id는 중복되면 안되는 고유의 값이 들어가야하므로 post_id를 활용하여 고유값 부여
    • 이전/다음 사진으로 이동하는 기능을 하는 하단의 a 태그의 href에는 #를 꼭 붙여 줄 것.
 <a class="carousel-control-prev" href="#post_{{ post.id }}" 
  • id값에 {{ post_id }}만 입력할 경우(숫자만 들어간 경우)는 작동하지 않으므로 유의할 것.
<div class="card" style="width: 18rem;">
  <div class="card-header">
    <span> <a href="{% url 'accounts:people' post.user.username %}">
        {{ post.user.username }} </a></span>
  </div> 
  <div id="post_{{ post.id }}" 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="{{ image.file.url }}" class="card-img-top" 
             alt="{{ image.file.image }}">
      </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>

accounts/people.html

  • people 페이지에 들어갈 경우, 여러 사진 중, 가장 최근의 첫번째 사진만 뜨게 코드 작성
    • post.image_set.first.file.url 이용(.first)
<div class="container">
    <h1> {{ people.username }}</h1>
    <div class="row">
        {% for post in people.post_set.all %}
        <div class="col-4">
            <img src= "{{ post.image_set.first.file.url }}" class="img-fluid"/>
        </div>
        {% endfor %}
    </div>

Views.py - Update 함수 수정

ImageFormSet 관련 코드를 Create 함수에 넣어서 수정한 것과 마찬가지로, update 함수도 이미지폼셋 관련 코드를 추가로 삽입하고 다듬어보도록 하자.

  • Get 방식인 경우
    • ImageFormSet 을 불러온 후, instance에 부모클래스를 넣음.
    • 이후, 선언한 변수를 템플릿 변수로 넘김
  • Post 방식인 경우
    • 기본적인 CRUD의 Update와 동일한 방식으로 코드 구현
    • PostForm의 두번째 인자에 있던 request.FILESImageFormSet 의 인자로 이동되었으므로 삭제
    • 유효성 검증 후 DB에 저장
    • Update 로직 구현 시에는, 이미 post 가 생성되어있으므로 transaction 코드를 필요 없음.
@login_required
def update(request, post_id):
    post = get_object_or_404(Post, id=post_id)
    if post.user != request.user:
        return redirect('posts:list')
    
    if request.method == 'POST':
        post_form = PostForm(request.POST, instance=post)
        image_formset = ImageFormSet(request.POST, request.FILES, instance=post)
        if post_form.is_valid() and image_formset.is_valid():
            post_form.save()
            image_formset.save()
            return redirect('posts:list')
    else:
        post_form = PostForm(instance=post)
        image_formset = ImageFormSet(instance=post)
    return render(request, 'posts/form.html', {
                                                'post_form': post_form,
                                                'image_formset' : image_formset,
                                                })

Comments