goodthings4me.tistory.com
파이썬 장고(django) 웹 프로그래밍 - 웹 페이지 만들기(1)
- 프로젝트 생성과 로그인 페이지(accounts 앱) 만들기
※ 쿠팡 파트너스 API 데이터를 추출하고 파이썬 장고(django)를 활용해 웹 서비스 페이지 만들어보기
- 초급 수준의 장고를 익히고 다음 단계로 넘어가기 위한 실전 경험 차원에서 웹 사이트 하나를 만들어 보려고 도전함
- 일부 기능과 오류 해결을 위해 구글 등에서 검색하여 사이트를 완성해가기 때문에 소스가 투박할 수 있음
- 에디터는 파이참 사용, 파이썬 3.95 버전과 장고 3.2 버전 설치 후 개발
- 쿠팡 파트너스 API로 쿠팡 상품을 추출하고, db.sqlite3에 insert 한 후 웹 페이지에서 서비스 하는 기능을 단계별로 기술함
01. 파이참(PyCharm)에서 프로젝트 생성
- 가상환경 설정 후 프로젝트 진행 (파이참이 아닌 Visual Studio Code도 가능)
D:\에 borame라는 폴더를 만들고, Location에서 불러온 후, Base Interpreter로 설치한 파이썬 버전을 선택한다.
02. 장고 설치
- 프로젝트 진입 후 파이참 터미널에서 venv/Scripts/activate 명령으로 가상환경에 접속한 후 장고를 설치한다.
(venv) PS D:\borame> pip install django==3.2 # 장고 3.2 버전 설치
# pip 업그레이드도 하라고 하니 실행한다.
(venv) PS D:\borame> python.exe -m pip install --upgrade pip
03. 프로젝트 생성
(venv) PS D:\borame> django-admin startproject config .
04. 기본 앱(DB) migrate --> db.sqlite3 파일 생성
(venv) PS D:\borame> python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying sessions.0001_initial... OK
(venv) PS D:\borame>
05. 어드민 계정 생성
(venv) PS D:\borame> python manage.py createsuperuser
Username (leave blank to use 'haemi'): admin
Email address:
Password:
Password (again):
Superuser created successfully.
(venv) PS D:\borame>
06. Window 명령 프롬프트 실행 후 테스트서버 실행 (파이참에서 직접 실행도 가능)
- 배치 파일을 만들어 놓고 사용하면 편리함 (bo.bat)
@echo off
cd/
d:
cd borame
cd venv
cd Scripts
activate
# 명령 프롬프트 실행 : 윈도우키 + q 또는 r 누른 후 "cmd" 입력
# 서버 구동 확인 : localhost:8000 or 127.0.0.1:8000
# localhost:8000/admin 입력 후 Username과 Password 입력
07. 사용자 계정 관리용 accounts 앱 생성 및 settings.py에 등록
(venv) PS D:\borame> python manage.py startapp accounts
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'accounts',
]
# 언어 및 TIME_ZONE 설정 (settings.py / TIME_ZONE 설정은 개인마다 차이 있음)
LANGUAGE_CODE = 'ko-kr' # 'en-us'
TIME_ZONE = 'Asia/Seoul' # 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = False
08. accounts 앱 하위에 templates 폴더 생성과 URLConf 정의를 위한 urls.py 파일 생성
※ URLConf 란, 특정 URL과 뷰를 매핑하는 List(settings.py에 최상위 URLConf 모듈 지정)
- URL로부터 뷰(View)를 얻기 위해, Django는 URLConf 라는 것을 사용한다.
- 어떤 url 요청이 들어오면 URLconf는 URL 패턴에 대해 어떤 views.py의 함수를 실행시킬지 정의한다.
# accounts 앱은 간단하게 입력 폼만을 다시 만들고, 계정은 admin 페이지에서 관리토록 함
- borame 사이트가 회원가입을 위한 것이 아니기 때문에 accounts 모델(models) 작성은 안하고 뷰(views)는 CBV(Class Based View)를 사용함
- 계정 관리 앱(accounts)에서는 'app_name' 사용하지 말라는 전문가의 의견이 있어서 사용 안함
from django.urls import path
from django.contrib.auth import views as auth_views
urlpatterns = [
path('login/', auth_views.LoginView.as_view(template_name='accounts/login.html'), name='login'),
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
]
- 로그인 페이지 URLConf 적용 : config>urls.py 수정
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('accounts.urls')),
]
- login.html 템플릿 생성
09. 웹 페이지 레이아웃 만들기
- login.html 템플릿 파일과 이후 만들어질 템플릿 파일들의 레이아웃 통일을 위해 전체 페이지 레이아웃을 만들고 그 페이지를 상속받아서 사용함
- 전체 페이지 레이아웃 설정 위해 폴더(템플릿 layout 폴더) 생성후 settings.py에 등록하고, 그 폴더에 base.html 파일을 만들어서 사용한다. (base.html 은 bootstrap 사용함)
- layout 템플릿 폴더는 프로젝트 root인 borame 밑에 만듦 : borame>layout
- settings.py 설정 (os 모듈이 필요함. 상단에 import os 추가)
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
여기서 'DIR':[] 부분을
'DIRS': [os.path.join(BASE_DIR, 'layout')], 처럼 수정
- layout 밑에 base.html 템플릿 파일 생성
https://getbootstrap.com/docs/5.1/getting-started/introduction/ 에서 CSS 부분과 JS 부분의 코드를 복사하여 base.html에 붙여넣기 함
# css : https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css
# js : https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/js/bootstrap.bundle.min.js
- bootstrap navbar layout 그대로 사용할 것이고, 템플릿 상속을 위해
<body> 부분에 아래 내용을 추가한다.
{% block content %}
{% endblock %}
# 전체 레이아웃 템플릿 파일 : base.html
<!DOCTYPE html>
<html lang="ko">
<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>Borame</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container-fluid">
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="#">BORAME</a>
<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="#">Home</a></li>
<li class="nav-item"><a class="nav-link" href="#">상품리스트</a></li>
{% if user.is_authenticated %}
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"
data-bs-toggle="dropdown" aria-expanded="false">상품등록/수정</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
<li><a class="dropdown-item" href="#">상품 등록</a></li>
<li><a class="dropdown-item" href="#">쿠팡 Redirect URL</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#">쿠팡 Update(Detail)</a></li>
</ul>
</li>
<li class="nav-item"><a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a></li>
<li class="nav-item"><a class="nav-link" href="#">로그아웃</a></li>
{% else %}
<li class="nav-item"><a class="nav-link" href="#">로그인</a></li>
{% endif %}
</ul>
<form class="d-flex">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</div>
</nav>
</div>
{% block content %}
{% endblock %}
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
- 로그인 여부(user.is_authenticated)에 따라 보여주는 메뉴가 틀림 (일반 사용자와 관리자만 구분)
10. 로그인 페이지 만들기
- 로그인 템플릿 파일 : login.html
{% extends "base.html" %}
{% block content %}
<div class="container p-3 my-3">
<form class="post-form my-3" method="post" action="{% url 'login' %}">
{% csrf_token %}
<div class="form-group my-3">
<label for="username">사용자 ID</label>
<input type="text" class="form-control" name="username" id="username" value="{{ form.username.value|default_if_none:'' }}">
</div>
<div class="form-group my-3">
<label for="password">비밀번호</label>
<input type="password" class="form-control" name="password" id="password" value="{{ form.password.value|default_if_none:'' }}">
</div>
<button type="submit" class="btn btn-primary">로그인</button>
</form>
</div>
{% endblock %}
# 로그인 페이지 : http://localhost:8000/accounts/login/ 접속 시
- 오류 발생 시 메시지를 보기 위해 layout 폴더에 form_errors.html (에러 메시지 표시) 파일 만듦
* 참고 사이트 : https://wikidocs.net/71259
# 파일 위치 : layout>form_errors.html
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<!-- 필드 오류를 출력한다. -->
<div class="alert alert-danger">
<strong>{{ field.label }}</strong>
{{ error }}
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<!-- 넌필드 오류를 출력한다. -->
<div class="alert alert-danger">
<strong>{{ error }}</strong>
</div>
{% endfor %}
{% endif %}
# 오류 메시지가 보이도록 login.html 파일에서 아래 부분을 수정 : {% include "form_errors.html" %} 부분 추가
<div class="container p-3 my-3">
<form class="post-form my-3" method="post" action="{% url 'login' %}">
{% csrf_token %}
{% include "form_errors.html" %}
11. 로그인 후 redirect 오류, 그리고 로그아웃 후 페이지 설정
- 장고는 로그인 후 profile로 자동 redirect 되도록 되어있다. 이런 로그인 경로를 localhost:8000 으로 가도록 하고, 로그아웃 부분도 동일 경로로 가도록 설정한다.
- 경로 설정은 settings.py에서 하며, base.html의 각 메뉴에도 연결할 것이고,
- 해당 프로젝트의 첫 페이지(root인 localhost:8000)가 앞으로 만들 쿠팡 파트너스 상품 리트스가 보이도록 products 앱을 만들어서 웹 페이지 default 파일인 index.html이 open 될 수 있도록 할 것임
# settings.py 하단 맨 마지막에 다음 내용을 추가한다.
LOGIN_URL = '/accounts/login/' # 로그인 버튼 클릭 또는 로그인 경로 지정 시 셋팅
LOGIN_REDIRECT_URL = '/' # 로그인 후 보내는 URL
LOGOUT_REDIRECT_URL = '/' # 로그아웃 후 보내는 URL
# base.html 수정
<li class="nav-item"><a class="nav-link" href="#">로그아웃</a></li> 부분을
<li class="nav-item"><a class="nav-link" href="{% url 'logout' %}">로그아웃</a></li> 로 수정
<li class="nav-item"><a class="nav-link" href="#">로그인</a></li> 부분을
<li class="nav-item"><a class="nav-link" href="{% url 'login' %}">로그인</a></li> 로 수정
# 로그인 후 localhost:8000 으로 보낸다. 현재 템플릿 파일이 없어서 Page not found (404) 오류 발생
>> 파이썬 장고(django) 웹 프로그래밍 - 웹 페이지 만들기 # 2
'코딩 연습 > 코딩배우기' 카테고리의 다른 글
구글에서 원하는 이미지 다운로드 해보기 (with 파이썬) (0) | 2021.10.11 |
---|---|
VS Code에서 파이썬 가상환경 만들기 (1) | 2021.10.11 |
티스토리 포스팅 글, 이미지 백업 (with 파이썬) (1) | 2021.09.06 |
파이썬 datetime 모듈과 장고(django) 모델(models) 시간 (0) | 2021.09.03 |
쿠팡 파트너스 상품 링크 상세정보 URL로 들어가기 - 오류 발생 (0) | 2021.08.27 |
댓글