본문 바로가기

SK네트웍스 Family AI캠프 10기/Daily 회고

75일차. Django

더보기

 

75일 차 회고.

 

 주말 동안 스트레스받을 일이 있어서 잠을 많이 잤더니 어젯밤에 잠이 잘 오지 않았다. 그래서 잠을 충분히 자지 못해서 하루 종일 피곤했던 것 같다. 장고도 내일이면 끝나는데 어떻게 하는지는 알겠지만 막상 혼자서 하려고 하면 잘 되지 않아서 답답하다.

 

 

 

 

1. Django

 

 

1-1. Login - Django

 

가상환경 생성

uv venv .venv -p 3.13
.\.venv\Scripts\activate

uv pip install -r .\requirements.txt
# requirements.txt

django
mysqlclient

 

Django 프로젝트 생성

django-admin startproject config .

 

Django 앱 생성

python manage.py startapp user
python manage.py startapp todolist

 

templates 생성

mkdir templates
mkdir .\templates\base
mkdir .\templates\user
mkdir .\templates\todolist

 

static 생성

mkdir static
mkdir .\static\css

 

코드 작성

  • TEMPLATE
<!--templates/user/index.html-->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>User Page</title>
</head>
<body>
    <h1>User List</h1>
</body>
</html>
<!--templates/todolist/index.html-->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>To-do List Page</title>
</head>
<body>
    <h1>To-do List</h1>
</body>
</html>
  • VIEW
# user/views.py

from django.shortcuts import render

def index(request):
    return render(request, 'user/index.html')
# todolist/views.py

from django.shortcuts import renderfrom django.shortcuts import render

def todolist(request):
    return render(request, 'todolist/todolist.html')
  • URL RESOLUTION
# config/urls.py

from django.urls import path, include

urlpatterns = [
    path('user/', include('user.urls')),
    path('', include('todolist.urls')),
]
# user/urls.py

from django.urls import path
from .views import index

urlpatterns = [
    path('', index, name='user'),
]
# todolist/urls.py

from django.urls import path
from .views import todolist

urlpatterns = [
    path('', todolist, name='todolist'),
]
  • SETTING
# config/settings.py

import os
from pathlib import Path

...

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'user',
    'todolist',
]

...

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': ['templates'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

...

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django_db',
        'USER': 'django_root',
        'PASSWORD': 'r1234',
        'HOST': 'localhost',
        'PORT': '3306',
    }
}

...

STATIC_URL = 'static/'
STATIC_PATH = os.path.join(BASE_DIR, 'static')
STATICFILES_DIRS = (STATIC_PATH,)

...

 

서버 실행

python manage.py runserver

 

Login 기능 구현

  • TEMPLATE
<!--templates/base/index.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">
    {% block stylesheet %} {% endblock %}
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
<!--templates/user/login.html-->

{% extends 'base/index.html' %}

{% block title %}Login Page{% endblock %}

{% block stylesheet %}
{% load static %}
<link rel="stylesheet" href="{% static 'css/login.css' %}">
{% endblock %}

{% block content %}
<div class="wrapper">
    <h2>Login</h2><br>

    {% if messages %}
    {% for message in messages %}
        <h2 style="color: #b22222;">{{message}}</h2>
    {% endfor %}
    {% endif %}
    <form action="#" method="POST">
    {% csrf_token %}
    <div class="input-box">
        <input type="text" placeholder="Enter your username" required name="username">
    </div>
    <div class="input-box">
        <input type="password" placeholder="Enter your password" required name="password">
    </div>
    <div class="policy">
    </div>
    <div class="input-box button">
        <input type="Submit" value="Login">
    </div>
    <div class="text">
        <h3>Don't have an account? <a href="{% url 'user-register' %}">Register now</a></h3>
    </div>
    <div class="text">
        <h3>Forgot Password? <a href="{% url 'user-login' %}">Reset</a></h3>
    </div>
    </form>
</div>
{% endblock %}
<!--templates/user/register.html-->

{% extends 'base/index.html' %}

{% block title %}Register Page{% endblock %}

