projectapp은 article이 그룹화 되어 나타나는 형태이다.
지금까지 진행했던 것과 마찬가지로 python manage.py startapp projectapp을 실시한다.
settings, urls, projectapp/urls, projectapp/models를 먼저 세팅해주고 migration까지 실시한다.
<settings.py>
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'accountapp',
'bootstrap4',
'profileapp',
'articleapp',
'projectapp',
]
<urls.py>
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('accountapp.urls')),
path('profiles/', include('profileapp.urls')),
path('articles/', include('articleapp.urls')),
path('projects/', include('projectapp.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
<projectapp/urls 생성>
from django.urls import path
from projectapp.views import ProjectCreateView, ProjectDetailView, ProjectListView
app_name = 'projectapp'
urlpatterns = [
]
<projectapp/models.py>
class Project(models.Model):
image = models.ImageField(upload_to='project/', null=True)
title = models.CharField(max_length=100, null=True)
description = models.CharField(max_length=200, null=True)
created_at = models.DateField(auto_now_add=True, null=True)
기본적인 세팅이 끝났으면 본격적으로 개발을 시작한다. projectapp의 경우 한번 생성하면 함부로 수정하거나 지울수 없다. 따라서 Create, Detail, ListView만 생성한다.
urlpatterns = [
path('create/', ProjectCreateView.as_view(), name='create'),
path('detail/<int:pk>', ProjectDetailView.as_view(), name='detail'),
path('list/', ProjectListView.as_view(), name='list')
]
<CreatView>
article의 createview와 동일하게 진행한다.
<views.py>
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})
<forms.py>
class ProjectCreationForm(ModelForm):
class Meta:
model = Project
fields = ['image', 'title', 'description']
<결과화면>
<DetailView>
<views.py>
class ProjectDetailView(DetailView):
model = Project
context_object_name = 'target_project'
template_name = 'projectapp/detail.html'
<결과화면>
<ListView>
listview의 경우 html을 만들어 주는데 해당 html은 article/list.html과 동일하고 context_object_name이 project_list 이므로 파일 내의 내용을 변경해 준다.
class ProjectListView(ListView):
model = Project
context_object_name = 'project_list'
template_name = "projectapp/list.html"
paginate_by = 5
{% extends 'base.html' %}
{% load static %}
{% block content %}
<style>
.container div {
width: 10rem;
height: 10rem;
border-radius: 1rem;
}
.container img {
width: 100%;
height: 100%;
}
</style>
<!DOCTYPE html>
{% if project_list %} # project_list를 순회
<div class="container">
{% for project in project_list %}
<div> # 해당 프로젝트에서 뽑을 내용들
<a href="{% url 'projectapp:detail' pk=project.pk %}">
<img src="{{ project.image.url }}" alt="" style="width: 100%; height: 100%; border-radius:1rem;">
</a>
<p class="text-center">
{{ project.title }}
</p>
</div>
{% endfor %}
<script src="{% static 'js/magicgrid.js' %}"></script>
</div>
{% else %}
<h3>Project Not Yet</h3>
{% endif %}
<!-- pagination -->
{% include 'snippets/pagination.html' %}
{% if user.is_authenticated %}
<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>
{% endif %}
{% endblock %}
<결과>
header.html의 navigation button을 Projects로 변경해주고 list로 향하는 url을 걸어주면 해당 페이지가 나타난다.
이제 project/detail.html 밑에 해당 project에 속해있는 article들이 나타나야 한다(1: N관계가 된다). 따라서 project를 부모로 갖도록 Article모델을 수정해준다. 모델을 수정했기 때문에 form도 수정해 주고, 이후 ProjectDetailView에 MultipleObjectMixin을 추가로 사용해 줌으로써 이 문제를 해결한다.
<articleapp/models.py수정>
class Article(models.Model):
writer = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='article')
project = models.ForeignKey(Project, on_delete=models.SET_NULL, null=True, related_name='article') #추가!
title = models.CharField(max_length=200, null=True)
image = models.ImageField(upload_to='article/', null=False)
content = models.TextField(null=True)
created_at = models.DateField(auto_now_add=True, null=True)
<articleapp/forms.py 수정>
추가 후 makemigrations과 migrate를 실시한다.
from django.forms import ModelForm
from articleapp.models import Article
class ArticleCreationForm(ModelForm):
project = forms.ModelChoiceField(queryset=Project.objects.all()) # 아무것도 선택하지 않아도 되게 설정
class Meta:
model = Article
fields = ['image', 'title', 'project', 'content'] #추가!
이후 article을 create하러 들어가보면 프로젝트를 선택할 수 있는 란이 설정되어 있다. 현재는 객체명으로 써져있기 때문에 이를 수정해주도록 하겠다.
<projectapp/models.py 내용추가>
from django.contrib.auth.models import User
from django.db import models
# Create your models here.
class Project(models.Model):
image = models.ImageField(upload_to='project/', null=True)
title = models.CharField(max_length=100, null=True)
description = models.CharField(max_length=200, null=True)
created_at = models.DateField(auto_now_add=True, null=True)
# 이내용 추가
def __str__(self):
return f"{self.pk}: {self.title}"
원하는대로 잘 출력되는것을 확인할 수 있다.
그럼 이제 들어가게 projectapp/detail에 해당 article이 보여지게 해야한다. 위에서 간략하게 설명한대로 진행한다.
<projectapp/views.py>
class ProjectDetailView(DetailView, MultipleObjectMixin): #mixin추가
model = Project
context_object_name = 'target_project'
template_name = 'projectapp/detail.html'
paginate_by = 20 #추가
def get_context_data(self, **kwargs): #추가
object_list = Article.objects.filter(project=self.get_object())
return super().get_context_data(object_list=object_list)
<projectapp/detail.py>
{% extends 'base.html' %}
{% block content %}
<div class="account_create">
<div>
<p>{{ target_project.title }}</p>
<p>{{ target_project.description }}</p>
</div>
<div>
<img src="{{ target_project.image.url }}" alt="" style="width: 10rem; height: 10rem; border-radius: 20rem; margin-bottom: 2rem;">
</div>
</div>
<div>
{% include 'snippets/list_fragment.html' with article_list=object_list %}
</div>
{% endblock %}
<결과>
'FrameWork > pinterest clone' 카테고리의 다른 글
12. 마무리 (0) | 2023.07.25 |
---|---|
11. Subscriptionapp 만들기 (0) | 2023.07.25 |
9. articleapp만들기 (0) | 2023.07.22 |
8. profileapp 만들기 (0) | 2023.07.22 |
7. accountapp 만들기 (0) | 2023.07.20 |