파이썬

 

 

 

 

시작하기

 

소스 : https://github.com/braverokmc79/python-django-mysite

 

1.파이썬 설치, django 설치, 가상환경 세팅

 

공식문서  :  빠른 설치 가이드

 

1. 파이썬 및 Django 설치 개요

Django 웹 개발을 시작하기 위해서는 먼저 파이썬(Python)을 설치해야 합니다. 또한, Django 프로젝트는 독립적인 환경에서 실행되는 것이 좋기 때문에

가상 환경(virtual environment)을 설정하는 것이 필수적입니다. 이번 강좌에서는 Python 설치, Django 설치 및 가상 환경 설정 방법을 차근차근 알아보겠습니다.

 

2. 파이썬 설치

  1. Python 공식 홈페이지 접속

  2. 설치 실행

    • 다운로드한 설치 파일을 실행하고, "Add Python to PATH" 옵션을 체크한 후 설치를 진행합니다.
  3. 설치 확인

    • 명령 프롬프트(cmd)에서 아래 명령어를 입력하여 정상적으로 설치되었는지 확인합니다.
    python --version
    
    • 정상적으로 설치되었다면 Python 버전이 출력됩니다.

 

3. 가상 환경(Virtual Environment) 설정

Django 프로젝트마다 독립적인 환경을 유지하기 위해  가상 환경(virtual environment) 을 설정해야 합니다.

  1. 가상 환경 패키지 설치

    pip install virtualenv
    
  2. 가상 환경 생성

    • 원하는 프로젝트 폴더에서 아래 명령어 실행:
    python -m venv myenv
    
    • myenv 폴더가 생성되며, 이 폴더 안에서 가상 환경이 실행됩니다.
  3. 가상 환경 활성화

    • Windows:
      myenv\Scripts\activate
      
    • Mac/Linux:
      source myenv/bin/activate
      
    • 활성화되면 프롬프트 앞에 (myenv)가 표시됩니다.

 

4. Django 설치

  1. Django 설치 명령어 실행

    pip install django
    
  2. 설치 확인

    python -m django --version
    
    • 설치된 Django의 버전이 출력되면 정상적으로 설치된 것입니다.

 

5. Django 프로젝트 생성 및 실행

  1. 새 프로젝트 생성

    django-admin startproject myproject
    
    • myproject 폴더가 생성됩니다.
  2. 서버 실행

    python manage.py runserver
    
    • 터미널에 http://127.0.0.1:8000/ 주소가 표시되면 브라우저에서 접속하여 Django가 정상적으로 실행되는지 확인합니다.

 

 

6. 정리

이로써 Django 개발을 위한 기본적인 환경 설정이 완료되었습니다.

 

 

 

 

 

 

 

 

 

 

2.프로젝트 생성, app 생성, 서버 구동, django cycle

 

공식문서 : 첫 번째 장고 앱 작성하기, part 1

 

1. Django 프로젝트 생성 및 실행

1. 개발 환경 설정

Django 프로젝트를 시작하기 전에 개발 환경을 설정해야 합니다. 먼저 Python과 Django가 정상적으로 설치되었는지 확인하세요.

가상 환경 설정 및 Django 설치

# 가상 환경 생성
python -m venv myenv

# 가상 환경 활성화 (Windows)
myenv\Scripts\activate

# 가상 환경 활성화 (Mac/Linux)
source myenv/bin/activate

# Django 설치
pip install django

설치 확인

python -m django --version

Django 버전이 출력되면 정상적으로 설치된 것입니다.

 

2. Django 프로젝트 생성

프로젝트 생성

django-admin startproject mysite

이 명령어를 실행하면 mysite 디렉터리가 생성되며, 기본적인 Django 프로젝트 구조가 구성됩니다.

프로젝트 폴더 구조

mysite/
├── manage.py
├── mysite/
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   ├── asgi.py
│   ├── wsgi.py

각 파일의 역할은 다음과 같습니다:

  • manage.py: Django 프로젝트를 관리하는 명령어 실행 스크립트
  • settings.py: 프로젝트의 설정 파일
  • urls.py: URL 라우팅 설정
  • wsgi.py, asgi.py: 웹 서버와 Django를 연결하는 파일

 

3. 서버 실행 및 Django 동작 흐름

개발 서버 실행

python manage.py runserver

이 명령어를 실행하면 개발 서버가 실행됩니다.

Django의 동작 흐름

  1. 사용자가 웹 브라우저에서 특정 URL을 입력합니다.
  2. Django의 urls.py가 요청된 URL을 분석하여 적절한 뷰(View)로 연결합니다.
  3. 뷰(View)에서 요청을 처리하고, 필요하다면 데이터베이스에서 데이터를 가져옵니다.
  4. 템플릿(Template)을 사용하여 사용자에게 HTML 응답을 반환합니다.
  5. 클라이언트(웹 브라우저)는 응답을 받아 화면에 표시합니다.

 

4. Django 앱 생성

Django에서는 기능 단위로 앱을 생성하여 프로젝트를 구성합니다.

앱 생성 명령어

python manage.py startapp polls

앱 폴더 구조

polls/
├── __init__.py
├── admin.py
├── apps.py
├── models.py
├── tests.py
├── views.py

