컴굥일지

[Django Study 14] Projectapp Implementation 본문

프로그래밍 강의/Django

[Django Study 14] Projectapp Implementation

gyong 2022. 5. 13. 18:08
반응형

[ProjectApp 구현]

  1. Create / Detail / List View 를 구현한다.

    (Update / Delete는 구현하지 않는다.

  2. Success_url to related Project (프로젝트 만들면 이후 이어질 페이지 정하기)

  3. Login_required to CreateView (최소한 로그인은 해야 프로젝트를 할 수 있게 하자)

  4. Model : title / description / image / created_at

===========================================================
  1. python manage.py startapp projectapp

  2. settings.py에 projectapp 추가

  3. urls.py

     #projectapp/urls
     from django.urls import path
    
     from projectapp.views import ProjectListView, ProjectCreateView, ProjectDetailView
    
     app_name = 'projectapp'
    
     urlpatterns = [
         path('list/', ProjectListView.as_view(), name='list'),
    
         path('create/', ProjectCreateView.as_view(), name='create'),
         path('detail/<int:pk>', ProjectDetailView.as_view(), name='detail'),
     ]
  4. views.py

     #projectapp/views.py
    
     from django.contrib.auth.decorators import login_required
     from django.shortcuts import render
    
     # Create your views here.
     from django.urls import reverse
     from django.utils.decorators import method_decorator
     from django.views.generic import CreateView, DetailView, ListView
     from django.views.generic.list import MultipleObjectMixin
    
     from articleapp.models import Article
     from projectapp.forms import ProjectCreationForm
     from projectapp.models import Project
     from subscribeapp.models import Subscription
    
     @method_decorator(login_required, 'get')
     @method_decorator(login_required, 'post')
     class ProjectCreateView(CreateView):
         model = Project
         form_class = ProjectCreationForm
         template_name = 'projectapp/create.html'
    
         def get_success_url(self):
             return reverse('projectapp:detail', kwargs={'pk': self.object.pk})
    
     class ProjectDetailView(DetailView, MultipleObjectMixin):
         model = Project
         context_object_name = 'target_project'
         template_name = 'projectapp/detail.html'
    
         paginate_by = 25
    
         def get_context_data(self, **kwargs):
             project = self.object
             user = self.request.user
             if user.is_authenticated:
                 subscription = Subscription.objects.filter(user=user, project=project)
             else:
                 subscription = None
             object_list = Article.objects.filter(project=self.get_object())
             return super(ProjectDetailView, self).get_context_data(object_list=object_list,
                                                                    subscription=subscription,
                                                                    **kwargs)
    
     class ProjectListView(ListView):
         model = Project
         context_object_name = 'project_list'
         template_name = 'projectapp/list.html'
         paginate_by = 25
  5. models.py

     #projectapp/models.py
    
     from django.db import models
    
     # Create your models here.
    
     class Project(models.Model):
         image = models.ImageField(upload_to='project/', null=False)
         title = models.CharField(max_length=20, null=False)
         description = models.CharField(max_length=200, null=True)
    
         created_at = models.DateTimeField(auto_now=True)
    
         def __str__(self):
             return f'{self.pk} : {self.title}'
  6. forms.py

     from django.forms import ModelForm
    
     from projectapp.models import Project
    
     class ProjectCreationForm(ModelForm):
         class Meta :
             model = Project
             fields = {'image', 'title', 'description'}
  7. HTML 생성

    • create.html

        <!--projectapp/templates/create.html-->
      
        {% extends 'base.html' %}
        {% load bootstrap4 %}
      
        {% block content %}
      
          <div style="text-align: center; max-width: 500px; margin: 4rem auto">
            <div class="mb-4">
              <h4>Create Project</h4>
            </div>
            <form action="{% url 'projectapp:create' %}" method="post" enctype="multipart/form-data">
              {% csrf_token %}
              {% bootstrap_form form %}
              <input type="submit" class="btn btn-dark rounded-pill col-6 mt-3">
            </form>
          </div>
      
        {% endblock %}
    • detail.html

        {% extends 'base.html' %}
      
        {% block content %}
      
          <div>
            <div style="text-align: center; max-width: 500px; margin: 4rem auto 1.5rem auto;">
              <img src="{{ target_project.image.url }}" alt=""
                   style="height: 12rem; width: 12rem; border-radius: 20rem; margin-bottom: 2rem; object-fit: cover;">
              <h2 style="font-family: 'NanumSquareB'">
                {{ target_project.title }}
              </h2>
              <h5>
                {{ target_project.description }}
              </h5>
            </div>
      
            <div class="text-center mb-5">
              {% if user.is_authenticated %}
                {% if not subscription %}
                <a href="{% url 'subscribeapp:subscribe' %}?project_pk={{ target_project.pk }}"
                   class="btn btn-primary rounded-pill px-4">
                  Subscribe
                </a>
                {% else %}
                <a href="{% url 'subscribeapp:subscribe' %}?project_pk={{ target_project.pk }}"
                   class="btn btn-dark rounded-pill px-4">
                  Unsubscribe
                </a>
                {% endif %}
              {% endif %}
            </div>
      
            <div>
              {% include 'snippets/list_fragment.html' with article_list=object_list %}
            </div>
      
          </div>
      
        {% endblock %}
    • list.html

        {% extends 'base.html' %}
        {% load static %}
      
        {% block content %}
      
        <style>
      
            .container {
                padding: 0;
                margin: 0, auto;
            }
      
            .container div {
              display: flex;
              justify-content: center;
              align-items: center;
      
              border-radius: 1rem;
            }
      
            .container img {
              width: 7rem;
              height: 7rem;
              object-fit: cover;
              border-radius: 1rem;
            }
      
        </style>
            {% if project_list %}
            <div class="container">
                {% for project in project_list %}
                <a href="{% url 'projectapp:detail' pk=project.pk %}">
                    {% include 'snippets/card_project.html' with project=project %}
                </a>
                {% endfor %}
            </div>
            <script src="{% static 'js/magicgrid.js' %}"></script>
            {% else %}
            <div class="text-center">
                <h1>No Projects YET!</h1>
            </div>
            {% endif %}
      
            {% include 'snippets/pagination.html' with page_obj=page_obj %}
      
            <div style="text-align: center">
                <a href="{% url 'projectapp:create' %}" class="btn btn-dark rounded-pill mt-3 mb-3 px-3">
                    Create Project
                </a>
            </div>
      
        {% endblock %}

[MultipleObjectMixin을 통한 ProjectApp 마무리]

project와 article을 연결해주는 작업을 해 줄 것이다

  • articleapp의 models.py에서 아래 코드 추가한 후
project = models.ForeignKey(Project, on_delete=models.SET_NULL, related_name='article', null=True)

views.py로 가서 project를 추가해준다

  • terminal에 ‘python manage.py makemigration’ 작성
  • projectapp의 views.py로 가서 detailview에서 MultipleObjectionMaxin 추가한 후 아래 코드도 추가
paginate_by = 25

def get_context_data(self, **kwargs):
    object_list = Article.objects.filter(project=self.get_object())
    return super(ProjectDetailView, self).get_context_date(object_list=object_list, **kwargs)
  • 앱에 종속되어 있지 않는 template에 list_pragment 파일을 생성한 후 아래 코드 작성 (articleapp의 list.html 복사해와서 내용 고치는 정도)
{% load static %}

  <style>
    .container {
      padding : 0;
      margin: 0, auto;
      }

    .container a{
      width: 45%;
      max-width: 250px;
      }

    .container div {
      display: flex;
      justify-content: center;
      align-items: center;
      border-radius: 1rem;
    }

    .container img{
      width: 100%;
      border-radius: 1rem;
    }
  </style>

  {% if article_list %}
  <div class="container">
    {% for article in article_list %}
    <a href="{% url 'articleapp:detail' pk=article.pk}">
      {% include 'snippets/card.html' with article=article %}
    </a>
  </div>
  <script src="(% static 'js/magicgird.js" %}></script>
  <% else %>
  <div class="text-center">
    <h1>No Articles YET!</h1>
  </div>
  {% endif %}

  {% include 'snippets/pagination.html' with page_obj=page_obj %}

  <div style="text-align center">
    <a href="{% url 'articleapp:create' %}" clss="btn btn-dark rounded-pull col-3 mt-3 mb-3 px-2">
      Create Article
    </a>
  </div>
  • 그리고 projectapp의 detail.html로 가서 아래 코드 추가
<div>

    {% include 'scrippts/list_pragment.html' with article_list=object_list %}

</div>

위 과정을 account app 파일에서 똑같이 적용해준다



[출처] 작정하고 장고! Django Pinterest 따라만들기 : 바닥부터 배포까지

섹션 8. Projectapp Implementation (40강 ~ 41강)

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

반응형
Comments