본문 바로가기
관리자

Programming-[Backend]/Django

Django로 Pinterest 따라 만들기-14. ProjectApp 만들기, MultipleObjectMixin

728x90
반응형

 

1. ProjectApp 스스로 만들어보기

 

여태까지 했던 내용을 바탕으로 스스로 ProjectApp을 만들어본다. 대상 및 요구사항은 아래와 같다.

 

대상: projectapp - article 들을 담을 수 있는 폴더 같은 개념이다. project:artilce = 1:N

요구사항:

 - Create, Detail, List View를 만든다.

 - Create 시 login이 필요하다.

 - Model의 fields = ['title', 'description', 'image', 'created_at']

 

위 사항들을 바탕으로 스스로 만들어본 페이지 사진

 



 

 

새로운 내용들

 

pagination option

 

기존에는 a link의 ? 앞에 {% url 'articleapp:list' %} 라는 문구가 있었는데, 이를 삭제했다. 이렇게 해서 list를 사용하는 페이지들 모두에서 pagination option을 공통으로 사용할 수 있게 된다.

<a href="?page={{ page_obj.number }}"
   class="btn btn-secondary rounded_pill active">
    {{ page_obj.number }}
</a>

 

truncatechars 옵션

프로젝트용 card를 표현하기 위해서 기존 snippets/card.html 외에 card_project.html을 추가하였다. 여기서 {{ }} 문법 내부의 | truncatechars 옵션을 보자. 이렇게 하면 project.title을 4글자까지 자르고, 나머지는 ...으로 표시해준다.(위 페이지 그림 참고)

<div style="text-align: center; display: block">
    <img src="{{ project.image.url }}" alt="">
    <div>
        {{ project.title | truncatechars:5 }}
    </div>
</div>

 

css의 object-fit 옵션

projectapp/list.html 에서 object-fit: cover 옵션을 사용했다. 이렇게 하면 .container가 정사각형이면 그에 맞게 사진을 정사각형으로 잘라서 배치해준다. 만약 이 옵션이 없는데 넣는 img가 정사각형이 아니라면 정사각형 .container 틀에 사진을 맞출려고 사진을 일그러뜨리게 된다.

.container img {
    width: 7rem;
    height: 7rem;
    border-radius: 1rem;
    object-fit: cover;
}

 

 


 

2. Project 페이지에 article List 넣기 : MultipleObjectMixin

 

이제 Project detail 페이지에 article list가 나오도록 한다.

 

 

Project : Article 연결

우선 1:N 관계로 연결해주기 위해서 연관관계의 주인인 Article의 model을 수정하고 migrate를 다시한다.

class Article(models.Model):
    writer = models.ForeignKey(User, on_delete=models.SET_NULL, related_name='article', null=True)
    project = models.ForeignKey(Project, on_delete=models.SET_NULL, related_name='article', null=True)
    
    ## 나머지 필드 생략

 

그리고 Article을 만들때, project 값도 넣을 수 있도록 ArticleCreationForm을 수정한다. (articleapp/create.html의 양식은 bootstrap의 {% form %}에 의해 자동 수정됨)

class ArticleCreationForm(ModelForm):
    class Meta:
        model = Article
        fields = ['title', 'image', 'project', 'content']

 

project의 dropdown 메뉴는 실제 project 이름이 안뜨는데, bootstrap을 수정해줘야할 것 같다. 어떻게 하는지 정확히 모르겠다...

 

 

 

 

MultipleObjectMixin 적용

 

이제 list를 만들기 위해서 MultipleObjectMixin을 적용한다. commentapp에서 했던 것처럼, article.comment.all로 모두 가져와도 되지만, 이렇게하면 아무런 옵션없이 무조건 다 가져오는게 돼버린다. 여러 옵션들을 제공하는 MultipleObjectMixin을 이용해서 list를 가져와보자.

 

projectapp/views.py:ProjectDetailView

MultipleObjectMixin을 상속받아서 paginate_by 옵션이 적용가능하게 되었다. 그리고 get_context_data 메서드를 불러와서 list로 사용할 객체를 Article 중에서 project가 detailView에서 가져오는 proejct object만 filtering 하도록 지정해주었다.

class ProjectDetailView(DetailView, MultipleObjectMixin):
    model = Project
    context_object_name = 'target_project'
    template_name = 'projectapp/detail.html'

    paginate_by = 5

    def get_context_data(self, **kwargs):
        object_list = Article.objects.filter(project=self.get_object())
        return super(ProjectDetailView, self).get_context_data(object_list=object_list, **kwargs)

 

 

projectapp에 적용

 

마지막으로 list를 적용한다. 위에서 정의한 object_list를 활용한다.

 

templates/snippets/list_fragment.html

공통으로 활용하기 위해서 list_fragment를 만든다. 이 코드는 articleapp/list.html의 파일을 그대로 복사해서 사용하며, 중복되는 extends, block content 구문만 삭제한다.

 

projectapp/detail.html의 일부

그리고 이 코드를 활용해서 projectapp/detail.html에 include ... with 구문으로 불러온다. list_fragment에서의 article_list가 view에서 detail.html로 전달되는 object_list가 되도록 하기 위해서 with 구문을 아래처럼 작성했다.

<hr>

    <div>
        {% include 'snippets/list_fragment.html' with article_list=object_list %}
    </div>

    </div>
{% endblock %}

 

 

accountapp에 적용

마지막으로 accountapp/AccountDetailView에서도 로그인한 사용자가 만든 article의 list가 조회될 수 있도록 MultipleObjectMixin을 적용해준다.

 

accountapp/AccountDetailView

class AccountDetailView(DetailView, MultipleObjectMixin):
    model = User
    context_object_name = 'target_user'
    template_name = 'accountapp/detail.html'

    paginate_by = 10

    def get_context_data(self, **kwargs):
        object_list = Article.objects.filter(writer=self.get_object())
        return super(AccountDetailView, self).get_context_data(object_list=object_list, **kwargs)

 

accountapp/detail.html 일부

 

<div>
        {% include 'snippets/list_fragment.html' with article_list=object_list %}
    </div>
    </div>
{% endblock %}

 

아래 article들이 왜 오른쪽으로 치우치는지는 잘 모르겠다.. 시간이 허용한다면 다음에 알아보자 ㅠ

 

 


 

 

참조

1. 작정하고 장고! Django로 Pinterest 따라만들기 : 바닥부터 배포까지-박형석님 인프런 강의

https://www.inflearn.com/course/%EC%9E%A5%EA%B3%A0-%ED%95%80%ED%84%B0%EB%A0%88%EC%8A%A4%ED%8A%B8/dashboard

728x90
반응형