📢 공지사항
home
💻

Django 1

상태
정하은
배정
공부 계획
일주일 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
복사