각 파일의 역할은 다음과 같습니다:

  • views.py: 웹 페이지의 로직을 정의하는 파일
  • models.py: 데이터베이스 모델을 정의하는 파일
  • admin.py: Django 관리자 페이지 설정 파일
  • apps.py: 앱의 설정 정보를 담은 파일

앱 등록

settings.py 파일에서 INSTALLED_APPS 목록에 polls 앱을 추가합니다.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'polls',  # 새로 만든 앱 추가
]

 

5. 뷰(View)와 URL 설정

뷰(View) 생성

polls/views.py 파일을 열고 다음과 같이 수정합니다.

from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")

URL 매핑

  1. polls/urls.py 파일을 생성하고 다음 코드를 추가합니다.
from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
]
  1. mysite/urls.py 파일을 수정하여 polls.urls를 포함합니다.
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('polls/', include('polls.urls')),
    path('admin/', admin.site.urls),
]

서버 실행 및 결과 확인

개발 서버를 실행하고 http://127.0.0.1:8000/polls/에 접속하면 Hello, world. You're at the polls index. 메시지가 나타납니다.

 

6. 정리

이번 강좌에서는 다음 내용을 학습했습니다:

  1. Django 프로젝트를 생성하는 방법
  2. Django의 기본적인 동작 흐름
  3. Django 앱을 생성하고 등록하는 방법
  4. 뷰(View)와 URL을 설정하여 웹 페이지를 만드는 방법

 

 

 

 

 

 

 

 

 

 

 

 

 

3.git 설치, git 사용법, github 사용법

 

1. Git의 필요성

Django 프로젝트를 개발할 때 코드 히스토리를 관리하는 것이 중요합니다. 이를 위해 Git을 사용하면 코드 변경 사항을 기록하고, 협업 시 코드 공유 및 버전 관리를 효과적으로 할 수 있습니다. 또한, GitHub와 같은 원격 저장소를 활용하면 프로젝트를 백업하고 협업할 수 있습니다.

 

2. Git 설치

Git을 사용하려면 먼저 Git을 설치해야 합니다.

  • Git 공식 웹사이트에서 운영 체제에 맞는 설치 파일을 다운로드합니다.
  • 다운로드한 파일을 실행하여 Git을 설치합니다.

설치가 완료되면 터미널 또는 명령 프롬프트에서 아래 명령어를 입력하여 Git이 정상적으로 설치되었는지 확인할 수 있습니다.

git --version

 

3. Git 기본 명령어

(1) Git 저장소 초기화

프로젝트 폴더에서 아래 명령어를 실행하여 Git 저장소를 초기화합니다.

git init

이 명령어를 실행하면 해당 폴더가 Git 저장소로 설정됩니다.

(2) 파일 추가 및 커밋

Git이 변경 사항을 추적하도록 파일을 추가하고, 커밋을 생성합니다.

git add .  # 모든 파일 추가
git commit -m "첫 번째 커밋"
  • git add . : 현재 폴더의 모든 변경 사항을 추가합니다.
  • git commit -m "메시지" : 변경 사항을 저장하는 커밋을 생성합니다.

(3) 변경 사항 확인

git status  # 현재 상태 확인
git log  # 커밋 내역 확인
  • git status : 변경된 파일 목록을 확인합니다.
  • git log : 커밋 히스토리를 확인합니다.

 

4. GitHub 저장소 연결 및 원격 저장소에 업로드

(1) GitHub 저장소 생성

  1. GitHub에 접속하여 로그인합니다.
  2. 새 저장소(repository)를 생성합니다.
  3. 저장소 이름을 설정하고, 공개/비공개 여부를 선택한 후 생성합니다.

(2) GitHub 원격 저장소 연결

git remote add origin https://github.com/사용자이름/저장소이름.git
git branch -M main
git push -u origin main
  • git remote add origin [URL] : 원격 저장소를 추가합니다.
  • git branch -M main : 기본 브랜치를 main으로 설정합니다.
  • git push -u origin main : 변경 사항을 원격 저장소에 업로드합니다.

 

5. 원격 저장소에서 변경 사항 가져오기

다른 기기에서 동일한 프로젝트를 가져오거나, 협업 중 변경 사항을 반영하려면 아래 명령어를 사용합니다.

git clone https://github.com/사용자이름/저장소이름.git

또한, 최신 변경 사항을 반영하려면 다음 명령어를 실행합니다.

git pull origin main

 

6. Git 사용 시 주의할 점

  • 중요한 파일(.env, db.sqlite3 등)은 .gitignore 파일을 사용하여 Git에 올리지 않도록 설정해야 합니다.
  • 커밋 메시지는 변경 사항을 명확히 설명하는 것이 좋습니다.
  • 실수로 커밋한 내용을 되돌릴 때는 git reset 또는 git revert 명령어를 활용할 수 있습니다.


 

.gitignore

# Python 관련
*.pyc
*.pyo
*.pyd
__pycache__/
*.swp
*.swo
*.bak

# Virtual Environment
env/
venv/
myenv/
ENV/
*.env
*.venv

# Django 관련
db.sqlite3
*.log
media/
staticfiles/

# VSCode 설정
.vscode/

# IDE 관련
.idea/
*.iml

# MacOS 관련
.DS_Store

# Windows 관련
Thumbs.db
ehthumbs.db
desktop.ini

 

7. 마무리