{% block stylesheet %}
{% load static %}
<link rel="stylesheet" href="{% static 'css/register.css' %}">
{% endblock %}

{% block content %}
<div class="wrapper">
    <h2>Register</h2><br>
    {% if messages %}
        {% for message in messages %}
            <h2 style="color: #b22222;">{{message}}</h2>
        {% endfor %}
    {% endif %}
    <form action="#" method="POST">
    {% csrf_token %}
    <div class="input-box">
        <input type="text" placeholder="Create a username" required name="username">
    </div>
    <div class="input-box">
        <input type="email" placeholder="Enter your email" required name="email">
    </div>
    <div class="input-box">
        <input type="password" placeholder="Enter your password" required name="password">
    </div>
    <div class="policy">
    </div>
    <div class="input-box button">
        <input type="Submit" value="Register">
    </div>
    <div class="text">
        <h3>Do you have an account? <a href="{% url 'user-login'%}">Login now</a></h3>
    </div>
    <div class="text">
        <h3>Forgot Password? <a href="{% url 'user-register'%}">Reset</a></h3>
    </div>
    </form>
</div>
{% endblock %}
<!--templates/todolist/todolist.html-->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>To-do List Page</title>
</head>
<body>
    <h1>To-do List</h1>
    <a href="{% url 'user-logout'%}">Logout</a>
</body>
</html>
  • VIEW
# user/views.py

from django.shortcuts import render, redirect
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login, logout
from django.contrib import messages

def user_register(request):
    if request.user.is_authenticated:
        return redirect(to='todolist')
    elif request.method == 'POST':
        username = request.POST.get('username').strip()
        email = request.POST.get('email').strip()
        password = request.POST.get('password').strip()

        if User.objects.filter(username=username).exists():
            messages.error(request, 'Username already exists')
            return redirect(to='user-register')
        elif not username or not email or not password:
            messages.error(request, 'Email and password are required')
            return redirect(to='user-register')
        
        new_user = User.objects.create_user(
            username=username,
            email=email,
            password=password
        )
        new_user.save()
        
        return redirect(to='user-login')

    return render(request, 'user/register.html')

def user_login(request):
    if request.user.is_authenticated:
        return redirect(to='todolist')
    elif request.method == 'POST':
        username = request.POST.get('username').strip()
        password = request.POST.get('password').strip()

        auth_user = authenticate(username=username, password=password)
        if not auth_user:
            messages.error(request, 'Invalid username or password')
            return redirect(to='user-login')
        
        login(request, auth_user)
        return redirect(to='todolist')

    return render(request, 'user/login.html')

def user_logout(request):
    logout(request)
    return redirect(to='user-login')
  • URL RESOLUTION
# user/urls.py

from django.urls import path
from .views import user_register, user_login, user_logout

urlpatterns = [
    path('register/', user_register, name='user-register'),
    path('login/', user_login, name='user-login'),
    path('logout/', user_logout, name='user-logout'),
]

 

To-do List 기능 구현

  • MODEL
# todolist/models.py

from django.db import models
from django.contrib.auth.models import User

