환경
- Ubuntu Server 22.04
- VSCode Insider
- Remote SSH Extension
- Python 3.10 venv
- Django 5.1.1
- SQLite 3.37.2
준비
# env 생성, 활성화
mkdir devcourse_django && cd devcourse_django
python -m venv django_env
source django_env/bin/activate
### 프로젝트 폴더를 옮겼다면
# vi django_env/bin/activate에서 virtual_env 경로를 바꿔줘야함 😫
# vi django_env/bin/pip 의 shebang 경로 (#!)도 바꿔준다
### python 명령 실행 시 커맨드라인 앞에 (venv_name) 붙었는지 확인 ###
# 장고, sqlite3 설치
pip install django
sudo apt install sqlite3
python -m django --version
# 프로젝트 init
django-admin startproject test_proj
# 프로젝트 트리 확인
sudo apt install tree
tree -d -L 3 ./
# dev server 실행
python manage.py runserver
# app 생성 : appname = polls
python manage.py startapp appname
# 관리자: url/admin 에서 관리 가능
python manage.py createsuperuser
실행
test_proj/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('polls/', include('polls.urls')),
path('admin/', admin.site.urls),
]
# polls에 urls.py 생성
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
]
polls/views.py
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello polls") # localhost:8000/polls/
def some_url(request):
return HttpResponse("hello someurl") # localhost:8000/polls/some_url
polls/models.py
# 모델 작성 부분인듯
from django.db import models
from django.utils import timezone
import datetime
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
# score = models.FloatField(default=0)
# is_something = models.BooleanField(default=False)
# data = models.JSONField(default=dict)
# 모델 메소드 (어제 글)
def is_recent(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
# 관리자 페이지에서 표시될 레코드 이름
def __str__(self):
return f'{'NEW!' if self.is_recent() else ''} {self.question_text}'
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
# 'migration' 필요
# migration 준비: test_proj의 settings.py에 앱 등록
test_proj/settings.py
# added polls app for migration
INSTALLED_APPS = [
'polls.apps.PollsConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
Migration
# Migration: Schema 생성으로 이해하면 될듯
# 해당 앱 아래에 migrations 폴더 생성됨
# 모델에 필드를 추가하면 다시 실행해야됨!
python manage.py makemigrations polls
# 체크: foreign 키에 인덱싱 됨
python manage.py sqlmigrate polls 0001
# Migrate (여기서 테이블 생성하는듯)
python manage.py migrate
# DB에서 확인 (sqlite 인터랙티브 세션)
sqlite3 db.sqlite3
# migrations rev 확인
.tables
# schema 확인
.schema polls_question
# 이전 schema로 (0001번) 다시 migrate 가능
# migrations 에서 0002 삭제하고 모델 코드 수정
python manage.py migrate polls 0001
# polls의 admin.py
from django.contrib import admin
from .models import *
admin.site.register(Question)
admin.site.register(Choice)
# 관리자 페이지에 모델 등록 된 것 확인
Django Shell 에서 테스트 하기
### shell에서 하는 방법: 메모리에 올려놓고 하는 장점이 있는...듯?
python manage.py shell
# shell에서
from polls.models import *
choice = Choice.objects.all()[0]
choice.id
choice.choice_text
choice.question # foreign key
question = Question.objects.all()[0]
question.choice_set.all() # 조인같은 기능인듯
# 관리자 페이지에서 레코드 추가하는 것과 같은 효과
from django.utils import timezone
q = Question(question_text='are you well')
q.pub_date = timezone.now() # 모델에 auto_now_add 설정하면 필요 없다
q.save()
# 커스텀 메소드 체크
q.is_recent()
# foreign키의 레코드 바로 만들기
q.choice_set.create(choice_text='temp_text')
# 반대 방향도 가능: 이 경우 return 타입은 쿼리셋이 아니다 (count() 등 쓸 수 없음)
ch = Choice(choice_text='temp_choice', question=q)
ch.save()
## 레코드 지우기
ch.delete()
# foreign키 세트 전부 삭제도 가능
q.choice_set.delete()
## 쿼리
Question.objects.get(id=1)
Question.objects.get(question_text__startswith='vacat') # 특이한 syntax
Question.objects.get(pub_date__second=59)
# 결과가 여러개일때는
Question.objects.filter(pub_date__year=2024) # .count() 등 쿼리 셋 공통 메소드
# 포함 쿼리
Question.objects.filter(question_text__contains='vacation')
# 비교
Question.objects.filter(votes__gt=0) # 0보다 큰
# regex
Question.objects.filter(question_text__regex=r'^vacation .*location+')
# 제외
Question.objects.exclude(blabla__lookup='')
# chain도 가능하다
Question.objects.filter(blabla__lookup='').filter(blabla__lookup='')
# lookup을 체인하는 것도 가능하다
Choice.objects.filter(question__question_text__contains='ideal')
# query eval
print(Question.objects.filter(pub_date__year=2024).query)
## other query set manipulation
# 업데이트
Question.objects.filter(votes__gt=0).update(votes=10)
MISC
python manage.py shell
# datetime이 아니라 timezone사용해야 함!
from django.utils import timezone
timezone.now()
# for time operations
import datetime
datetime.timedelta(days=1, years=1...)
# django sqlite reference
# https://docs.djangoproject.com/en/5.1/ref/models/querysets
'W | eb' 카테고리의 다른 글
Django CRUD: API (0) | 2024.10.09 |
---|---|
Django CRUD: Serialize (0) | 2024.10.08 |
Django CRUD: Admin (1) | 2024.10.08 |
Django Template (0) | 2024.10.08 |
HTML (0) | 2024.10.02 |