0. 클래스형 뷰란?
Django의 views.py에서 함수형(def), 클래스형(class)를 모두 제공하고 있다.
클래스형 뷰의 장점은 아래와 같다.
- 이미 구현되어 있는 기능을 상속으로 받아와서 쓸 수 있다.
- 코드가 길어지거나 개발하는 웹 or 앱의 규모가 큰 경우 코드를 깔끔하게 볼 수 있다.
이때, Django에 이미 구현해서 제공하는 기능들을 제네릭 뷰라고 한다.
1. 프로젝트 시작하기
2. 모델만들기
데이터를 어떤 틀에 담아서 저장해놓고 쓸지 정의합니다.
저는 사이트의 이름과 그 사이트의 url 이 두 가지 정보를 담을 클래스를 정의하였습니다.
#app/models.py
from django.db import models
class Bookmark(models.Model):
site_name = models.CharField(max_length=100)
url = models.URLField('Site URL')
#객체의 이름은 아래와 같이 지어주겠다.
def __str__(self):
return "이름 : "+self.site_name+",주소 : "+self.url
$ python manage.py makemigrations
$ python manage.py migrate
관리자 페이지에서 볼 수 있도록 클래스를 등록해줍니다.
#app/admin.py
from django.contrib import admin
from .models import Bookmark
admin.site.register(Bookmark)
$ python manage.py createsuperuser
실행시켜서, 객체 하나를 만들어 주겠습니다. 게시판에 글 하나를 작성하시는 것과 같습니다.
$ python manage.py runserver
먼저, 주소창에 '/admin'을 붙여서 접속합니다.
createsuperuser로 만들었던 계정으로 로그인하면, 아래와 같은 화면을 볼 수 있습니다.
Bookmarks 옆의 [+Add]를 눌러서 아무 사이트 이름과 URL을 입력한 후 [SAVE]를 클릭합니다.
3. [클래스형 뷰] 화면 구성하기
Django에서 제공하는 ListView클래스를 상속받아 사용해보겠습니다.
#app/views.py
from django.views.generic.list import ListView
from .models import Bookmark
class BookmarkListView(ListView):
model = Bookmark
app폴더 내에 urls.py파일을 하나 생성하고, project의 urls.py와 이어주겠습니다.
#project/urls.py
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('bookmark/', include('classapp.urls')),
]
#app/urls.py
from django.urls import path
from .views import BookmarkListView
urlpatterns = [
path('', BookmarkListView.as_view(), name='list'),
]
이제, templates 즉 html을 만들어 주겠습니다. classproject에 templates폴더를 생성해주고, 만든 폴더 안에 base.html파일을 하나 생성합니다.
<!--project/templates/base.html-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<div class="container">
{% block content%}
{% endblock%}
</div>
</body>
</html>
https://getbootstrap.com/ 를 써서 보기 좋게 구성하려고 합니다. [Get started]를 눌러서 css와 js와 관련된 link를 연결해주겠습니다.
<!--project/templates/base.html-->
<!DOCTYPE html>
<html lang="en">
<head>
...
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
</head>
settings.py에서 templates의 기본 주소를 project내의 templates폴더로 변경되었음을 알려줍니다.
#settings.py
import os
TEMPLATES = [
{
#...
'DIRS': [os.path.join(BASE_DIR, "templates")],
#...
]
그 다음, app안에 templates폴더를 생성하고, 그 안에 classapp이름의 폴더를 생성해서 또 그 안에 bookmark_list.html 파일을 생성합니다.
https://getbootstrap.com/ 에서 table을 검색해서 코드 복붙하고 수정하였습니다.
<!--bookmark_list.html-->
{% extends 'base.html' %}
{% block title %}Bookmark List{% endblock %}
{% block content %}
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Site</th>
<th scope="col">URL</th>
<th scope="col">Modify</th>
<th scope="col">Delete</th>
</tr>
</thead>
<tbody>
{% for bookmark in object_list %}
<tr>
<td>{{forloop.counter}}</th>
<td>{{bookmark.site_name}}</td>
<td><a href="{{bookmark.url}}" target="_blank">{{bookmark.url}}</a></td>
<!-- target blank는 url을 눌렀을 때, 새창을 띄우겠다는 속성 -->
<td><a href="#" class="btn btn-success btn-sm">Modify</a></td>
<td><a href="#" class="btn btn-danger btn-sm">Delete</a></td>
</tr>
{%endfor%}
</tbody>
</table>
{% endblock%}
4. [클래스형 뷰] Create 구현
장고에서 제공하는 CreateView를 상속받아서 썼다.
#views.py
from django.views.generic.edit import CreateView
from django.urls import reverse_lazy
class BookmarkCreateView(CreateView):
model = Bookmark #데이터 틀은 Bookmark를 쓰겠다.
fields = ['site_name', 'url'] #이 두가지를 입력으로 받겠다. model에 정의한 이름으로
success_url = reverse_lazy('list') #성공하면 list화면을 띄우겠다. => url에 정의됨
template_name_suffix = '_create'
#사용할 template이름은 '모델명'+'_create'
app/templates/classapp 안에 bookmark_create.html파일을 생성하고 url로 연결해준다.
from .views import BookmarkCreateView
urlpatterns = [
#...
path('add/', BookmarkCreateView.as_view(), name='add'),
]
아래는 bookmark_create.html 파일 코드이다.
<!--bookmark_create.html-->
{% extends 'base.html' %}
{% block title %}Bookmark Add{% endblock %}
{% block content %}
<form action="" method="post">
{% csrf_token %}
{{form.as_p}}
<!-- form.as_p :클래스형 뷰의 옵션값임, 모델의 필드(site_name, URL)를 p태그로 감싸서 보여줌-->
<input type="submit" value="Add" class="btn btn-info btn-sm">
</form>
{% endblock%}
bookmark_list화면에서 [Add]버튼을 누르면 bookmark_create화면으로 넘어가도록 하자.
<!--bookmark_list.html-->
<a href="{% url 'add' %}" class="btn btn-info">Add Bookmark</a>
5. [클래스형 뷰] Detail 구현
장고의 generic view중 DetailView를 썼다.
#views.py
from django.views.generic.detail import DetailView
class BookmarkDetailView(DetailView):
model = Bookmark
url에 실행시킬 view를 연결시킨다.
#app/urls.py
from .views import *
urlpatterns = [
#...
path('detail/<int:pk>', BookmarkDetailView.as_view(), name='detail'),
]
app/templates/classapp/bookmark_detail.html을 생성한다.
DetailView가 html파일에 object로 객체를 넘겨주기 때문에, object.필드이름으로 출력하면 된다.
<!--bookmark_detail.html-->
{% extends 'base.html %}
{% block title %}Bookmark Detail{% endblock %}
{% block content %}
{{object.site_name}}
<br/>
{{object.url}}
<!-- generic view인 DetailView가 object라는 이름으로 객체를 전달한다. -->
{% endblock %}
site의 이름을 클릭했을 때 '자세히 보기' 페이지로 넘어가도록 한다.
<!--bookmark_list.html-->
<!--site이름을 클릭했을 때 detail을 보여준다.-->
<td><a href="{% url 'detail' pk=bookmark.id %}">{{bookmark.site_name}}</a></td>
6. [클래스형 뷰] Update 구현
장고의 generic view중 UpdateView를 썼다.
#views.py
from django.views.generic.edit import CreateView, UpdateView
class BookmarkUpdateView(UpdateView):
model = Bookmark
fields = ['site_name', 'url']
template_name_suffix = "_update"
#app/urls.py
urlpatterns = [
#...
path('update/<int:pk>', BookmarkUpdateView.as_view(), name='update'),
]
app/templates/classapp/bookmark_update.html을 생성한다.
<!--bookmark_update.html-->
{% extends 'base.html' %}
{% block title %}Bookmark Update{% endblock %}
{% block content %}
<form action="" method="post">
{% csrf_token %}
{{form.as_p}}
<input type="submit" value="Update" class="btn btn-info btn-sm">
</form>
{% endblock %}
list화면에서 [Modify]버튼을 눌렀을 때, bookmark_update 화면이 뜨도록 연결해주겠습니다.
<!--bookmark_list.html-->
<td><a href="{% url 'update' pk=bookmark.id %}" class="btn btn-success btn-sm">Modify</a></td>
update페이지에서 수정을 한 후 [Update]버튼을 누르면 에러가 납니다.
views.py에서 success_url을 안 알려줬기 때문인데, create할 때 해봤으니까 get_absolute_url이라는 걸 써보겠습니다.
get_absolute_url은 models.py에 쓰는 것이다.
#models.py
from django.urls import reverse
class Bookmark(models.Model):
#...
def get_absolute_url(self):
return reverse('detail', args=[str(self.id)])
#...
7. [클래스형 뷰] Delete 구현
장고의 generic view중 DeleteView를 썼다.
#views.py
from django.views.generic.edit import CreateView, UpdateView, DeleteView
class BookmarkDeleteView(DeleteView):
model = Bookmark
success_url = reverse_lazy('list')
#models.py
urlpatterns = [
#...
path('delete/<int:pk>', BookmarkDeleteView.as_view(), name='delete'),
]
app/templates/classapp/bookmark_confirm_delete.html을 생성한다.
https://getbootstrap.com/ 에서 alert을 검색해서 코드 복붙하고 수정하였습니다.
{% extends 'base.html' %}
{% block title %}Confirm Delete{% endblock %}
{% block content %}
<form action="" method="post">
{% csrf_token %}
<div class="alert alert-danger" role="alert">
다음의 "{{object}}"을 삭제하시겠습니까?
</div>
<!-- <div class="alert alert-danger">다음의 "{{object}}"을 삭제하시겠습니까?</div> -->
<input type="submit" value="Delete" class="btn btn-danger">
{% endblock %}
list화면에서 [Delete]버튼을 눌렀을 때, bookmark_delete 화면이 뜨도록 연결해주겠습니다.
<!--bookmark_list.html-->
<td><a href="{% url 'delete' pk=bookmark.id %}" class="btn btn-danger btn-sm">Delete</a></td>
8. 완성된 화면
'Programming > Django' 카테고리의 다른 글
클래스형 뷰를 사용한 CRUD(2)-Bootstrap을 이용한 pagination (0) | 2021.06.23 |
---|---|
Django 입력 받기 (0) | 2021.05.31 |
Django API 서버 만들기 (0) | 2021.04.13 |
REST API 서버 - 기본 세팅 (0) | 2021.04.11 |
로그인&로그아웃 (0) | 2020.08.26 |