class Question(models.Model):
    ....
    # was_published_recently : 직접 추가한 메소드. 게시한 지 하루 이상 됐는지 확인
    # timedelta는 날짜 호은 시간 사이의 간격을 나타내기 위해 사용되는 함수
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

Django

Django란 웹사이트를 개발할 수 있도록 돕는 구성요소로 이루어진 파이썬 기반 웹 애플리케이션 프레임워크이다.


설치 및 project 생성

터미널

pip install django # 파이썬 환경에서 설치
conda install djangto # 아나콘다 환경에서 설치

django-admin startproject mysite # mysite라는 새로운 Django 프로젝트 생성하기
python manage.py runserver # 생성한 프로젝트를 서버에서 실행하기
python manage.py startapp appname # appname 앱 생성하기

파이썬 코드

App 생성

터미널

python manage.py startapp appname # appname 앱 생성하기

파이썬

# 앱 생성
# 1. python manage.py startapp appname
# 2. 앱의 url 설정
# 2-1 프로젝트 폴더 아래에 있는 urls.py에 path() 등록
# 2-2 앱 폴더 아래에 urls.py 생성 및 코드 작성
# 2-3 앱 폴더 아래에 있는 views.py 설정
# 3. 서버 url/앱 이름 으로 접속 (e.g. 127.0.0.1:8000/polls)

# 2 과정
# 2-1
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path("admin/", admin.site.urls), # admin/(첫번째 인자) 이라는 url이 들어오면 admin.site.urls(두번째 인자)로 연결해라
    path("polls/", include('polls.urls'))
]
# 2-2
from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world.")
# 2-3
from django.urls import path
from . import views

urlpatterns = [
    path('',views.index, name='index')
]

URL 설정

polls/views.py
def some_url(request):
    return HttpResponse("Hello World!")

# polls/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('some_url',views.some_url)
]

 

모델 만들기

# 사용자 정의 앱의 models의 마이그레이션
# 프로젝트 폴더 아래 settings.py의 INSTALLED_APPS에 먼저 등록이 필요하다.
# 앱 폴더 아래 apps.py에 config를 INSTALLED_APPS 리스트의 최상단에 등록!
# INSTALLED_APPS = [
#    'polls.apps.PollsConfig'
#    ...
#]
python manage.py makemigrations polls # migration 파일 생성하기
python manage.py sqlmigrate polls 0001 # migration으로 실행될 SQL 문장 살펴보기
python manage.py migrate polls 0001 # 마이그레이션을 0001버전으로 다시 롤백하기
python manage.py migrate # migration 실행하기
# 질문과 선택지 테이블

class Question(models.Model):
    question_text = models.CharField(max_length=200) # 질문
    pub_date = models.DateTimeField('date published') # 질문을 만든 날
    pub_date = models.DateTimeField(auto_now_add=True) # 질문이 처음 생길 때 pub_date가 생김 
    
class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE) # Question 테이블에서 받아온 외래키
    choice_text = models.CharField(max_length=200) # 선택지
    votes = models.IntegerField(default=0) # 투표수

 

관리자 게정 생성하고 접속하기

admin : 시스템 관리자들이 데이터를 수정하거나 추가하는 페이지(127.0.0.1:8000/admin)
admin 페이지에서 쉽게 CRUD가 가능하기에 편리하다!

python manage.py createsuperuser # Django Admin 계정 생성하기
# polls/admin.py
# admin에 model 추가
from django.contrib import admin
from .models import *

#Register your models here
admin.site.register(Question)
admin.site.register(Choice)

#polls/models.py
class Question(models.Model):
    ....
    def __str__(self):
        return f'제목: {self.question_text}, 날짜: {self.pub_date}' # 페이지에서 어떻게 표현될지 정의

admin 화면

Django Shell 사용하기

python manage.py shell # 쉘모드 사용하기

# models.py 파일에 정의된 모든 모델 가져오기
>>> from polls.models import *
>>> Question

