공부 계획
•
일주일 3일간 3, 3, 4개씩 수강
01.Django app
프로젝트 생성
•
cmd
Microsoft Windows [Version 10.0.19042.1288]
(c) Microsoft Corporation. All rights reserved.
C:\Users\jhe00>py -m django -- version
C:\Users\jhe00\AppData\Local\Programs\Python\Python39\python.exe: No module named django
C:\Users\jhe00>dir
C 드라이브의 볼륨에는 이름이 없습니다.
볼륨 일련 번호: 9AEB-3250
C:\Users\jhe00 디렉터리
2021-11-10 오후 02:25 <DIR> .
2021-11-10 오후 02:25 <DIR> ..
2021-07-27 오후 05:03 <DIR> .cache
2021-07-15 오전 02:42 <DIR> .config
2021-07-27 오후 05:03 <DIR> .eclipse
2021-06-22 오전 02:14 198 .gitconfig
2021-07-25 오후 05:24 <DIR> .idlerc
2021-10-02 오전 10:26 <DIR> .p2
2021-11-10 오후 02:19 123 .python_history
2021-07-07 오전 04:10 <DIR> .vscode
2021-02-04 오전 12:08 <DIR> 3D Objects
2021-07-22 오후 10:50 500,375,944 Anaconda3-2021.05-Windows-x86_64.exe
2021-08-18 오후 06:59 140 BullseyeCoverageError.txt
2021-11-02 오전 08:47 <DIR> Contacts
2021-03-09 오후 11:32 <DIR> Documents
2021-11-09 오후 08:23 <DIR> Downloads
2021-07-27 오후 04:43 <DIR> eclipse
2021-07-27 오후 05:03 <DIR> eclipse-workspace
2021-10-31 오후 09:49 <DIR> Favorites
2021-07-12 오후 05:25 2,373 HP PageWide Pro 452dw Printer.lnk
2021-10-31 오후 09:49 <DIR> Links
2021-11-02 오전 08:47 <DIR> Music
2021-11-10 오후 02:25 <DIR> myenv
2021-11-10 오후 02:23 <DIR> OneDrive
2021-07-12 오후 05:24 85,899,640 PW452_DW_Full_WebPack_38.9.1948.exe
2021-07-22 오후 10:44 383,473,400 pycharm-community-2021.1.3.exe
2021-07-22 오후 10:42 26,037,888 python-3.9.6-amd64.exe
2021-11-02 오전 08:47 <DIR> Saved Games
2021-11-02 오전 08:47 <DIR> Searches
2021-03-05 오전 12:16 <DIR> source
2021-11-02 오전 08:47 <DIR> Videos
8개 파일 995,789,706 바이트
23개 디렉터리 333,434,327,040 바이트 남음
C:\Users\jhe00>cd myenv
C:\Users\jhe00\myenv>dir
C 드라이브의 볼륨에는 이름이 없습니다.
볼륨 일련 번호: 9AEB-3250
C:\Users\jhe00\myenv 디렉터리
2021-11-10 오후 02:25 <DIR> .
2021-11-10 오후 02:25 <DIR> ..
2021-11-10 오후 02:25 42 .gitignore
2021-11-10 오후 02:25 <DIR> Lib
2021-11-10 오후 02:25 405 pyvenv.cfg
2021-11-10 오후 02:30 <DIR> Scripts
2개 파일 447 바이트
4개 디렉터리 333,433,520,128 바이트 남음
C:\Users\jhe00\myenv>cd Scripts
C:\Users\jhe00\myenv\Scripts>dir
C 드라이브의 볼륨에는 이름이 없습니다.
볼륨 일련 번호: 9AEB-3250
C:\Users\jhe00\myenv\Scripts 디렉터리
2021-11-10 오후 02:30 <DIR> .
2021-11-10 오후 02:30 <DIR> ..
2021-11-10 오후 02:25 2,143 activate
2021-11-10 오후 02:25 983 activate.bat
2021-11-10 오후 02:25 3,024 activate.fish
2021-11-10 오후 02:25 1,285 activate.nu
2021-11-10 오후 02:25 1,758 activate.ps1
2021-11-10 오후 02:25 1,193 activate_this.py
2021-11-10 오후 02:25 510 deactivate.bat
2021-11-10 오후 02:25 333 deactivate.nu
2021-11-10 오후 02:30 106,392 django-admin.exe
2021-11-10 오후 02:30 677 django-admin.py
2021-11-10 오후 02:25 106,350 pip-3.9.exe
2021-11-10 오후 02:25 106,350 pip.exe
2021-11-10 오후 02:25 106,350 pip3.9.exe
2021-11-10 오후 02:25 106,350 pip3.exe
2021-11-10 오후 02:25 24 pydoc.bat
2021-11-10 오후 02:25 543,464 python.exe
2021-11-10 오후 02:25 542,440 pythonw.exe
2021-11-10 오후 02:30 106,345 sqlformat.exe
2021-11-10 오후 02:25 106,337 wheel-3.9.exe
2021-11-10 오후 02:25 106,337 wheel.exe
2021-11-10 오후 02:25 106,337 wheel3.9.exe
2021-11-10 오후 02:25 106,337 wheel3.exe
2021-11-10 오후 02:30 <DIR> __pycache__
22개 파일 2,161,319 바이트
3개 디렉터리 333,433,315,328 바이트 남음
C:\Users\jhe00\myenv\Scripts>activate.bat
(myenv) C:\Users\jhe00\myenv\Scripts>py -m django --version
3.2.9
(myenv) C:\Users\jhe00\myenv\Scripts>cd ..
(myenv) C:\Users\jhe00\myenv>cd ..
(myenv) C:\Users\jhe00>dir
C 드라이브의 볼륨에는 이름이 없습니다.
볼륨 일련 번호: 9AEB-3250
C:\Users\jhe00 디렉터리
2021-11-10 오후 02:25 <DIR> .
2021-11-10 오후 02:25 <DIR> ..
2021-07-27 오후 05:03 <DIR> .cache
2021-07-15 오전 02:42 <DIR> .config
2021-07-27 오후 05:03 <DIR> .eclipse
2021-06-22 오전 02:14 198 .gitconfig
2021-07-25 오후 05:24 <DIR> .idlerc
2021-10-02 오전 10:26 <DIR> .p2
2021-11-10 오후 02:19 123 .python_history
2021-07-07 오전 04:10 <DIR> .vscode
2021-02-04 오전 12:08 <DIR> 3D Objects
2021-07-22 오후 10:50 500,375,944 Anaconda3-2021.05-Windows-x86_64.exe
2021-08-18 오후 06:59 140 BullseyeCoverageError.txt
2021-11-02 오전 08:47 <DIR> Contacts
2021-03-09 오후 11:32 <DIR> Documents
2021-11-09 오후 08:23 <DIR> Downloads
2021-07-27 오후 04:43 <DIR> eclipse
2021-07-27 오후 05:03 <DIR> eclipse-workspace
2021-10-31 오후 09:49 <DIR> Favorites
2021-07-12 오후 05:25 2,373 HP PageWide Pro 452dw Printer.lnk
2021-10-31 오후 09:49 <DIR> Links
2021-11-02 오전 08:47 <DIR> Music
2021-11-10 오후 02:25 <DIR> myenv
2021-11-10 오후 02:23 <DIR> OneDrive
2021-07-12 오후 05:24 85,899,640 PW452_DW_Full_WebPack_38.9.1948.exe
2021-07-22 오후 10:44 383,473,400 pycharm-community-2021.1.3.exe
2021-07-22 오후 10:42 26,037,888 python-3.9.6-amd64.exe
2021-11-02 오전 08:47 <DIR> Saved Games
2021-11-02 오전 08:47 <DIR> Searches
2021-03-05 오전 12:16 <DIR> source
2021-11-02 오전 08:47 <DIR> Videos
8개 파일 995,789,706 바이트
23개 디렉터리 333,433,147,392 바이트 남음
(myenv) C:\Users\jhe00>dir
C 드라이브의 볼륨에는 이름이 없습니다.
볼륨 일련 번호: 9AEB-3250
C:\Users\jhe00 디렉터리
2021-11-10 오후 02:25 <DIR> .
2021-11-10 오후 02:25 <DIR> ..
2021-07-27 오후 05:03 <DIR> .cache
2021-07-15 오전 02:42 <DIR> .config
2021-07-27 오후 05:03 <DIR> .eclipse
2021-06-22 오전 02:14 198 .gitconfig
2021-07-25 오후 05:24 <DIR> .idlerc
2021-10-02 오전 10:26 <DIR> .p2
2021-11-10 오후 02:19 123 .python_history
2021-07-07 오전 04:10 <DIR> .vscode
2021-02-04 오전 12:08 <DIR> 3D Objects
2021-07-22 오후 10:50 500,375,944 Anaconda3-2021.05-Windows-x86_64.exe
2021-08-18 오후 06:59 140 BullseyeCoverageError.txt
2021-11-02 오전 08:47 <DIR> Contacts
2021-03-09 오후 11:32 <DIR> Documents
2021-11-09 오후 08:23 <DIR> Downloads
2021-07-27 오후 04:43 <DIR> eclipse
2021-07-27 오후 05:03 <DIR> eclipse-workspace
2021-10-31 오후 09:49 <DIR> Favorites
2021-07-12 오후 05:25 2,373 HP PageWide Pro 452dw Printer.lnk
2021-10-31 오후 09:49 <DIR> Links
2021-11-02 오전 08:47 <DIR> Music
2021-11-10 오후 02:25 <DIR> myenv
2021-11-10 오후 02:23 <DIR> OneDrive
2021-07-12 오후 05:24 85,899,640 PW452_DW_Full_WebPack_38.9.1948.exe
2021-07-22 오후 10:44 383,473,400 pycharm-community-2021.1.3.exe
2021-07-22 오후 10:42 26,037,888 python-3.9.6-amd64.exe
2021-11-02 오전 08:47 <DIR> Saved Games
2021-11-02 오전 08:47 <DIR> Searches
2021-03-05 오전 12:16 <DIR> source
2021-11-02 오전 08:47 <DIR> Videos
8개 파일 995,789,706 바이트
23개 디렉터리 333,431,754,752 바이트 남음
(myenv) C:\Users\jhe00>cd Onedrive
(myenv) C:\Users\jhe00\OneDrive>django-admin startproject mysite
(myenv) C:\Users\jhe00\OneDrive>dir
C 드라이브의 볼륨에는 이름이 없습니다.
볼륨 일련 번호: 9AEB-3250
C:\Users\jhe00\OneDrive 디렉터리
2021-11-10 오후 02:43 <DIR> .
2021-11-10 오후 02:43 <DIR> ..
2021-03-09 오전 12:04 <DIR> appdata
2021-03-10 오후 06:57 <DIR> help
2021-03-10 오후 08:54 <DIR> licenses
2021-11-10 오후 02:43 <DIR> mysite
2021-03-10 오후 06:57 <DIR> sys
2021-03-09 오전 12:04 <DIR> uninstall
2021-11-10 오후 02:24 1,164 개인 중요 보관소.lnk
2021-11-06 오후 05:55 <DIR> 문서
2021-11-10 오후 02:32 <DIR> 바탕 화면
2021-11-06 오후 05:55 <DIR> 사진
2021-10-04 오후 01:36 0 프레젠테이션 1.pptx
2021-10-04 오후 01:36 0 프레젠테이션.pptx
3개 파일 1,164 바이트
11개 디렉터리 333,428,953,088 바이트 남음
(myenv) C:\Users\jhe00\OneDrive>cd mysite
(myenv) C:\Users\jhe00\OneDrive\mysite>dir
C 드라이브의 볼륨에는 이름이 없습니다.
볼륨 일련 번호: 9AEB-3250
C:\Users\jhe00\OneDrive\mysite 디렉터리
2021-11-10 오후 02:43 <DIR> .
2021-11-10 오후 02:43 <DIR> ..
2021-11-10 오후 02:43 684 manage.py
2021-11-10 오후 02:43 <DIR> mysite
1개 파일 684 바이트
3개 디렉터리 333,427,933,184 바이트 남음
(myenv) C:\Users\jhe00\OneDrive\mysite>
TypeScript
복사
•
Visual Code 설치 및 실행 → 편집기에 mysite 폴더 열기
-
서버 구동
•
서버 구동 및 실행 여부 확인
-
(myenv) C:\Users\jhe00\OneDrive\mysite>py manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
November 10, 2021 - 15:01:26
Django version 3.2.9, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/ => 주소창에 입력
Quit the server with CTRL-BREAK.
TypeScript
복사
-주소창에 http://127.0.0.1:8000/ 입력 후
⇒
주의
-위에서 구동한 개발 서버는 순수 Python으로 작성된 경량 웹 서버
⇒ ONLY 개발 목적으로만 사용!
-상용 ⇒ Nginx or Apache 사용
Django Cycle
•
Django Cycle
-
02-1. Database
django model
•
Database
-polls/models.py
from django.db import models
# Create your models here.
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_Date = models.DataTimeField('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)
Python
복사
-database ⇒ question, choice
-question : 질문, 생성 날짜 (발행일)
-choice : 선택지에 해당하는 질문, 표의 수
- cmd
py [manage.py](http://manage.py) makemigrate polls
py manage.py migrate
py [manage.py](http://manage.py) shell
from django utils import timezone
q = Question(question_text="What's new?", pub_date=timezone.now())
q.save()
q.id
q.question_text
q.pub_date
q.question_text = "What's up?"
q.save()
Question.objects.all()
Python
복사
-polls/models.py
import datetime
from django.db import models
from django.utils import timezone
# Create your models here.
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_Date = models.DataTimeField('date published')
def _str_(self):
return 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
def was_published_recently(self):
return self.pub_Date >= timezone.now() - datetime.timedelta(days = 1)
Python
복사
-shell 실행 후 Question에 대한 data 확인
02-2. Admin
django admin
•
cmd
py manage.py createsuperuser
# 웹브라우저를 열고 로컬 도메인의 "\admin\"으로 이동 후 로그인
Python
복사
•
admin.py
from django.contrib import admin
from .models import Question
admin.site.register(Question)
Python
복사
03.View
django view
•
poll 어플리케이션에서 4개의 뷰 작성
-Question "index" 페이지
-Question "detail" 페이지
-Question "resullt" 페이지
-"vote" 기능
•
views.py
def detail(request, question_id):
return HTTPResponse("You're looking at question %s." % question_id)
def results(request, question_id):
response = "You're looking at the results of question %s."
return HTTPResponse(response % question_id)
def vote(request, question_id):
return HTTPResponse("You're voting on question %s." % question_id)
Python
복사
•
urls.py
from django.urls import path
from . import views
urlpatterns = [
# ex : /polls/
path('', views.index, name = 'index')
# ex : /polls/5/
path('<int:question_id>/', views.detail, name = 'detail')
# ex : /polls/results/
path('<int:question_id>/results/', views.results, name = 'results')
# ex : /polls/5/vote/
path('<int:question_id>/vote/', views.vote, name = 'vote')
]
Python
복사
•
view가 실제로 뭔가를 하도록 만들기
-views.py
from django.http import HttpResponse
from .models import Question
def index(request):
latest_question_list = Question.objects.order_by('_pub_date')[:5]
output = ', '.join([q.question_text for q in latest_question_list])
return HttpResponse(output)
# Leave the rest of the views (detail, results, vote) unchanged
Python
복사
-polls/templates/polls/index.html
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li><a href = "/polls/{{question.id}}/"{{question.question_text}}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.<\p>
{% endif %}
HTML
복사
•
지름길 : render()
- 코드 양을 줄여줌
-views.py
from django.http import HttpResponse
from django.template import loader
from .models import Question
def index(request):
latest_question_list = Question.objects.order_by('_pub_date')[:5]
template = loader.get_template('polls/index.html')
context = {
'latest_question_list' : latest_quetion_list,
}
return HttpResponse(template.render(context, request))
# Leave the rest of the views (detail, results, vote) unchanged
Python
복사
•
404 에러 일으키기
-polls/views.py
from django.http import Http404
from django.shortcuts import render
from .models import Question
#...
def detail(request, question_id)
try:
question = Question.objects.get(pk=question_id)
except Question.DoesNotExist:
raise Http404("Question dose not exist")
return render(request, 'polls/detail.html', {'question':question})
Python
복사
•
템플릿 시스템 이용하기
-polls/templates/polls/details.html
<h1>{{question.question.text}}</h1>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>
HTML
복사
•
템플릿에서 하드코딩된 URL 제거
04.Form & Generic View
django form
•
detail.html
<h1>{{ question.question_text }}</h1>
<!--<ul>
{% for choice in quesiton.choice_set.all %}
<li>{{ choice.choice_text }}</li>
{% endfor %}
</ul> -->
{% if error_message %}<p>{{ error_message }}</p>>{% endif %}
<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% 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 %}
<input type="submit" value="Vote">
</form>
HTML
복사
•
results.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 %}"> Vote again?</a>
HTML
복사
•
urls.py
app_name = 'polls'
urlpatterns = [
# ex /polls/
path('', views.index, name='index'),
# path('', views.index, name='index'),
path('', views.IndexView.as_view(), name='index'),
# ex /polls/5/
path('<int:question_id>/', views.detail, name='detail'),
# path('<int:question_id>/', views.detail, name='detail'),
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
# ex /polls/5/results/
path('<int:question_id>/results/', views.results, name='results'),
# path('<int:question_id>/results/', views.results, name='results'),
path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
# ex /polls/5/vote
path('<int:question_id>/vote/', views.vote, name='vote'),
]
Python
복사
•
views.py
from django.http import HttpResponse, Http404
from django.http import HttpResponse, Http404, HttpResponseRedirect
from django.template import loader
from django.shortcuts import render, get_object_or_404
from django.urls import reverse
from django.views import generic
from .models import Question
# Create your views here.
def index(request):
# def index(request):
# 1. Basic view
# return HttpResponse("Hello, world.")
@@ -24,14 +26,22 @@ def index(request):
# return HttpResponse(template.render(context, request))
# 4. Use the shortcut - render
latest_question_list = Question.objects.order_by('-pub_date')[:5]
context = {
'latest_question_list': latest_question_list,
}
return render(request, 'polls/index.html',context)
# latest_question_list = Question.objects.order_by('-pub_date')[:5]
# context = {
# 'latest_question_list': latest_question_list,
# }
# return render(request, 'polls/index.html',context)
#5. Use the Generic View
class IndexView(generic.ListView):
template_name = 'polls/index.html'
context_object_name = 'latest_question_list'
def detail(request, question_id):
def get_queryset(self):
return Question.objects.order_by('-pub_date')[:5]
# def detail(request, question_id):
# 1. Basic view
# return HttpResponse("You're looking at question %s." % question_id)
@@ -43,11 +53,41 @@ def detail(request, question_id):
# return render(request, 'polls/detail.html', {'question': question})
# 3. Use the shortcut - get_object_or_404
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/detail.html', {'question': question})
# question = get_object_or_404(Question, pk=question_id)
# return render(request, 'polls/detail.html', {'question': question})
#4. Use the Generic View
class DetailView(generic.DetailView):
model = Question
template_name = 'polls/detail.html'
# def results(request, question_id):
# 1. Basic view
# return HttpResponse(response % question_id)
# 2. Use the shortcut - get_object_or_404
# question = get_object_or_404(Question, pk=question_id)
# return render(request, 'polls/results.html', {'question': question})
#3. Use the Generic View
class ResultsView(generic.DetailView):
model = Question
template_name = 'polls/results.html'
def results(request, question_id):
return HttpResponse(response % question_id)
def vote(request, question_id):
return HttpResponse("You're voing on question %s." % question_id)
# return HttpResponse("You're voing 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, chocie.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()
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
Python
복사
05.Test
django test
•
테스트 코드
# test.py
import datetime
from django.test import TestCase
from django.utils import timezone
from .models import Question
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_quesiton.was_published_recently(),False)
Python
복사
•
버그 수정
# polls/models.py
def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days = 1) <= self.pub_date <= now
Python
복사
•
뷰 테스트
python manage.py shell
from django.test.utils import setup_test_environment
setup_test_environment()
from django.test import Client
# creat an instance of the client for our use
client = Client()
Shell
복사
06.CSS & Static File
django css
•
polls/static/polls/style.css
li a {
color: green;
}
body {
background: white url("images/background.jpeg") no-repeat;
}
CSS
복사
•
polls/templates/polls/index.html
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'polls/style.css' %}">
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
HTML
복사
07.Customize Admin
django customize the admin
•
mysite/settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
Python
복사
•
polls/admin.py
from django.contrib import admin
from .models import Question, Choice
# Register your models here.
class ChoiceInline(admin.TabularInline):
model = Choice
extra = 3
admin.site.register(Question)
admin.site.register(Choice)
class QuestionAdmin(admin.ModelAdmin):
list_display = ('question_text', 'pub_date', 'was_published_recently')
fieldsets = [
(None, {'fields': ['question_text']}),
('Date information', {'fields': ['pub_date']}),
]
inlines = [ChoiceInline]
list_filter = ['pub_date']
search_fields = ['question_text']
admin.site.register(Question, QuestionAdmin)
Python
복사
•
polls/models.py
def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days=1) <= self.pub_date <= now
was_published_recently.admin_order_field = 'pub_date'
was_published_recently.boolean = True
was_published_recently.short_description = 'Published recently?'
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
Python
복사
•
templates/admin/base_site.html
{% extends "admin/base.html" %}
{% block title %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %}
{% block branding %}
<h1 id="site-name"><a href="{% url 'admin:index' %}">Polls administration</a></h1>
{% endblock %}
{% block nav-global %}{% endblock %}
HTML
복사