Django 프로젝트-To Do List(10): 스타일링

4 minute read

1. block content

이제 모든 서버 작업을 마쳤으니 보기 좋게 꾸며보는 시간만이 남았다. 이 프로젝트의 목적은 django에 대한 기초를 알아보는 것으로, 지금부터 할 프론트엔드 절차는 자세하게 설명하지는 않고 핵심만 짚어가며 살펴보도록 하자.

먼저 스타일링을 담당할 main.html을 생성하자. 그리고 가장 중요한 것은 바로 block절이다. 해당 구문은 여러 뷰에 중복되는 템플릿이 있는 경우 사용한다.

우선 main의 스타일링을 적용할 부분에 block 구문을 선언해주고, 중복되는 템플릿을 적용할 모든 템플릿에 main을 상속하고 적용할 템플릿을 block절 안으로 넣는다. 여기서는 모든 템플릿에 이를 반복한다. 예시는 task_list 하나만 기술한다.

<!-- task/templates/task/main.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>To Do Items</title>
</head>
<body>
    <div class="container">
        {% block content %} {% endblock content %}
    </div>
</body>
</html>
<!-- task/templates/task/task_list.html-->
{% extends 'task/main.html' %}
{% block content %}
<h1>Login</h1>

<form method="POST">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="login">
</form>

<p>Don't have am account? <a href="{% url 'register' %}">Register</a> </p>
{% endblock %}

2. 유저 정보 스타일링

이제 본격적인 스타일링을 시작한다. 여기서는 그리 복잡하지 않기 때문에 head에 바로 style 태그를 만들어 스타일링을 한다.

<!-- task/templates/task/main.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>To Do Items</title>
    <link rel="preconnect" href="https://fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css2?family=Nunito:wght@200&display=swap" rel="stylesheet">
    <style>
        body {
            background-color: #FAFAFA;
            font-family: 'Nunito', sans-serif;
            padding-top: 50px;
        }

        h1,
        h2,
        h3,
        h4,
        h5,
        h6,
            {
            font-family: 'Raleway', sans-serif;
        }
        .container {
            max-width: 550px;
            margin: auto;
            background-color: #fff;
            -webkit-box-shadow: 2px 2px 13px -4px rgba(0, 0, 0, 0.21);
            box-shadow: 2px 2px 13px -4px rgba(0, 0, 0, 0.21);
        }
    </style>
</head>
<body>
    <div class="container">
        {% block content %} {% endblock content %}
    </div>
</body>
</html>

다음은 task_list에 사용자의 정보와 완료되지 않은 task의 개수를 나타내는 템플릿을 작성해보자. 먼저 기존의 유저 확인란을 제거하고 아래의 코드를 입력한다.

하나하나 살펴보면 새로 보이는 템플릿 태그가 있다. 우선 {{ request.user|title }}은 필터 태그로 원하는 형식으로 바꿀 수 있게 도와준다. title은 앞글자만 대문자로 바꾸는 필터태그이다.

{{ count|pluralize:”s” }}는 복수형으로 바꿀 수 있게 도와주는 태그로 count가 1개보다 많을 때 뒤에 s를 붙여준다.

<!-- task/templates/task/task_list.html-->
{% extends 'task/main.html' %}
{% block content %}
<div class="header-bar">
    <div>
        <h1>Hello {{ request.user|title }}</h1>
        <h3 style="margin:0">You have <i>{{ count }}</i> incomplete task{{ count|pluralize:"s" }}</h3>
    </div>

    {% if request.user.is_authenticated %}
    <a href="{% url 'logout' %}">Logout</a> {% else %}
    <a href="{% url 'login' %}">Login</a> {% endif %}
</div>
...

그 다음은 해당 html의 css를 완료해준다.

