hyeonga_code

파이선 웹구축_장고_26_페이징 기능까지 구현 본문

Python_Django

파이선 웹구축_장고_26_페이징 기능까지 구현

hyeonga 2023. 6. 18. 05:59
반응형

- 페이징 기법까지 적용한 전체 코드

1. <config> > 'settings.py'

'settings.py'

=====

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
SECRET_KEY = 'django-insecure-a)ms^w63$yve_^r#lob$#)ut6#q#@gqz%-cwljv&c9i_$p$h)o'
DEBUG = True
ALLOWED_HOSTS = []
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'acc.apps.AccConfig',
    'board.apps.BoardConfig',
    'mathfilters'
]
AUTH_USER_MODEL = "acc.User"
MEDIA_URL = "/media/"
MEDIA_ROOT = BASE_DIR/'media'
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'config.urls'
TEMPLATES = [
    {
        'BACKEND''django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR/'templates'],
        'APP_DIRS'True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
WSGI_APPLICATION = 'config.wsgi.application'
DATABASES = {
    'default': {
        'ENGINE''django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}
AUTH_PASSWORD_VALIDATORS = [
    {'NAME''django.contrib.auth.password_validation.UserAttributeSimilarityValidator',},
    {'NAME''django.contrib.auth.password_validation.MinimumLengthValidator', },
    {'NAME''django.contrib.auth.password_validation.CommonPasswordValidator', },
    {'NAME''django.contrib.auth.password_validation.NumericPasswordValidator',},
]
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'Asia/Seoul'
USE_I18N = True
USE_TZ = False
STATIC_URL = 'static/'
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
cs

 

2. <config> > 'urls.py'

=====

1
2
3
4
5
6
7
8
9
10
11
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
from . import settings
 
urlpatterns = [
    path('admin/', admin.site.urls),
    path('acc/', include('acc.urls')),
    path('board/', include('board.urls')),
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
 
cs

 

3. <acc> 앱 생성 > 'models.py'

'models.py'

=====

1
2
3
4
5
6
7
8
9
10
11
12
from django.db import models
from django.contrib.auth.models import AbstractUser
 
class User(AbstractUser):
    pic = models.ImageField(upload_to="usr/%y/%m")
    comment = models.TextField()
    age = models.IntegerField(default=0)
 
    def getpic(self):
        if self.pic:
            return self.pic.url
        return "/media/noimage.png"
cs

4. <acc> > 'admin.py'

'admin.py'

=====

1
2
3
from django.contrib import admin
from .models import User
admin.site.register(User)
cs

5. <acc> > 'urls.py'

'urls.py'

=====

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from django.urls import path
from . import views
 
app_name = "acc"
urlpatterns = [
    path('index/', views.index, name="index"),
    path('login/', views.ulogin, name="login"),
    path('logout/', views.ulogout, name="logout"),
    path('profile/', views.profile, name="profile"),
    path('delete/', views.delete, name="delete"),
    path('signup/', views.signup, name="signup"),
    path('update/', views.update, name="update"),
    path('chpass/', views.chpass, name="chpass")
]
cs

6. <acc> > 'views.py'

'views.py'

=====

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.hashers import check_password
from .models import User
 
def update(request):
    if request.method == "POST":
        u = request.user
        uc = request.POST.get("ucomm")
        um = request.POST.get("umail")
        pi = request.FILES.get("upic")
        u.email , u.comment = um, uc
        if pi:
            u.pic.delete()
            u.pic = pi
        u.save()
        return redirect("acc:profile")
    return render(request, "acc/update.html")
 
def chpass(request):
    u = request.user
    cp = request.POST.get("cpass")
    if check_password(cp, u.password):
        np = request.POST.get("npass")
        u.set_password(np)
        u.save()
        return redirect("acc:login")
    return redirect("acc:update")
 
def signup(request):
    if request.method == "POST":
        un = request.POST.get("uname")
        up = request.POST.get("upass")
        ua = request.POST.get("uage")
        uc = request.POST.get("ucomm")
        pi = request.FILES.get("upic")
        try:
            User.objects.create_user(username=un, password=up, age=ua, comment=uc, pic=pi)
            return redirect("acc:login")
        except:
            pass # 메세지
    return render(request, "acc/signup.html")
 
def delete(request):
    u = request.user
    up = request.POST.get("upass")
    if check_password(up, u.password):
        u.pic.delete()
        u.delete()
        return redirect("acc:index")
    else:
        pass # 메세지
    return redirect("acc:profile")
    
 
def profile(request):
    return render(request, "acc/profile.html")
 
def ulogout(request):
    logout(request)
    return redirect("acc:index")
 
def index(request):
    return render(request, "acc/index.html")
 
def ulogin(request):
 
    if request.user.is_authenticated:
        return redirect("acc:index")
 
    if request.method == "POST":
        un = request.POST.get("uname")
        up = request.POST.get("upass")
        u = authenticate(username=un, password=up)
        if u:
            login(request, u)
            return redirect("acc:index")
        else:
            pass # 메세지
    return render(request, "acc/login.html")
cs

 

 

- 페이징 기법까지 적용한 전체 코드

7. <board> 앱 생성 > 'models.py'

'models.py'

=====

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from django.db import models
from acc.models import User
from django.utils import timezone
 
class Board(models.Model):
    subject = models.CharField(max_length=100)
    writer = models.ForeignKey(User, on_delete=models.CASCADE, related_name="writer")
    content = models.TextField()
    pubdate = models.DateTimeField(default=timezone.now)
    likey = models.ManyToManyField(User, blank=True, related_name="likey")
 
    def __str__(self):
        return self.subject
 
class Reply(models.Model):
    board = models.ForeignKey(Board, on_delete=models.CASCADE)
    replyer = models.ForeignKey(User, on_delete=models.CASCADE)
    comment = models.TextField()
 
    def __str__(self):
        return f"{self.board}_{self.replyer}"
cs

8. <board> > 'admin.py'

'admin.py'

=====

1
2
3
4
from django.contrib import admin
from .models import Board, Reply
admin.site.register(Board)
admin.site.register(Reply)
cs

9. <board> > 'urls.py'

'urls.py'

=====

1
2
3
4
5
6
7
8
9
10
11
from django.urls import path
from . import views
 
app_name = "board"
urlpatterns = [
    path('index/', views.index, name="index"),
    path('detail/<bpk>', views.detail, name="detail"),
    path('delete/<bpk>', views.delete, name="delete"),
    path('create/', views.create, name="create"),
    path('update/<bpk>', views.update, name="update")
]
cs

10. <board> > 'views.py'

'views.py'

=====

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
from django.shortcuts import render, redirect
from .models import Board
from django.core.paginator import Paginator
 
def index(request):
    pg = request.GET.get("page"1)
    cate = request.GET.get("cate""")
    kw = request.GET.get("kw""")
 
    if kw:
        if cate == "sub":
            b = Board.objects.filter(subject__startswith=kw)
        elif cate == "wri":
            try:
                from acc.models import User
                u = User.objects.get(username=kw)
                b = Board.objects.filter(writer=u)
            except:
                b = Board.objects.none()
 
        elif cate == "con":
            b = Board.objects.filter(content__contains=kw)
    else:
        b = Board.objects.all()
 
    b = b.order_by("-pubdate")
    pag = Paginator(b, 3)
    obj = pag.get_page(pg)
    context = {
        "bset" : obj,
        "kw" : kw,
        "cate" : cate
    }
    return render(request, "board/index.html", context)
 
 
def update(request, bpk):
    b = Board.objects.get(id=bpk)
    if request.user != b.writer:
        return redirect("board:index")
        
    if request.method == "POST":
        s = request.POST.get("sub")
        c = request.POST.get("con")
        b.subject, b.content = s,c
        b.save()
        return redirect("board:detail", bpk)
        
    context = {
        "b" :b
    }
    return render(request, "board/update.html", context)
 
def create(request):
    if request.method == "POST":
        s = request.POST.get("sub")
        c = request.POST.get("con")
        Board(subject=s, writer=request.user, content=c).save()
        return redirect("board:index")
    return render(request, "board/create.html")
 
def delete(request, bpk):
    b = Board.objects.get(id=bpk)
    if request.user == b.writer:
        b.delete()
    else:
        pass # 메세지 (불법적인 접근)
    return redirect("board:index")
 
def detail(request, bpk):
    b = Board.objects.get(id=bpk)
    context = {
        "b" : b
    }
    return render(request, "board/detail.html", context)
cs

- 페이징 기법까지 적용한 전체 코드

11. <templates> > 'base.html'

'base.html'

=====

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Bootstrap demo</title>
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
    </head>
    <body>
        {% if user.is_authenticated %}
        <!-- 인증된 사용자 메뉴바 -->
            <nav class="navbar navbar-expand-lg navbar-dark" style="background-color: rgb(0, 0, 0);">
                <div class="container-fluid">
                    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                        <span class="navbar-toggler-icon"></span>
                    </button>
                    <div class="collapse navbar-collapse" id="navbarSupportedContent">
                        <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                            <li class="nav-item">
                                <a class="nav-link active" aria-current="page" href="{% url 'acc:index' %}">HOME</a>
                            </li>
                            <li class="nav-item">
                                <a class="nav-link active" aria-current="page" href="{% url 'board:index' %}">BOARD</a>
                            </li>
                            <li class="nav-item dropdown">
                                <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
                                    {{ user }}
                                </a>
                                <ul class="dropdown-menu">
                                    <li><a class="dropdown-item" href="{% url 'acc:profile' %}">PROFILE</a></li>
                                    <li><hr class="dropdown-divider"></li>
                                    <li><a class="dropdown-item" href="{% url 'acc:logout' %}">LOGOUT</a></li>
                                </ul>
                            </li>
                        </ul>
                    </div>
                </div>
            </nav>
        {% else %}
        <!-- 익명의 사용자 메뉴바 -->
            <nav class="navbar navbar-expand-lg navbar-dark" style="background-color: rgb(0, 0, 0);">
                <div class="container-fluid">
                    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                        <span class="navbar-toggler-icon"></span>
                    </button>
                    <div class="collapse navbar-collapse" id="navbarSupportedContent">
                        <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                            <li class="nav-item">
                                <a class="nav-link active" aria-current="page" href="{% url 'acc:index' %}">HOME</a>
                            </li>
                            <li class="nav-item">
                                <a class="nav-link active" aria-current="page" href="{% url 'acc:login' %}">LOGIN</a>
                            </li>
                            <li class="nav-item">
                                <a class="nav-link active" aria-current="page" href="{% url 'acc:signup' %}">SIGNUP</a>
                            </li>
                        </ul>
                    </div>
                </div>
            </nav>
        {% endif %}
        <div class="container mt-5 mb-5">
            {% block con %}
            {% endblock %}
        </div>
        <style>
            .nav-item{
                font-size: 20px;
                font-weight: bold;
                margin-left: 10px;
            }
            .form-control{
                font-weight: bold;
                font-size: 20px;
            }
            .form-label{
                font-weight: bold;
                font-size: 20px;
            }
        </style>
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
    </body>
</html>
cs

12. <acc> > 'index.html'

'index.html'

=====

1
2
3
4
5
6
7
8
9
{% extends 'base.html' %}
{% block con %}
    <div class="p-5 mb-4 bg-light rounded-3">
        <div class="container-fluid py-5">
            <h1 class="display-5 fw-bold">WELCOME TO MY WEBSITE!</h1>
            <p class="col-md-8 fs-4">Hello everyone! My first django project 💥 </p>
        </div>
    </div>
{% endblock %}
cs

13. <acc> > 'login.html'

'login.html'

=====

1
2
3
4
5
6
7
8
9
10
11
12
{% extends 'base.html' %}
{% block con %}
    <h1><b>LOGIN PAGE</b></h1>
    <form method="post">
        {% csrf_token %}
        <input type="text" name="uname" class="form-control mt-5" placeholder="INPUT USERNAME">
        <input type="password" name="upass" class="form-control mt-3" placeholder="INPUT PASSWORD">
        <div class="text-end mt-4">
            <button class="btn btn-dark btn-lg">LOGIN</button>
        </div>
    </form>
{% endblock %}
cs

14. <acc> > 'profile.html'

'profile.html'

=====

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
{% extends 'base.html' %}
{% block con %}
    <div class="container mt-5 mb-5">
        <h1><b>{{ user }}'s PROFILE</b></h1>
        <div class="row">
            <div class="col-sm-7 text-center" style="margin: auto;">
                <img src="{{ user.getpic }}" class="rounded-circle" width="80%">
            </div>
            <div class="col-sm-5">
 
                <label class="form-label mt-5">USERNAME</label>
                <input type="text" value="{{user}}" disabled class="form-control">
        
                <label class="form-label mt-4">AGE</label>
                <input type="text" value="{{user.age}}" disabled class="form-control">
        
                <label class="form-label mt-4">EMAIL</label>
                <input type="text" value="{{user.email}}" disabled class="form-control">
 
                <label class="form-label mt-4">COMMENT</label>
                <textarea class="form-control" style="height:150px" disabled>{{ user.comment }}</textarea>
            </div>
        </div>
        <div class="mt-5 text-end">
            <a href="{% url 'acc:update' %}" class="btn btn-dark btn-lg">정보수정</a>
            <!-- modal trigger button -->
            <button type="button" class="btn btn-danger btn-lg" data-bs-toggle="modal" data-bs-target="#exampleModal">계정삭제</button>
        </div>
    </div>
 
    <!-- Modal -->
    <form method="post" action="{% url 'acc:delete' %}">
        {% csrf_token %}
        <div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <h1 class="modal-title fs-5" id="exampleModalLabel">계정 삭제 알림창</h1>
                        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                    </div>
                    <div class="modal-body">
                        <label class="form-label">패스워드 확인</label>
                        <input type="password" name="upass" class="form-control">
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">닫기</button>
                        <button class="btn btn-danger">삭제</button>
                    </div>
                </div>
            </div>
        </div>
    </form>
{% endblock %}
cs

15. <acc> > 'signup.html'

'signup.html'

=====

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
{% extends 'base.html' %}
{% block con %}
    <h1><b>SIGNUP PAGE</b></h1>
    <form method="post" enctype="multipart/form-data" name="createForm">
        {% csrf_token %}
        <label class="form-label mt-5">USERNAME</label>
        <input type="text" name="uname" class="form-control">
 
        <label class="form-label mt-4">PASSWORD</label>
        <input type="password" name="upass" class="form-control">
 
        <label class="form-label mt-4">CHECK PASSWORD</label>
        <input type="password" name="ckpass" class="form-control">
 
        <label class="form-label mt-4">AGE</label>
        <input type="number" value="0" name="uage" class="form-control">
 
        <label class="form-label mt-4">USERPIC</label>
        <input type="file" name="upic" class="form-control">
 
        <label class="form-label mt-4">COMMENT</label>
        <textarea class="form-control" name="ucomm"></textarea> 
 
        <div class="text-end mt-4">
            <button type="button" onclick="check()" class="btn btn-dark btn-lg">회원가입</button>
        </div>
    </form>
 
    <script>
        function check(){
            cf = document.createForm;
            if(!cf.uname.value){
                alert("USERNAME 은 필수입력 사항입니다!");
            }else if(!cf.upass.value){
                alert("PASSWORD 는 필수입력 사항입니다!");
            }else if(cf.upass.value != cf.ckpass.value){
                alert("PASSWORD 가 서로 일치하지 않습니다 :(");
            }else{ cf.submit(); }
        }
    </script>
{% endblock %}
cs

16. <acc> > 'update.html'

'update.html'

=====

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
{% extends 'base.html' %}
{% block con %}
    <h1><b>UPDATE PAGE</b></h1>
    <form method="post" enctype="multipart/form-data">
        {% csrf_token %}
        <!-- username 은 변경불가하도록 disabled 유지 -->
        <label class="form-label mt-5">USERNAME</label>
        <input type="text" disabled value="{{user}}" class="form-control">
 
        <label class="form-label mt-4">EMAIL</label>
        <input type="text" value="{{user.email}}" name="umail" class="form-control">
 
        <label class="form-label mt-4">USERPIC</label>
        <input type="file" class="form-control" name="upic">
 
        <label class="form-label mt-4">COMMENT</label>
        <textarea class="form-control" name="ucomm">{{ user.comment }}</textarea> 
 
        <div class="text-end mt-4">
            <!-- Button trigger modal -->
            <button type="button" class="btn btn-primary btn-lg" data-bs-toggle="modal" data-bs-target="#exampleModal">패스워드변경</button>
            <button class="btn btn-dark btn-lg">수정완료</button>
        </div>
    </form>
 
    <!-- Modal -->
    <form method="post" action="{% url 'acc:chpass' %}">
        {% csrf_token %}
        <div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <h1 class="modal-title fs-5" id="exampleModalLabel"><b>패스워드 변경창</b></h1>
                        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                    </div>
                    <div class="modal-body">
                        <input type="password" name="cpass" placeholder="CURRENT PASSWORD" class="form-control">
                        <input type="password" name="npass" placeholder="NEW PASSWORD" class="form-control mt-3">
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">닫기</button>
                        <button class="btn btn-primary">변경</button>
                    </div>
                </div>
            </div>
        </div>
    </form>
{% endblock %}
cs

- 페이징 기법까지 적용한 전체 코드

17. <board> > 'index.html'

'index.html'

=====

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
{% extends 'base.html' %}
{% block con %}
    <!-- board/index.html -->
 
    {% load mathfilters %}
    <h1><b>게시판</b></h1>
        
    <div class="text-end">
        <a href="{% url 'board:create' %}" class="btn btn-dark">게시글생성</a>
    </div>
 
    <table class="table table-hover mt-4">
        <thead>
            <tr class="table-dark">
                <th scope="col">NO</th>
                <th scope="col">SUBJECT</th>
                <th scope="col">SUMMARY</th>
                <th scope="col">WRITER</th>
                <th scope="col">LIKEY</th>from django.urls import path
            </tr>
        </thead>
        <tbody>
            {% for i in bset %}
            <tr>
                <th scope="row">{{ bset.start_index|add:forloop.counter0 }}</th>
                <td><a class="sub" href="{% url 'board:detail' i.id %}">{{ i.subject }}</a></td>
                <td>{{ i.content|truncatewords:10 }}</td>
                <td>{{ i.writer }}</td>
                <td>0</td>
            </tr>
            {% empty %}
                <tr>
                    {% if kw %}
                        <th>검색 결과가 존재하지 않습니다 😉</th>
                    {% else %}
                        <th>첫 번째 게시글을 작성해주세요 🤣</th>
                    {% endif %}
                </tr>
            {% endfor %}
        </tbody>
    </table>
 
 
    <nav aria-label="Page navigation example" class="mt-3">
        <ul class="pagination justify-content-center">
 
            {% if bset.has_previous %}
                <li class="page-item"><a class="page-link" href="{% url 'board:index' %}?page=1&cate={{cate}}&kw={{kw}}">HOME</a></li>
                <li class="page-item"><a class="page-link" href="{% url 'board:index' %}?page={{bset.previous_page_number}}&cate={{cate}}&kw={{kw}}">PRE</a></li>
            {% else %}
                <li class="page-item disabled"><a class="page-link">HOME</a></li>
                <li class="page-item disabled"><a class="page-link">PRE</a></li>
            {% endif %}
            
            {% for i in bset.paginator.page_range %}
                {% if bset.number|add:3 >= i and i >= bset.number|sub:3 %}
                    <li class="page-item {% if bset.number == i %} active {% endif %}"><a class="page-link" href="{% url 'board:index' %}?page={{i}}&cate={{cate}}&kw={{kw}}">{{i}}</a></li>
                {% endif %}
            {% endfor %}
 
            {% if bset.has_next %}
                <li class="page-item"><a class="page-link" href="{% url 'board:index' %}?page={{bset.next_page_number}}&cate={{cate}}&kw={{kw}}">NEXT</a></li>
                <li class="page-item"><a class="page-link" href="{% url 'board:index' %}?page={{bset.paginator.num_pages}}&cate={{cate}}&kw={{kw}}">FIN</a></li>
            {% else %}
                <li class="page-item disabled"><a class="page-link">NEXT</a></li>
                <li class="page-item disabled"><a class="page-link">FIN</a></li>
            {% endif %}
        </ul>
    </nav>
 
    <form>
        <div class="row mt-5">
            <div class="col-sm-2">
                <select class="form-select" name="cate">
                    <option value="sub" {% if cate == "sub" %} selected {% endif %}>제목</option>
                    <option value="wri" {% if cate == "wri" %} selected {% endif %}>작성자</option>
                    <option value="con" {% if cate == "con" %} selected {% endif %}>내용</option>
                </select>
            </div>
            <div class="col-sm-6">
                <input type="text" name="kw" value="{{kw}}" class="form-control">
            </div>
            <div class="col-sm-2">
                <button class="btn btn-secondary" style="width:100%">검색</button>
            </div>
            <div class="col-sm-2">
                <a href="{% url 'board:index' %}"><button class="btn btn-dark" type="button" style="width:100%">초기화</button></a>
            </div>
        </div>
    </form>
{% endblock %}
cs

18. <board> > 'create.html'

'create.html'

=====

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{% extends 'base.html' %}
{% block con %}
    <h1><b>게시글 작성</b></h1>
    <form method="post">
        {% csrf_token %}
        <div class="mb-3 mt-5">
            <label class="form-label"><b>SUBJECT</b></label>
            <input type="text" name="sub" class="form-control">
        </div>
        <div class="mb-3">
            <label class="form-label"><b>WRITER</b></label>
            <input type="text" class="form-control" value="{{ user }}" disabled>
        </div>
        <div class="mb-3">
            <label class="form-label"><b>CONTENT</b></label>
            <textarea class="form-control" name="con" style="height: 150px;"></textarea>
        </div>
        <div class="text-end mt-3">
            <button class="btn btn-dark">생성</button>
        </div>
    </form>
{% endblock %}
cs

19. <board> > 'detail.html'

'detail.html'

=====

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
{% extends 'base.html' %}
{% block con %}
    <h1><b>{{ b.subject }}</b></h1>
    <div class="row mt-5">
        <div class="col-sm-9">
            <textarea class="form-control" style="height:200px" disabled>{{ b.content }}</textarea>
        </div>
        <div class="col-sm-3">
            <img src="{{ b.writer.getpic }}" width="100%">
            <div class="text-center mt-3">
                <h5>written by <b>{{ b.writer }}</b></h5>
            </div>
            <div class="text-end mt-3">
                <b>{{ b.pubdate|date:'Y년 m월 d일 / H:i' }}</b>
            </div>
        </div>
    </div>
    <div class="text-end mt-4">
        <a href="{% url 'board:index' %}" class="btn btn-dark">글목록</a>
        {% if user == b.writer %}
            <a href="{% url 'board:update' b.id %}" class="btn btn-dark">글수정</a>
            <!-- Button trigger modal -->
            <button type="button" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#remove">
                글삭제
            </button>
        {% endif %}
    </div>
 
    <!-- Modal -->
    <div class="modal fade" id="remove" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title" id="exampleModalLabel"><b>게시글 삭제 알림창</b></h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body">
                    정말 삭제하시겠습니까?
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">취소</button>
                    <a href="{% url 'board:delete' b.id %}" class="btn btn-danger">삭제</a>
                </div>
            </div>
        </div>
    </div>
{% endblock %}
cs

20. <board> > 'update.html'

'update.html'

=====

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{% extends 'base.html' %}
{% block con %}
    <h1><b>게시글수정</b></h1>
    <form method="post">
        {% csrf_token %}
        <div class="mb-3 mt-5">
            <label class="form-label"><b>SUBJECT</b></label>
            <input type="text" value="{{b.subject}}" name="sub" class="form-control">
        </div>
        <div class="mb-3">
            <label class="form-label"><b>WRITER</b></label>
            <input type="text" class="form-control" disabled value="{{ b.writer }}">
        </div>
        <div class="mb-3">
            <label class="form-label"><b>CONTENT</b></label>
            <textarea class="form-control" name="con" style="height: 150px;">{{ b.content }}</textarea>
        </div>
        <div class="text-end mt-3">
            <button class="btn btn-dark">수정</button>
        </div> 
    </form>
{% endblock %}
cs

 

반응형