# 테이블에서 모든 오브젝트 가져오기
>>> Question.objects.all()

# Choice 오브젝트의 첫번째 개체 가져오기
>>> choice = Choice.objects.all()[0]
>>> choice.id
>>> choice.choice_text
>>> choice.votes

#첫번째 Choice와 연결된 Question 가져오기
>>> choice.question
>>> choice.question.pub_date
>>> choice.question.id # 외래키

#해당 Question과 연결되어 있는 모든 Choice 가져오기(Question은 Choice와 연결되어 있지 않기에 _set이 필요)
>>> question.choice_set.all()
  • 현재 시간 구하기
# Django Shell 환경
# datetime 활용
>>> from datetime import datetime
>>> datetime.now()

# timezone 활용(Django에서는 이 방법 활용)
>>> from django.utils import timezone
>>> timezone.now()
  • 레코드 생성, 삭제 및 수정
# 모델 import는 필수!
>>> from polls.models import *

#"커피 vs 녹차" 라는 내용의 새로운 Question 오브젝트를 생성하고 'q1'이라는 변수에 저장하기
>>> q1 = Question(question_text = "커피 vs 녹차")

#tiemzone을 활용하여 새로운 오브젝트 'q1'의 생성시각을 설정하기
>>> from django.utils import timezone
>>> q1.pub_date = timezone.now()

#새로운 Question 오브젝트 'q1'을 데이터베이스에 저장하기
>>> q1.save()

>>> q3 = Question(question_text = "abc")
>>> q3.pub_date = timezone.now()
>>> q3.save()

#create() 메서드를 활용하여 q3와 연결된 새로운 Choice 오브젝트를 생성하고, choice_text 필드에 값을 넣어주기
>>> q3.choice_set.create(choice_text = "b")

#새로운 Choice 오브젝트를 생성하고 question 필드에 q3 값을 넣어 연결하기
>>> choice_c = Choice(choice_text='c', question=q3)

#새로운 Choice 오브젝트를 데이터베이스에 저장하기
>>> choice_c.save()

#Question 오브젝트 중 가장 마지막으로 만들어진 것을 가져오기
>>> q = Question.objects.last()

#해당 오브젝트의 question_text에 새로운 내용을 더해 수정하기
>>> q.question_text = q.question_text + '???'

#해당 오브젝트의 question_text를 업데이트(수정)
>>> q.question_text = '업데이트 할 내용'

#Choice 오브젝트 중 가장 마지막으로 만들어진 것을 가져오기
>>> choice = Question.objects.last()

#해당 오브젝트에 연결된 Question을 통해서 choice set을 가져오기
>>> choice.queston.choice_set.all()

#해당 오브젝트를 삭제하기
>>> choice.delete()
  • 모델 필터링
    get() 메소드는 오브젝트 하나를, filter() 메소드는 여러 오브젝트를 포함하는 쿼리셋을 반환!
>>> from polls.models import *

#get() 메서드를 사용하여 조건에 해당하는 오브젝트 필터링
>>> Question.objects.get(id=1)
>>> q = Question.objects.get(question_text__startswith='휴가를')
>>> Question.objects.get(pub_date__year=2023) #get으로 여러가지 오브젝트를 가져오려고 한다면 에러발생
polls.models.Question.MultipleObjectsReturned: get() returned more than one Question

#filter() 메서드를 사용하여 조건에 해당하는 오브젝트 필터링
>>> Question.objects.filter(pub_date__year=2023)
<QuerySet [<Question: 제목: 휴가를 어디서 보내고 싶으세요?, 날짜: 2023-02-05 18:52:59+00:00>, <Question: 제목: 가장 좋아하는 디저트는?, 날짜: 2023-02-05 18:53:27+00:00>, ...]>
>>> Question.objects.filter(pub_date__year=2023).count()