이번 강좌에서는 Git 설치부터 기본적인 명령어 사용법, GitHub 원격 저장소 연결까지 다루었습니다. Git을 활용하여 Django 프로젝트의 버전 관리를 효율적으로 진행하세요!

 

 

 

 

 

 

 

 

4.django model, model 사용법, api 사용

 

 

공식문서 :   첫 번째 장고 앱 작성하기, part 2

 

1. Django에서 데이터베이스 사용하기

웹 애플리케이션을 개발할 때 데이터를 저장하기 위해 데이터베이스가 필요합니다. Django는 기본적으로 SQLite를 사용하지만, MySQL, PostgreSQL 등 다양한 데이터베이스를 지원합니다. 데이터베이스 종류를 변경하려면 settings.py에서 DATABASES 설정을 수정하면 됩니다.

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mydatabase',
        'USER': 'myuser',
        'PASSWORD': 'mypassword',
        'HOST': 'localhost',
        'PORT': '3306',
    }
}

 

2. Django의 모델(Model) 개념

Django에서는 데이터베이스의 테이블을 모델(Model)이라는 개념으로 관리합니다. 모델은 데이터 구조를 정의하며, Django의 ORM(Object-Relational Mapping)을 통해 데이터베이스 테이블과 매핑됩니다.

from django.db import models

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
  • CharField: 문자열을 저장하는 필드
  • DateTimeField: 날짜 및 시간을 저장하는 필드
  • ForeignKey: 관계형 데이터베이스에서 외래 키(Foreign Key)를 설정하는 필드

 

mysite/settings.py

INSTALLED_APPS = [
    'polls.apps.PollsConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    #'polls',  # 새로 만든 앱 추가 중복 등록된 'polls'
]

 

 

3. 데이터베이스 마이그레이션

Django는 모델을 정의한 후 데이터베이스 테이블을 생성하는 마이그레이션(Migration) 기능을 제공합니다.

python manage.py makemigrations polls
python manage.py migrate
  • makemigrations: 모델의 변경 사항을 감지하고 마이그레이션 파일을 생성
  • migrate: 마이그레이션 파일을 실행하여 데이터베이스 테이블을 생성 또는 수정

 

4. Django ORM을 이용한 데이터 조작

Django ORM을 사용하면 SQL 문을 직접 작성하지 않고도 데이터베이스를 쉽게 조작할 수 있습니다.

from myapp.models import Question
from django.utils import timezone

# 데이터 생성
q = Question(question_text="What's new?", pub_date=timezone.now())
q.save()

# 데이터 조회
all_questions = Question.objects.all()
q1 = Question.objects.get(id=1)

# 데이터 수정
q1.question_text = "Updated question"
q1.save()

# 데이터 삭제
q1.delete()

 

5. shell 접속하여 실행

 

$ python manage.py shell
>>> from polls.models import Choice, Question 

>>> Question.objects.all()
<QuerySet []>


>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())


>>> q.save()


>>> q.id
1


>>> q.question_text

>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=datetime.timezone.utc)


>>> q.question_text = "What's up?"
>>> q.save()


>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>

서버를 실행한 후 /admin 페이지에서 로그인하면 데이터를 관리할 수 있습니다.

 

polls/models.py  수정후 다시   shell 접속하여 실행 테스트

import datetime
from django.db import models
from django.utils import timezone

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

    def __str__(self):
        return self.question_text
    
    def was_published_recently(self):
       return self.pub_date >= timezone.now() - datetime.timedelta(days=1)


class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

    def __str__(self):
        return self.choice_text
    

 

 

 

6. API를 활용한 데이터 조회

Django의 쉘을 실행하여 API를 통해 데이터를 조회할 수도 있습니다.

python manage.py shell
from myapp.models import Question
Question.objects.filter(question_text__startswith="What's")
  • filter(): 특정 조건을 만족하는 데이터를 조회
  • startswith(): 특정 문자열로 시작하는 데이터 검색

 

7. Django에서 MySQL 사용 시 주의할 점

Django에서 MySQL을 사용할 경우 몇 가지 주의해야 할 점이 있습니다.

  1. MySQL 클라이언트 설치

    pip install mysqlclient
    

    또는

    pip install pymysql
    

    그리고 __init__.py 파일에 다음 코드를 추가해야 합니다.

    import pymysql
    pymysql.install_as_MySQLdb()
    
  2. DATABASES 설정에서 ENGINE 값 확인 MySQL을 사용할 때 ENGINE 값은 'django.db.backends.mysql'이어야 합니다.

  3. UTF-8 인코딩 설정 my.cnf 파일에서 UTF-8을 사용하도록 설정하는 것이 좋습니다.

    [mysqld]
    character-set-server=utf8mb4
    collation-server=utf8mb4_unicode_ci
    

 

8. 정리 

이번 강의에서는 Django에서 MySQL을 설정하는 방법과 기본적인 데이터 조작 방법을 알아보았습니다. Django의 ORM을 활용하면 SQL을 직접 작성하지 않고도 데이터베이스를 쉽게 관리할 수 있습니다.

 

 

 

 

 

 

 

 

5.django admin 사용법

 

1. Django Admin 개요

  • Django는 기본적으로 관리자(Admin) 기능을 제공함.
  • 관리자 페이지는 웹 애플리케이션에서 콘텐츠를 관리하는 역할을 함.
  • HTML 페이지만 존재하는 사이트가 아니라면, 대부분의 웹 애플리케이션에 관리자 기능이 필요함.
  • Django의 Admin 기능은 데이터베이스 모델을 UI에서 쉽게 관리할 수 있도록 도와줌.

 