<!-- task/templates/task/main.html-->
        .header-bar {
            display: flex;
            justify-content: space-between;
            color: #fff;
            padding: 10px;
            border-radius: 5px 5px 0 0;
            background: linear-gradient(90deg, #EEA390 0%, #EB796F 43%, #EB796F 100%);
        }
        .header-bar a {
            color: rgb(247, 247, 247);
            text-decoration: none;
        }

3. 리스트 스타일링

유저 정보 스타일링을 마쳤으니 이제 바로 밑에 리스트를 스타일링 해보자. 여기서 중요한 스타일링은 task를 완료했다면 선이 그어지게 하고 삭제버튼을 구현하는 것이다.

<!-- task/templates/task/task_list.html-->
<div id="tasklist" class="task-items-wrapper">
    {% for task in tasks %}
    <div class="task-wrapper">
        {% if task.complete %}
        <div class="task-title">
            <div class="task-complete-icon"></div>
            <i><s><a href="{% url 'task-update' task.id %}">{{ task }}</a></s></i>
        </div>
        {% else %}
        <div class="task-incomplete-icon"></div>
            <a href="{% url 'task-update' task.id %}">{{ task }}</a>
        </div>
        {% endif %}
        <a class="delete-link" href="{% url 'task-delete' task.id %}">&#215;</a>
    </div>
    {% empty %}
    <h3>No items in list</h3>
    {% endfor %}{% raw %}
</div>
...
<!-- task/templates/task/main.html-->
        .task-wrapper {
            display: flex;
            align-items: center;
            justify-content: space-between;
            background-color: #fff;
            border-top: 1px solid #dfe4ea;
            overflow: hidden;
            padding: 20px;
        }
        .task-title {
            display: flex;
            padding: 20px;
        }

        .task-title a {
            text-decoration: none;
            color: #4b5156;
            margin-left: 10px;
        }
        .task-complete-icon {
            height: 20px;
            width: 20px;
            background-color: rgb(105, 192, 105);
            border-radius: 50%;
        }
        .task-incomplete-icon {
            height: 20px;
            width: 20px;
            background-color: rgb(218, 218, 218);
            border-radius: 50%;
        }
        .delete-link {
            text-decoration: none;
            font-weight: 900;
            color: #cf4949;
            font-size: 22px;
            line-height: 0;
            padding: 20px 0px;
        }

리스트를 고쳤으니 바로 위에 검색창과 추가버튼을 스타일링하자.

<!-- task/templates/task/task_list.html-->
<div id="search-add-wrapper">
    <form method="GET" style="display: flex;">
        <input type='text' name='search-area' value="{% raw %}{{ search_input }}">
        <input class="button" type="submit" value='Search'>
    </form>
    <a id="add-link" href="{% url 'task-create' %}">&#x2b;</a>
</div>
<!-- task/templates/task/main.html-->
        #add-link {
            color: #EB796F;
            text-decoration: none;
            font-size: 42px;
            text-shadow: 1px 1px #81413b;
        }

        #search-add-wrapper {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 20px;
        }
        input[type=text],
        input[type=password],
        textarea {
            border: 1px solid #EB796F;
            border-radius: 5px;
            padding: 10px;
            width: 90%;
        }

        label {
            padding-top: 10px !important;
            display: block;
        }

        .button {
            border: 1px solid #EB796F;
            background-color: #FAFAFA;
            color: #EB796F;
            padding: 10px;
            font-size: 14px;
            border-radius: 5px;
            cursor: pointer;
            text-decoration: none;
        }
        .card-body {
            padding: 20px;
        }

추가로 task_form도 보기 좋게 정렬해주었다.

<!-- task/templates/task/task_form.html-->
{% extends 'task/main.html' %}
{% block content %}
<div class="header-bar">
    <a href="{% url 'tasks' %}">&#8592; Back</a>
</div>

<div class="card-body">
    <form method="POST" action="">
        {% csrf_token %}
        {{ form.as_p }}
        <input class="button" type="submit" value="Submit">
    </form>
</div>
{% endblock %}
<!-- task/templates/task/main.html-->
        .card-body {
            padding: 20px;
        }

마지막으로 delete와 register, login까지 스타일링을 완료한다.

<!-- task/templates/task/task_confirm_delete.html-->
{% extends 'task/main.html' %}
{% block content %}
<div class="header-bar">
    <a href="{% url 'tasks' %}">&#8592;Go Back</a>
</div>

<div class="card-body">
    <form method="POST">
        {% csrf_token %}
        <p>Are you sure you want to delete this task "{{ task }}"</p>
        <input type="submit" value="Delete">
    </form>
    {% endblock %}
</div>
<!-- task/templates/task/register.html-->
{% extends 'task/main.html' %}
{% block content %}
<div class="header-bar">
    <h1>Register</h1>
</div>

<div class="card-body">
    <form method="POST">
        {% csrf_token %}
        <label>{{form.username.label}}</label>
        {{form.username}}

        <label>{{form.password1.label}}</label>
        {{form.password1}}

        <label>{{form.password2.label}}</label>
        {{form.password2}}
        <input style="margin-top:10px ;" class="button" type="submit" value="Register">
    </form>
    <p>Already have an account? <a href="{% url 'login' %}">Login</a></p>
</div>
{% endblock %}
<!-- task/templates/task/login.html-->
{% extends 'task/main.html' %}
{% block content %}
<div class="header-bar">
    <h1>Login</h1>
</div>

<form method="POST">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="login">
</form>

<p>Don't have am account? <a href="{% url 'register' %}">Register</a> </p>
{% endblock %}

Leave a comment