class TodoList(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    title = models.CharField(max_length=200)
    status = models.BooleanField(default=False)

    def __str__(self):
        return self.title
  • TEMPLATE
<!--templates/base/index.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">
    {% block stylesheet %} {% endblock %}
    {% block script %} {% endblock %}
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
<!--templates/todolist/todolist.html-->

{% extends 'base/index.html' %}

{% block stylesheet %}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
{% endblock %}

{% block script %}
<script src="//d.bablic.com/snippet/6288d4c3c4c5800001a91242.js?version=3.9"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js" integrity="sha384-QJHtvGhmr9XOIpI6YVutG+2QOK9T+ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-fQybjgWLrvvRgtW6bFlB7jaZrFsaBXjsOMm/tB9LTS58ONXgqbR9W8oWht/amnpF" crossorigin="anonymous"></script>
{% endblock %}

{% block title %}To-do List Page{% endblock %}

{% block content %}
<h1 class="fs-1 fw-bold p-2 text-center" style="color:lightseagreen;">To-do List</h1>
<section class="vh-100" style="background-color: #eee;">
    <div class="container text-center font-monospace py-5 h-100">
        <div class="row d-flex justify-content-center align-items-center h-100">
        <div class="col col-lg-9 col-xl-7">
            <div class="card rounded-3">
            <div class="card-body p-4">
                {% if messages %}
                {% for message in messages %}
                    <h4 style="color: crimson;">{{message}}</h4>
                {% endfor %}
                {% endif %}
                <h2 class="fw-bold my-3 pb-3">Todo List</h2>
                <form method="POST" class="row row-cols-lg-auto g-3 justify-content-center align-items-center mb-4 pb-2">
                {% csrf_token %}
                    <div class="col-12">
                        <div class="form-outline">
                        <input type="text" id="form1" class="form-control" name="task" placeholder="Enter a task here"/>
                        </div>
                    </div>
                    <div class="col-12">
                        <button type="submit" class="btn btn-outline-primary w-40">Add Task</button>
                        <a href="{% url 'user-logout' %}">
                            <button type="button" class="btn btn-outline-info w-40">Logout</button>
                        </a>
                    </div>
                </form>
                {% if todo_list|length > 0 %}
                <table class="table mb-4">
                    <thead>
                        <tr>
                        <th scope="col">Todo Item</th>
                        <th scope="col">Status</th>
                        <th scope="col">Action</th>
                        </tr>
                    </thead>
                    <tbody>
                        {% for i in todo_list %}
                        <tr>
                        <td>{{i.title}}</td>
                        {% if i.status == True %}
                            <td>Complete</td>
                        {% else %}
                            <td>In progress</td>
                        {% endif %}
                        <td>
                            <a href="{% url 'todolist-update' i.id %}"><button type="submit" class="btn btn-outline-success col-5">Finished</button></a>
                            <a href="{% url 'todolist-delete' i.id %}"><button type="submit" class="btn btn-outline-danger col-5">Delete</button></a>
                        </td>
                        </tr>
                        {% endfor %}
                    </tbody>
                </table>
                {% else %}
                <h4 style="color: crimson;">No tasks available</h4>
                {% endif %}
            </div>
            </div>
        </div>
        </div>
    </div>
</section>
{% endblock %}
  • VIEW
# todolist/views.py

from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .models import TodoList

@login_required(login_url='user-login')
def todolist(request):
    if request.method == 'POST':
        task = request.POST.get('task').strip()

        if TodoList.objects.filter(title=task, user=request.user).exists():
            messages.error(request=request, message='Task already exists')
            return redirect(to='todolist')
        elif not len(task):
            messages.error(request=request, message='Task cannot be empty')
            return redirect(to='todolist')

        new_task = TodoList(title=task, user=request.user)
        new_task.save()

    content = {
        "todo_list": TodoList.objects.filter(user=request.user).order_by('id'),
    }
    return render(request, 'todolist/todolist.html', content)

@login_required(login_url='user-login')
def update_task(request, task_id):
    task = TodoList.objects.get(id=task_id, user=request.user)
    task.status = True
    task.save()

    return redirect(to='todolist')

@login_required(login_url='user-login')
def delete_task(request, task_id):
    TodoList.objects.filter(id=task_id, user=request.user).delete()

    return redirect(to='todolist')
  • URL RESOLUTION
# todolist/urls.py

from django.urls import path
from .views import todolist, update_task, delete_task

urlpatterns = [
    path('', todolist, name='todolist'),
    path('todolist-update/<int:task_id>', update_task, name='todolist-update'),
    path('todolist-delete/<int:task_id>', delete_task, name='todolist-delete'),
]

 

 

'SK네트웍스 Family AI캠프 10기 > Daily 회고' 카테고리의 다른 글

77일차. AWS - IAM & EC2  (0) 2025.04.30
76일차. Django  (0) 2025.04.29
74일차. Django  (0) 2025.04.25
73일차. Django  (0) 2025.04.24
72일차. JavaScript & Django  (0) 2025.04.23