2. Django Admin 사용법

2.1 관리자 계정 생성

  1. 터미널에서 아래 명령어 실행:
    python manage.py createsuperuser
    
  2. 아이디, 이메일, 비밀번호 입력 후 관리자 계정 생성.
    • 비밀번호가 너무 단순하면 경고 메시지가 뜨지만, 강행 가능.

 

2.2 Django Admin 접속

  1. 서버 실행:
    python manage.py runserver
    
  2. 브라우저에서 관리자 페이지로 이동:
    http://127.0.0.1:8000/admin/
    
  3. 생성한 아이디와 비밀번호 입력 후 로그인.

 

2.3 모델 등록 및 관리

  • 기본적으로 데이터베이스에 저장된 모델 데이터는 관리자 페이지에서 보이지 않음.
  • admin.py에서 모델을 등록해야 확인 가능.
from django.contrib import admin

# Register your models here.
from .models import Question

admin.site.register(Question)
  • 등록 후 관리자 페이지 새로고침하면 해당 모델이 표시됨.
  • Django Admin을 통해 데이터 추가, 수정, 삭제 가능.
  • SQL이나 API 없이 웹 UI에서 직접 데이터 관리 가능.

 

3. Django Admin 활용

  • Django Admin은 웹 개발 시 테스트 및 데이터 관리에 매우 유용함.
  • 관리자 화면을 커스터마이징하여 원하는 스타일로 변경 가능.
  • 다음 강의에서는 View와 Template을 활용한 페이지 구성을 다룰 예정.

 

 

 

 

 

 

 

 

 

 

6.django view 사용, html 불러오기 및 연결

첫 번째 장고 앱 작성하기, part 3

 

1. 관리자 페이지 설정

from django.contrib import admin
from .models import Question, Choice

admin.site.register(Question)
admin.site.register(Choice)
  • Question과 Choice 모델을 Django 관리자 페이지에서 관리할 수 있도록 등록함.
  •  

2. URL 패턴 설정

from django.urls import path
from . import views

app_name = "polls"

urlpatterns = [    
    path("", views.index, name="index"),
    path("<int:question_id>/", views.detail, name="detail"),
    path("<int:question_id>/results/", views.results, name="results"),
    path("<int:question_id>/vote/", views.vote, name="vote"),   
]

 

  • polls/ 경로로 요청이 들어오면 index 뷰를 실행.
  • polls/<question_id>/ 경로는 detail 뷰를 실행.
  • polls/<question_id>/results/ 경로는 results 뷰 실행.
  • polls/<question_id>/vote/ 경로는 vote 뷰 실행.

 

3. 뷰(Views) 설정

from django.shortcuts import render , get_object_or_404
from .models import Question
# Create your views here.
from django.http import HttpResponse, Http404
from django.template import loader


# 메인 페이지 (index)
def index(request):
    # 1
    # return HttpResponse("Hello,world!")

    # 2
    # last_question_list = Question.objects.order_by('-pub_date')[:5]
    # output = ', '.join([q.question_text for q in last_question_list])
    # return HttpResponse(output)

    # 3
    # latest_question_list = Question.objects.order_by("-pub_date")[:5]
    # template = loader.get_template("polls/index.html")
    # context = {
    #     "latest_question_list": latest_question_list,
    # }
    # return HttpResponse(template.render(context, request))

    # 4
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {"latest_question_list": latest_question_list}
    return render(request, "polls/index.html" , context)


# 상세 페이지 (detail)
def detail(request, question_id):
    #1
    # try:
    #     question = Question.objects.get(pk=question_id)
    # except Question.DoesNotExist:
    #   raise Http404("Question does not exist")    
    # return render(request, "polls/detail.html", {"question" :question} )

    #2    
    question = get_object_or_404(Question,pk=question_id)    
    return render(request, "polls/detail.html", {"question": question})


# 결과 페이지 (results)
def results(request, question_id):
    response = "You're looking at the results of question %s."
    return HttpResponse(response % question_id)

# 투표 페이지 (vote)
def vote(request, question_id):
    return HttpResponse("You're voting on question %s." % question_id)

  • index: 최신 5개의 질문을 템플릿에 전달.
  • detail: 특정 질문을 가져와 상세 페이지에서 표시.
  • results: 특정 질문의 결과를 반환.
  • vote: 특정 질문에 대한 투표를 처리하는 뷰.

 

4. 템플릿 설정

4.1 상세 페이지 템플릿 (polls/detail.html)

<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>

 

  • 질문 텍스트를 제목으로 표시.
  • 해당 질문에 대한 모든 선택지를 리스트 형태로 표시.

 

4.2 메인 페이지 템플릿 (polls/index.html)

{% if latest_question_list %}
    <ul>
        {% for question in latest_question_list %}
        <li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
        {% endfor %}
    </ul>
{% else %}
    <p> No polls are available.</p>
{% endif %}
  • 최신 질문 목록을 출력하며, 클릭 시 상세 페이지로 이동하도록 URL 설정.
  • 질문이 없을 경우 "No polls are available." 메시지 출력.

 