#쿼리셋의 SQL 쿼리
>>> Question.objects.filter(pub_date__year=2023).query
>>> print(Question.objects.filter(pub_date__year=2023).query)
SELECT "polls_question"."id", "polls_question"."question_text", "polls_question"."pub_date" FROM "polls_question" WHERE "polls_question"."pub_date" BETWEEN 2023-01-01 00:00:00 AND 2023-12-31 23:59:59.999999

>>> Question.objects.filter(question_text__startswith='휴가를').query
>>> print(Question.objects.filter(question_text__startswith='휴가를').query)
SELECT "polls_question"."id", "polls_question"."question_text", "polls_question"."pub_date" FROM "polls_question" WHERE "polls_question"."question_text" LIKE 휴가를% ESCAPE '\'

>>> q = Question.objects.get(pk=1)
>>> q.choice_set.all()
>>> print(q.choice_set.all().query)
SELECT "polls_choice"."id", "polls_choice"."question_id", "polls_choice"."choice_text", "polls_choice"."votes" FROM "polls_choice" WHERE "polls_choice"."question_id" = 1

#startswith 연산자를 활용한 오브젝트 필터링
>>> q = Question.objects.filter(question_text__startswith='휴가를')
>>> q2 = Question.objects.filter(pub_date__year=2023)

#contains 연산자를 활용한 오브젝트 필터링(알파벳 대소문자 구분 가능)
>>> Question.objects.filter(question_text__contains='휴가')

#해당 쿼리셋에 대한 SQL 쿼리 생성
>>> Choice.objects.filter(votes__gt=0).query
>>> print(Choice.objects.filter(votes__gt=0).query)
SELECT "polls_choice"."id", "polls_choice"."question_id", "polls_choice"."choice_text", "polls_choice"."votes" FROM "polls_choice" WHERE "polls_choice"."votes" > 0

#정규표현식을 활용하여 조건에 해당하는 오브젝트들 필터링
>>> Question.objects.filter(question_text__regex=r'^휴가.*어디')
>>> print(Question.objects.filter(question_text__regex=r'^휴가.*어디').query)
SELECT "polls_question"."id", "polls_question"."question_text", "polls_question"."pub_date", "polls_question"."owner_id" FROM "polls_question" WHERE "polls_question"."question_text" REGEXP ^휴가.*어디
  • 모델 관계 기반 필터링
#Question의 question_text 필드 값이 '휴가'로 시작하는 모든 Choice 오브젝트를 필터링하기
>>> Choice.objects.filter(question__question_text__startswith='휴가')

#exclude() 메서드를 사용하여 question_text 필드 값이 '휴가'로 시작하는 모든 Choice 오브젝트를 제외하고 필터링하기
>>> Question.objects.exclude(question_text__startswith='휴가')
  • 모델 메소드 추가
    models.py에 정의한 오브젝트에 직접 메소드를 추가할 수 있다.

 

 

파일설명

  • urls.py : url의 패턴이 정의하는 파일.
  • models.py : DB를 테이블 별로 읽고 하나의 테이블에 저장되어 있는 값을 코드에서 읽어들일 수 있도록 도와줌.(ORM)
  • views.py : 뷰(view) 는 애플리케이션의 "로직"을 넣는 곳. 모델에서 정보를 받아와서 템플릿에 전달하는 역할.
                      models.py를 활용

다양한 모델 필드

  • models.CharField - 글자 수가 제한된 텍스트
  • models.TextField - 글자 수에 제한이 없는 긴 텍스트
  • models.DateTimeField - 날짜와 시간
  • models.ForeignKey - 다른 모델에 대한 링크
  • 그 외의 필드는 공식 문서 참조 : https://docs.djangoproject.com/en/5.0/ref/models/fields/

'데브코스 > Week 5' 카테고리의 다른 글

Week 5 - 5  (0) 2024.04.12
Week 5 - 4  (0) 2024.04.11
Week 5 - 3  (0) 2024.04.10
Week 5 - 2  (0) 2024.04.09

+ Recent posts