5. 강의 주요 내용 정리

  1. Django의 뷰(View) 개념

    • 클라이언트 요청(Request)을 받아 데이터베이스에서 정보를 가져오고, 이를 템플릿에 전달해 응답(Response)으로 반환하는 역할.
    • HttpResponse()로 직접 문자열을 반환할 수도 있지만, 일반적으로 render()를 사용해 템플릿을 렌더링함.
  2. URL과 뷰 연결

    • urlpatterns에 경로를 지정하고 각 URL과 뷰를 매칭시킴.
    • path("<int:question_id>/", views.detail, name="detail")와 같이 동적 경로를 사용하여 특정 데이터를 조회 가능.
  3. 템플릿을 활용한 데이터 출력

    • context를 사용해 뷰에서 가져온 데이터를 템플릿에 전달.
    • 템플릿에서는 {% for question in latest_question_list %}와 같은 문법을 사용해 데이터를 반복 출력 가능.
  4. 에러 처리 및 get_object_or_404 활용

    • get_object_or_404(Question, pk=question_id)를 사용하여 데이터가 없을 경우 404 에러 발생.
    • 직접 try-except를 사용하여 에러 처리를 할 수도 있지만 get_object_or_404를 이용하면 더 간결하게 처리 가능.
  5. URL 하드코딩 방지

    • <a href="{% url 'polls:detail' question.id %}"> 방식으로 URL을 설정하면, URL 패턴이 변경되어도 템플릿을 수정할 필요가 없음.

 

 

 

 

 

 

 

 

 

 

7.django form 사용, 데이터 받아오는 법, generic view 사용

첫 번째 장고 앱 작성하기, part 4

 

1. URL 설정 (urls.py)

Django 프로젝트의 polls 앱에서 URL 패턴을 정의하는 코드입니다. urlpatterns 리스트를 사용하여 요청된 URL과 처리할 뷰 함수를 연결합니다.

from django.urls import path
from . import views


app_name="polls"

urlpatterns = [    
    # ex: http://127.0.0.1:8000/polls/
    #path("", views.index, name="index"),
    
    # ex: http://127.0.0.1:8000/polls/1/
    #path("<int:question_id>/", views.detail, name="detail"),
    
    # ex: http://127.0.0.1:8000/polls/1/results/
    #path("<int:question_id>/results/", views.results, name="results"),
    
    # ex: http://127.0.0.1:8000/polls/1/vote/
    #path("<int:question_id>/vote/", views.vote, name="vote"),   


    path("", views.IndexView.as_view(), name="index"),
    path("<int:pk>/", views.DetailView.as_view(), name="detail"),
    path("<int:pk>/results/", views.ResultsView.as_view(), name="results"),
    path("<int:question_id>/vote/", views.vote, name="vote"),
]

 

 

2. 뷰 함수 (views.py)

기본적인 뷰 함수들을 정의합니다.

from django.shortcuts import render , get_object_or_404
from .models import Question , Choice
# Create your views here.
from django.http import HttpResponse, Http404 , HttpResponseRedirect
from django.template import loader
from django.urls import reverse
from django.views import generic


# 메인 페이지 (index)
def index(request):
    # 1
    # return HttpResponse("Hello,world!")

    # 2
    # last_question_list = Question.objects.order_by('-pub_date')[:5]
    # output = ', '.join([q.question_text for q in last_question_list])
    # return HttpResponse(output)

    # 3
    # latest_question_list = Question.objects.order_by("-pub_date")[:5]
    # template = loader.get_template("polls/index.html")
    # context = {
    #     "latest_question_list": latest_question_list,
    # }
    # return HttpResponse(template.render(context, request))

    # 4
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {"latest_question_list": latest_question_list}
    return render(request, "polls/index.html" , context)


class IndexView(generic.ListView):
    template_name = "polls/index.html"
    context_object_name = "latest_question_list"

    def get_queryset(self):
        """마지막으로 게시된 5개의 질문을 반환합니다."""
        return Question.objects.order_by("-pub_date")[:5]




# 상세 페이지 (detail)
def detail(request, question_id):
    #1
    # try:
    #     question = Question.objects.get(pk=question_id)
    # except Question.DoesNotExist:
    #   raise Http404("Question does not exist")    
    # return render(request, "polls/detail.html", {"question" :question} )

    #2    
    question = get_object_or_404(Question,pk=question_id)    
    return render(request, "polls/detail.html", {"question": question})


class DetailView(generic.DetailView):
    model = Question
    template_name = "polls/detail.html"



# 결과 페이지 (results)
def results(request, question_id):
    response = "You're looking at the results of question %s."
    return HttpResponse(response % question_id)


class ResultsView(generic.DetailView):
    model = Question
    template_name = "polls/results.html"



# 투표 페이지 (vote)
def vote(request, question_id):
    #return HttpResponse("You're voting on question %s." % question_id)

    question = get_object_or_404(Question, pk=question_id)
    try:
        selected_choice = question.choice_set.get(pk=request.POST["choice"])
    except (KeyError, Choice.DoesNotExist):    
        return render(
            request,
            "polls/detail.html",
            {
                "question": question,
                "error_message": "You didn't select a choice.",
            },
        )
    else:
        selected_choice.votes += 1
        selected_choice.save()
        # 게시물 데이터를 성공적으로 처리 한 후에는 항상 HttpResponseRedirect 로  results 페이지로 이동하므로서
        # 사용자가 뒤로 버튼및 새로고침시 데이터가 두 번 게시되는 것을 방지합니다.
        return HttpResponseRedirect(reverse("polls:results", args=(question.id,)))



# 설문조사 결과 페이지
def results(reqest, question_id):
    question =get_object_or_404(Question, pk=question_id)
    return render(reqest, "polls/results.html", {"question": question})

 

render와 reverse 함수 설명

  • render(request, template_name, context)
    • 템플릿 파일을 렌더링하여 HttpResponse 객체를 반환합니다.
    • context 딕셔너리를 전달하면 템플릿에서 해당 데이터를 사용할 수 있습니다.
  • reverse(viewname, args=(), kwargs={})
    • URL 패턴의 이름을 사용하여 URL을 동적으로 생성합니다.
    • 예제: reverse("polls:results", args=(question.id,))
      • "polls:results"는 polls 앱의 results URL 패턴을 가리킵니다.
      • args=(question.id,)는 URL에서 <int:question_id>/results/ 부분의 question_id 값을 전달하는 역할을 합니다.
    •  

3. 제너릭 뷰 (views.py)

Django의 제너릭 뷰를 활용하여 간결한 코드로 뷰를 작성할 수 있습니다.

from django.views import generic
from .models import Question

class IndexView(generic.ListView):
    template_name = "polls/index.html"
    context_object_name = "latest_question_list"

    def get_queryset(self):
        return Question.objects.order_by("-pub_date")[:5]

class DetailView(generic.DetailView):
    model = Question
    template_name = "polls/detail.html"

class ResultsView(generic.DetailView):
    model = Question
    template_name = "polls/results.html"

 

 

4. 투표 폼 템플릿 (detail.html)

사용자가 선택지를 고를 수 있도록 폼을 생성합니다.

<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
<fieldset>
    <legend><h1>{{ question.question_text }}</h1></legend>
    {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
    {% for choice in question.choice_set.all %}
        <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
        <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
    {% endfor %}
</fieldset>
<input type="submit" value="Vote">
</form>

 

 

5. 결과 페이지 템플릿 (results.html)

투표 결과를 출력하는 HTML 페이지입니다.

<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>
<a href="{% url 'polls:detail' question.id %}">투표 다시하기?</a>

 

 

6. 강의 요약

  • 뷰 함수 활용: 기본적인 index, detail, results, vote 함수 작성.
  • 제너릭 뷰 활용: ListView와 DetailView를 사용하여 코드의 간결성을 유지.
  • 폼을 활용한 데이터 전달: 사용자가 폼을 제출하면 POST 방식으로 데이터를 서버에 전달함.
  • CSRF 토큰 사용: 보안 강화를 위해 폼 내부에 {% csrf_token %}을 추가.
  • 뷰에서 데이터 처리: request.POST를 통해 사용자가 제출한 데이터를 받아와 처리.
  • 예외 처리: 선택지가 없는 경우 예외 처리를 통해 다시 상세 페이지로 리다이렉트.
  • 템플릿에서 pluralize 필터 사용: 투표 수에 따라 단/복수를 자동으로 조정.
  • reverse 함수 활용: URL을 동적으로 생성하여 유지보수를 용이하게 만듦.

이 강의를 통해 Django의 기본적인 URL 매핑, 뷰 함수 작성, 제너릭 뷰 활용, 폼 데이터 전송 및 결과 페이지 렌더링에 대해 학습하였습니다.

 

 

 

 

 

8.django test 사용, test case 작성, unit test

첫 번째 장고 앱 작성하기, part 5

 

Django 테스트 코드 정리

1. 테스트 코드의 필요성

테스트 코드는 코드가 예상한 결과를 반환하는지 확인하는 용도로 사용된다. 특히, 코드 수정 및 유지보수 과정에서 예기치 않은 오류를 방지하는 중요한 역할을 한다. 테스트 코드를 작성하는 이유는 다음과 같다:

  1. 시간 절약: 기능이 많아질수록 수동 테스트는 비효율적이며, 자동화된 테스트 코드가 필요하다.
  2. 기능 명확화: 테스트를 작성하면 기능이 명확하게 정의되므로, 발생할 수 있는 오류를 사전에 방지할 수 있다.
  3. 코드의 신뢰성 증가: 테스트가 없는 코드는 불완전한 것으로 간주될 수 있으며, 테스트를 통해 코드의 안정성을 확보할 수 있다.
  4. 협업 효율성 증대: 여러 개발자가 공동으로 작업할 때, 코드 변경 후에도 기존 기능이 정상 작동하는지 검증할 수 있다.

2. Django에서 테스트 코드 작성

2.1 테스트 환경 설정

Django에서 테스트를 수행하기 위해서는 TestCase 클래스를 상속받아 테스트 케이스를 작성해야 한다.

from django.test import TestCase
from django.utils import timezone
from .models import Question
import datetime

2.2 단위 테스트 (Unit Test)

2.2.1 was_published_recently() 테스트

class QuestionModelTests(TestCase):
    def test_was_published_recently_with_future_question(self):
        """
        미래의 날짜를 가진 질문이 최근에 발행된 것으로 간주되지 않는지 확인한다.
        """
        time = timezone.now() + datetime.timedelta(days=30)
        future_question = Question(pub_date=time)
        self.assertIs(future_question.was_published_recently(), False)

설명:

  • 현재 날짜보다 30일 후의 날짜를 가진 Question 객체를 생성.
  • was_published_recently() 함수의 반환값이 False인지 검증.

2.2.2 create_question() 헬퍼 함수

def create_question(question_text, days):
    """
    질문을 생성하며, days 값에 따라 발행일(pub_date)을 조정한다.
    양수: 미래 날짜, 음수: 과거 날짜
    """
    time = timezone.now() + datetime.timedelta(days=days)
    return Question.objects.create(question_text=question_text, pub_date=time)

3. 뷰(View) 테스트

3.1 인덱스 페이지 테스트

3.1.1 데이터가 없을 때

class QuestionIndexViewTests(TestCase):
    def test_no_questions(self):
        """
        데이터가 없는 경우 적절한 메시지가 출력되는지 확인.
        """
        response = self.client.get(reverse("polls:index"))
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "No polls are available.")
        self.assertQuerySetEqual(response.context["latest_question_list"], [])

3.1.2 과거 데이터가 있는 경우

    def test_past_question(self):
        """
        과거에 생성된 질문이 인덱스 페이지에 정상적으로 표시되는지 확인.
        """
        question = create_question(question_text="Past question.", days=-30)
        response = self.client.get(reverse("polls:index"))
        self.assertQuerySetEqual(
            response.context["latest_question_list"],
            [question],
        )

3.1.3 미래 데이터가 있는 경우

    def test_future_question(self):
        """
        미래에 생성된 질문은 인덱스 페이지에 표시되지 않아야 한다.
        """
        create_question(question_text="Future question.", days=30)
        response = self.client.get(reverse("polls:index"))
        self.assertContains(response, "No polls are available.")
        self.assertQuerySetEqual(response.context["latest_question_list"], [])

3.1.4 과거 및 미래 데이터가 함께 존재하는 경우

    def test_future_question_and_past_question(self):
        """
        과거와 미래의 질문이 함께 존재할 때, 과거 질문만 표시되는지 확인.
        """
        question = create_question(question_text="Past question.", days=-30)
        create_question(question_text="Future question.", days=30)
        response = self.client.get(reverse("polls:index"))
        self.assertQuerySetEqual(
            response.context["latest_question_list"],
            [question],
        )

3.1.5 여러 개의 과거 데이터가 있는 경우

    def test_two_past_questions(self):
        """
        두 개의 과거 질문이 존재할 때, 인덱스 페이지에 정상적으로 표시되는지 확인.
        """
        question1 = create_question(question_text="Past question 1.", days=-30)
        question2 = create_question(question_text="Past question 2.", days=-5)
        response = self.client.get(reverse("polls:index"))
        self.assertQuerySetEqual(
            response.context["latest_question_list"],
            [question2, question1],
        )

4. 결론

Django의 테스트 코드를 작성하는 것은 코드의 신뢰성을 높이고 유지보수를 용이하게 만든다. 특히, 자동화된 테스트를 통해 개발 및 협업 과정에서 발생할 수 있는 오류를 사전에 방지할 수 있다. 위의 테스트 코드는 polls 앱의 주요 기능이 정상적으로 동작하는지 확인하는 예제이며, 이를 기반으로 다양한 테스트 케이스를 추가하여 프로젝트의 안정성을 보장할 수 있다.

 

 

 

 

 

 

 

 

 

9.css, static file,들의 django css 연결, static 파일

 

첫 번째 장고 앱 작성하기, part 6

 

 

1. 정적 파일이란?

정적 파일(static files)이란 HTML, CSS, JavaScript와 같은 클라이언트 측에서 실행되는 파일을 의미합니다. Django에서는 이러한 정적 파일을 별도의 디렉토리에 저장하고 관리할 수 있도록 지원합니다.

 

2. 정적 파일의 기본 개념

  • Django는 정적 파일(static files)을 별도로 분리하여 관리할 수 있는 기능을 제공함.
  • 기본적으로 static 디렉토리를 생성하여 관리.
  • 규모가 커지면 별도의 저장소(AWS S3 등)에 정적 파일을 저장할 수도 있음.

 

3. Django에서 정적 파일 설정

(1) static 디렉토리 생성

앱 내부에 static 디렉토리를 생성하여 CSS, JavaScript, 이미지 파일 등을 저장합니다.

/myapp/
    /static/
        /myapp/
            /css/
            /js/
            /images/

Django는 정적 파일을 앱 내부 static 디렉토리에 저장하는 것을 권장하며, 네임스페이스를 활용하여 다른 앱과의 충돌을 방지할 수 있습니다.

(2) settings.py 설정

STATIC_URL = '/static/'
STATICFILES_DIRS = [
    BASE_DIR / "static"
]

(3) CSS 파일 작성 및 적용

1) static/myapp/css/style.css 파일 생성 후 작성

body {
    background-color: #f0f0f0;
    font-family: Arial, sans-serif;
}

2) HTML 파일에서 정적 파일 로드

{% load static %}를 사용하여 CSS 파일을 불러옵니다.

{% load static %}
<html>
<head>
    <link rel="stylesheet" type="text/css" href="{% static 'myapp/css/style.css' %}">
</head>
<body>
    <h1>정적 파일 적용 완료</h1>
</body>
</html>

(4) 이미지 파일 적용 방법

이미지 파일을 정적 디렉토리 내에 저장 후, CSS에서 불러와 사용할 수 있습니다.

background-image: url("../images/background.jpg");

또한 HTML에서도 {% static %}을 이용하여 이미지를 로드할 수 있습니다.

<img src="{% static 'myapp/images/logo.png' %}" alt="Logo">

 

4. 정적 파일의 로딩 및 확인

  1. 정적 파일을 작성 후 Django 서버를 실행합니다.
  2. 웹 페이지에서 정상적으로 CSS 및 이미지가 적용되었는지 확인합니다.

이렇게 정적 파일을 설정하면 Django 프로젝트에서 효율적으로 CSS와 이미지 파일을 관리할 수 있습니다.

다음 강의에서는 Django Admin 기능을 좀 더 세부적으로 다룰 예정입니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

10.django customize the admin

 

첫 번째 장고 앱 작성하기, part 7

 

1. Django Admin 커스터마이징 개요

Django의 기본 Admin 페이지를 프로젝트에 맞게 커스터마이징하면 보다 편리한 관리가 가능합니다. Admin을 커스터마이징하기 위해서는 admin.ModelAdmin을 상속받아 설정을 변경할 수 있습니다.

 

2. ModelAdmin을 활용한 커스터마이징

2.1 QuestionAdmin 설정

from django.contrib import admin
from .models import Question, Choice

class ChoiceInline(admin.TabularInline):
    model = Choice
    extra = 3

class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        ("질문 정보", {'fields': ['question_text']}),  # 질문 입력 필드
        ("날짜 정보", {'fields': ['pub_date'], 'classes': ['collapse']}),  # 날짜 정보 입력 필드 (접을 수 있음)
    ]
    
    inlines = [ChoiceInline]  # Choice 모델을 같은 페이지에서 관리 가능
    list_display = ('question_text', 'pub_date', 'was_published_recently')  # 목록에서 표시할 필드 지정
    list_filter = ['pub_date']  # 날짜 기준 필터 추가
    search_fields = ['question_text']  # 검색 가능하도록 설정

admin.site.register(Question, QuestionAdmin)

 

2.2 Question 모델 설정

from django.db import models
from django.utils import timezone
import datetime

class Question(models.Model):
    question_text = models.CharField(max_length=200, verbose_name="질문 내용")
    pub_date = models.DateTimeField('게시 날짜')

    def __str__(self):
        return self.question_text
    
    @admin.display(
        boolean=True,
        ordering="pub_date",
        description="최근 게시 여부",
    )
    def was_published_recently(self):
        now = timezone.now()
        return now - datetime.timedelta(days=1) <= self.pub_date <= now

 

3. Admin 템플릿 커스터마이징

기본 Django Admin 인터페이스의 base_site.html을 변경하여 사이트의 제목 및 스타일을 커스터마이징할 수 있습니다.

1)설정 파일 (mysite/settings.py를 기억하세요)을 열고 DIRS 옵션을 TEMPLATES 설정에 추가\

2)가상환경(env)/Lib/django/contrib/admin/templates

 

3.1 base_site.html 변경

{% extends "admin/base.html" %}

{% block title %}{% if subtitle %}{{ subtitle }} | {% endif %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %}

{% block branding %}
<div id="site-name">
    <a href="{% url 'admin:index' %}">
       설문조사 관리
    </a>
</div>
{% if user.is_anonymous %}
  {% include "admin/color_theme_toggle.html" %}
{% endif %}
{% endblock %}

{% block nav-global %}{% endblock %}

 

 

 

 

4. 주요 커스터마이징 요소

  • fieldsets: 입력 필드를 그룹화하여 관리 가능
  • inlines: 연결된 모델을 같은 페이지에서 관리 가능
  • list_display: 관리자 목록 페이지에서 보일 필드 지정
  • list_filter: 특정 필드를 기준으로 필터 기능 추가
  • search_fields: 검색 기능 추가
  • admin.display: 커스텀 필드 설정 가능 (정렬, 불리언 값 아이콘 표시 등)

 

5. 추가 커스터마이징 사항

  1. 탭 형식의 인라인 적용: admin.TabularInline 사용하여 테이블 형식으로 정리 가능
  2. 정렬 기준 설정: ordering 옵션으로 정렬 기준 지정 가능
  3. 아이콘으로 불리언 값 표시: boolean=True 설정 시 True/False가 아이콘으로 표시됨
  4. Admin 필드명 한글화: description을 활용하여 관리 페이지에서 필드명 변경 가능

 

6. 정리

Django Admin을 커스터마이징하면 더욱 효율적으로 데이터를 관리할 수 있습니다. 필요에 따라 ModelAdmin을 활용하여 필드, 필터, 검색 기능을 추가하고, Admin 템플릿을 변경하여 사이트의 브랜딩을 반영할 수 있습니다.

 

 

 

 

 

 

 

 

about author

PHRASE

Level 60  라이트

내가 할 말을 사돈이 한다 , 내가 해야 할 말을 남이 가로채어 한다. / 내가 원망해야 할 일인데 남이 도리어 나를 원망한다. / 내가 하고 싶었던 말을 남이 대신 해 주어 잘 되었다.

댓글 ( 1)

댓글 남기기

작성