
3월인데도 날씨가 여전히 춥다. 취미와 악기에 대해 간단히 얘기를 나눴다.
오늘 금요일!
내일부터 주말이니 오늘 파이팅 하자!@
MVT(Model Template View) 패턴
Model : 데이터를 정의 ⇒ model.py
Template : 화면을 정의 ⇒ templates 디렉터리 하위에 *.html 파일
View : 어플리케이션의 흐름을 제어 ⇒ views.py
⇒ 느슨한 결합(losse couping) 설계 원칙에 부합

C:\python> python --version
Python 3.12.2
C:\python> pip list
Package Version
--------------- -----------
Faker 23.3.0
pip 24.0
PyMySQL 1.1.0
python-dateutil 2.9.0.post0
six 1.16.0
C:\python> python -m venv mysite
~~~~~~
가상 환경 이름 ⇒ 동일한 이름에 디렉터리가 생성
C:\python> .\mysite\Scripts\activate
(mysite) C:\python>
~~~~~~~~
가상 환경에서 작업하는 것을 의미
(mysite) C:\python> pip list
Package Version
pip 24.0 ⇐ #1과는 다른 새로운 환경인 것을 확인
(mysite) C:\python> pip install faker==22.7.0
Collecting faker==22.7.0
Downloading Faker-22.7.0-py3-none-any.whl.metadata (15 kB)
Collecting python-dateutil>=2.4 (from faker==22.7.0)
Using cached python_dateutil-2.9.0.post0-py2.py3-none-any.whl.metadata (8.4 kB)
Collecting six>=1.5 (from python-dateutil>=2.4->faker==22.7.0)
Using cached six-1.16.0-py2.py3-none-any.whl.metadata (1.8 kB)
Downloading Faker-22.7.0-py3-none-any.whl (1.7 MB)
---------------------------------------- 1.7/1.7 MB 3.2 MB/s eta 0:00:00
Using cached python_dateutil-2.9.0.post0-py2.py3-none-any.whl (229 kB)
Using cached six-1.16.0-py2.py3-none-any.whl (11 kB)
Installing collected packages: six, python-dateutil, faker
Successfully installed faker-22.7.0 python-dateutil-2.9.0.post0 six-1.16.0
(mysite) C:\python> pip list
Package Version
--------------- -----------
Faker 22.7.0 ⇐ 패키지가 설치된 것을 확인
pip 24.0
python-dateutil 2.9.0.post0
six 1.16.0
(mysite) C:\python> set path ⇐ PATH 환경변수를 확인
Path=C:\python\mysite\Scripts;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Users\crpark\AppData\Local\Programs\Python\Python312\Scripts\;C:\Users\crpark\AppData\Local\Programs\Python\Python312\;C:\Users\crpark\AppData\Local\Microsoft\WindowsApps;C:\Users\crpark\AppData\Local\Programs\Microsoft VS Code\bin
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
(mysite) C:\python> deactivate ⇐ 가상 환경 내에서는 PATH 환경변수에 해당 경로가 등록되어 있으므로
어느 경로에서나 명령어 실행이 가능
C:\python> set path ⇐ 가상 환경과 관련한 경로가 포함되어 있지 않음
Path=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Users\crpark\AppData\Local\Programs\Python\Python312\Scripts\;C:\Users\crpark\AppData\Local\Programs\Python\Python312\;C:\Users\crpark\AppData\Local\Microsoft\WindowsApps;C:\Users\crpark\AppData\Local\Programs\Microsoft VS Code\bin
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
C:\python> pip list
Package Version
--------------- -----------
Faker 23.3.0 ⇐ 가상 환경에서 설치한 Faker 모듈과 버전이 상이한 것을 확인
pip 24.0
PyMySQL 1.1.0
python-dateutil 2.9.0.post0
six 1.16.0
C:\python> python -m venv yoursite
C:\python> .\yoursite\Scripts\activate
(yoursite) C:\python>
(yoursite) C:\python> pip list
Package Version
------- -------
pip 24.0
(yoursite) C:\python> pip install faker==20.1.0
Collecting faker==20.1.0
Downloading Faker-20.1.0-py3-none-any.whl.metadata (15 kB)
Collecting python-dateutil>=2.4 (from faker==20.1.0)
Using cached python_dateutil-2.9.0.post0-py2.py3-none-any.whl.metadata (8.4 kB)
Collecting six>=1.5 (from python-dateutil>=2.4->faker==20.1.0)
Using cached six-1.16.0-py2.py3-none-any.whl.metadata (1.8 kB)
Downloading Faker-20.1.0-py3-none-any.whl (1.7 MB)
---------------------------------------- 1.7/1.7 MB 9.2 MB/s eta 0:00:00
Using cached python_dateutil-2.9.0.post0-py2.py3-none-any.whl (229 kB)
Using cached six-1.16.0-py2.py3-none-any.whl (11 kB)
Installing collected packages: six, python-dateutil, faker
Successfully installed faker-20.1.0 python-dateutil-2.9.0.post0 six-1.16.0
(yoursite) C:\python> pip list
Package Version
--------------- -----------
Faker 20.1.0
pip 24.0
python-dateutil 2.9.0.post0
six 1.16.0
(yoursite) C:\python> deactivate
C:\python> pip list
Package Version
--------------- -----------
Faker 23.3.0 ⇐ 가상 환경과 무관하게 버전이 유지되는 것을 확인
pip 24.0
PyMySQL 1.1.0
python-dateutil 2.9.0.post0
six 1.16.0
C:\python> .\mysite\Scripts\activate
(mysite) C:\python>
(mysite) C:\python> pip install django==3.1.3
Collecting django==3.1.3
Downloading Django-3.1.3-py3-none-any.whl.metadata (3.7 kB)
Collecting asgiref<4,>=3.2.10 (from django==3.1.3)
Downloading asgiref-3.7.2-py3-none-any.whl.metadata (9.2 kB)
Collecting pytz (from django==3.1.3)
Downloading pytz-2024.1-py2.py3-none-any.whl.metadata (22 kB)
Collecting sqlparse>=0.2.2 (from django==3.1.3)
Downloading sqlparse-0.4.4-py3-none-any.whl.metadata (4.0 kB)
Downloading Django-3.1.3-py3-none-any.whl (7.8 MB)
---------------------------------------- 7.8/7.8 MB 27.8 MB/s eta 0:00:00
Downloading asgiref-3.7.2-py3-none-any.whl (24 kB)
Downloading sqlparse-0.4.4-py3-none-any.whl (41 kB)
---------------------------------------- 41.2/41.2 kB 2.1 MB/s eta 0:00:00
Downloading pytz-2024.1-py2.py3-none-any.whl (505 kB)
---------------------------------------- 505.5/505.5 kB 31.0 MB/s eta 0:00:00
Installing collected packages: pytz, sqlparse, asgiref, django
Successfully installed asgiref-3.7.2 django-3.1.3 pytz-2024.1 sqlparse-0.4.4
(mysite) C:\python> pip list
Package Version
--------------- -----------
asgiref 3.7.2
Django 3.1.3
Faker 22.7.0
pip 24.0
python-dateutil 2.9.0.post0
pytz 2024.1
six 1.16.0
sqlparse 0.4.4
(mysite) C:\python\mysite> pip install setuptools ⇐ python 3.12 버전에서 삭제된 도구를 설치
Collecting setuptools python 3.11 버전에서 기본적으로 포함되어 있음
Using cached setuptools-69.1.1-py3-none-any.whl.metadata (6.2 kB)
Using cached setuptools-69.1.1-py3-none-any.whl (819 kB)
Installing collected packages: setuptools
Successfully installed setuptools-69.1.1
(mysite) C:\python\mysite> django-admin startproject config . ⇐ 현재 디렉터리를 프로젝트 디렉터리로 만들라는 의미
# 내 PC -> C 디스크 -> python -> mysite
# 여기까지 함.
(mysite) c:\python\projects\mysite> tree . /f
폴더 PATH의 목록입니다.
볼륨 일련 번호는 9027-83B9입니다.
C:\PYTHON\PROJECTS\MYSITE
│ manage.py
│
└─config
asgi.py
settings.py
urls.py
wsgi.py
__init__.py
(mysite) c:\python\projects\mysite> code .
(mysite) c:\python\projects\mysite> python 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.
March 08, 2024 - 11:14:34
Django version 3.1.3, using settings 'config.settings' ⇐ 설정 파일
Starting development server at http://127.0.0.1:8000/ ⇐ 접속 주소
Quit the server with CTRL-BREAK. ⇐ 서버 중지 방법 (Ctrl + C)
앱 - 특정 기능을 수행하는 웹 애플리케이션
(mysite) c:\python\projects\mysite> django-admin startapp pybo
~~~~ 앱 이름
(mysite) c:\python\projects\mysite> tree .\pybo /f
폴더 PATH의 목록입니다.
볼륨 일련 번호가 0000001B 9027:83B9입니다.
C:\PYTHON\PROJECTS\MYSITE\PYBO
│ admin.py
│ apps.py
│ models.py
│ tests.py
│ views.py
│ __init__.py
│
└─migrations
__init__.py
(mysite) c:\python\projects\mysite> python manage.py runserver
Page not found
from django.contrib import admin
from django.urls import path
from pybo import views
urlpatterns = [
path('admin/', admin.site.urls),
path('pybo/', views.index) ⇐ views.py 파일에 index 함수는 구현되지 않은 상태임
]
File "C:\Users\crpark\AppData\Local\Programs\Python\Python312\Lib\importlib\__init__.py", line 90, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 995, in exec_module
File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
File "c:\python\projects\mysite\config\urls.py", line 22, in <module>
path('pybo/', views.index)
^^^^^^^^^^^
AttributeError: module 'pybo.views' has no attribute 'index' ⇐ 뷰 함수가 정의되지 않았기 때문에 오류가 발생
from django.shortcuts import render
from django.http import HttpResponse ⇐ 요청에 대한 응답을 만들 때 사용하는 클래스
def index(request):
return HttpResponse("안녕하세요. PYBO에 온 것을 환영합니다.")
http://localhost:8000/pybo 로 접속
200 OK 초록불 확인
다른 명령 프롬프트에서 curl로 접속
C:\Users\crpark> curl http://localhost:8000/pybo/ -v
* Trying [::1]:8000... ⇐ 개발 서버와 연결을 시도
* Trying 127.0.0.1:8000...
* Connected to localhost (127.0.0.1) port 8000
> GET /pybo/ HTTP/1.1 ⇐ 요청 시작
> Host: localhost:8000 ⇐ 요청 헤더 시작
> User-Agent: curl/8.4.0
> Accept: */*
> ⇐ 요청 헤더 끝 (GET 방식인 경우 요청 본문은 생략)
< HTTP/1.1 200 OK ⇐ 응답 시작
< Date: Fri, 08 Mar 2024 04:32:44 GMT ⇐ 응답 헤더 시작
< Server: WSGIServer/0.2 CPython/3.12.2
< Content-Type: text/html; charset=utf-8
< X-Frame-Options: DENY
< Content-Length: 52
< X-Content-Type-Options: nosniff
< Referrer-Policy: same-origin
< ⇐ 응답 헤더 끝
안녕하세요. PYBO에 온 것을 환영합니다. ⇐ 응답 본문 ⇒ index 함수에서 HttpResponse 인스턴스 생성 시
* Connection #0 to host localhost left intact 입력한 문자열

from django.contrib import admin
from django.urls import path, include
from pybo import views
urlpatterns = [
path('admin/', admin.site.urls),
# path('pybo/', views.index),
path('pybo/', include('pybo.urls')) ⇐ pybo 패키지에 있는 urls 모듈을 참조해서 URL 맵핑을 처리
] → pybo\urls.py 파일에 pybo/ 패턴의 요청을 처리할 URL 맵핑을 정의
from django.urls import path
from . import views # 현재 패키지에서 views 모듈을 가져옴
urlpatterns = [
path('', views.index),
]
(mysite) c:\python\projects\mysite> python 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.
March 08, 2024 - 14:08:05
Django version 3.1.3, using settings 'config.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
[08/Mar/2024 14:08:08] "GET /pybo/ HTTP/1.1" 200 52
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
(mysite) c:\python\projects\mysite> python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying sessions.0001_initial... OK

C:\Program Files\DB Browser for SQLite\DB Browser for SQLite.exe 실행

pybo\models.py
from django.db import models
# 질문 모델 클래스를 정의
class Question(models.Model):
# 질문 모델이 가지는 속성을 정의
subject = models.CharField(max_length=200) # 글자 수 제한이 있는 데이터
content = models.TextField() # 글자 수 제한이 없는 데이터
create_date = models.DateTimeField() # 날짜, 시간을 나타내는 데이터
# 답변 모델 클래스를 정의
class Answer(models.Model):
# 답변 모델이 가지는 속성을 정의
question = models.ForeignKey(Question, on_delete=models.CASCADE)
content = models.TextField()
create_date = models.DateTimeField()
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'pybo.apps.PyboConfig', ⇐ 장고가 pybo 앱을 인식하고 데이터베이스 관련 작업을 수행할 수 있음
]
(mysite) c:\python\projects\mysite> python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
No migrations to apply.
Your models have changes that are not yet reflected in a migration, and so won't be applied.
Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them.
~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
장고가 테이블 작업을 수행하기 위한 파일을 생성 실제 테이블을 생성
(mysite) c:\python\projects\mysite> python manage.py makemigrations
Migrations for 'pybo':
pybo\migrations\0001_initial.py
- Create model Question
- Create model Answer
(mysite) c:\python\projects\mysite> dir pybo\migrations ⇐ 마이그레이션 파일이 있는 위치
C 드라이브의 볼륨에는 이름이 없습니다.
볼륨 일련 번호: 9027-83B9
c:\python\projects\mysite\pybo\migrations 디렉터리
2024-03-08 오후 03:02 <DIR> .
2024-03-08 오후 03:02 <DIR> ..
2024-03-08 오후 03:02 1,104 0001_initial.py
2024-03-08 오후 01:09 0 __init__.py
2024-03-08 오후 03:02 <DIR> __pycache__
2개 파일 1,104 바이트
3개 디렉터리 172,790,190,080 바이트 남음
(mysite) c:\python\projects\mysite> type pybo\migrations\0001_initial.py
# Generated by Django 3.1.3 on 2024-03-08 06:02
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Question',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('subject', models.CharField(max_length=200)),
('content', models.TextField()),
('create_date', models.DateTimeField()),
],
),
migrations.CreateModel(
name='Answer',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('content', models.TextField()),
('create_date', models.DateTimeField()),
('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pybo.question')),
],
),
]
(mysite) c:\python\projects\mysite> python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, pybo, sessions
Running migrations:
Applying pybo.0001_initial... OK

(mysite) c:\python\projects\mysite> python manage.py shell
Python 3.12.2 (tags/v3.12.2:6abddd9, Feb 6 2024, 21:26:36) [MSC v.1937 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>
>>> from pybo.models import Question, Answer
>>> from django.utils import timezone
>>> q = Question(subject='pybo가 무엇인가요?', content='pybo에 대해서 알려 주세요', create_date=timezone.now())
>>> q.save() ⇐ 모델 데이터를 데이터베이스에 저장

>>> q.subject
'pybo가 무엇인가요?'
>>> q.id ⇐ 장고가 자동으로 넣어 주는 필드
1
Question 인스턴스를 하나 더 생성해서 저장
>>> q = Question(subject='두번째 질문입니다.', content='ID는 자동으로 생성되나요?', create_date=timezone.now())
>>> q.save()
>>> q.id
2

>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>, <Question: Question object (2)>]>
~ ~
장고가 Question 모델 데이터에 자동으로 입력한 ID 값
pybo\models.py
from django.db import models
# 질문 모델 클래스를 정의
class Question(models.Model):
# 질문 모델이 가지는 속성을 정의
subject = models.CharField(max_length=200) # 글자 수 제한이 있는 데이터
content = models.TextField() # 글자 수 제한이 없는 데이터
create_date = models.DateTimeField() # 날짜, 시간을 나타내는 데이터
def __str__(self):
return self.subject ⇐ 제목을 반환
# 답변 모델 클래스를 정의
class Answer(models.Model):
# 답변 모델이 가지는 속성을 정의
question = models.ForeignKey(Question, on_delete=models.CASCADE)
content = models.TextField()
create_date = models.DateTimeField()
>>> exit()
(mysite) c:\python\projects\mysite> python manage.py shell
Python 3.12.2 (tags/v3.12.2:6abddd9, Feb 6 2024, 21:26:36) [MSC v.1937 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from pybo.models import Question, Answer
>>> Question.objects.all()
<QuerySet [<Question: pybo가 무엇인가요?>, <Question: 두번째 질문입니다.>]>
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
>>> Question.objects.filter(id=1) ⇐ 조건에 해당하는 데이터를 모두 찾아서 QuerySet 형태로 반환
<QuerySet [<Question: pybo가 무엇인가요?>]>
>>> rs = Question.objects.filter(id=1)
>>> rs[0].subject
'pybo가 무엇인가요?'
>>> rs = Question.objects.filter(id=100) ⇐ 조건을 만족하는 결과가 없는 경우 빈 QuerySet을 반환
>>> rs
<QuerySet []>
>>> Question.objects.get(id=1) ⇐ 조건에 해당하는 데이터 중 하나만 해당 객체 타입으로 반환
<Question: pybo가 무엇인가요?>
>>> rs = Question.objects.get(id=1)
>>> rs.subject
'pybo가 무엇인가요?'
>>> rs = Question.objects.get(id=100) ⇐ 조건을 만족하는 결과가 없는 경우 오류가 발생
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "C:\Users\crpark\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\db\models\manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\crpark\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\db\models\query.py", line 429, in get
raise self.model.DoesNotExist(
pybo.models.Question.DoesNotExist: Question matching query does not exist.
>>> Question.objects.filter(subject='인가요') ⇐ 일치하는 것을 조회
<QuerySet []>
>>> Question.objects.filter(subject__contains='인가요') ⇐ SQL의 LIKE 연산과 동일하게 동작
<QuerySet [<Question: pybo가 무엇인가요?>]>
>>> q = Question.objects.get(id=1) ⇐ 수정 대상 조회 (get, filter)
>>> q
<Question: pybo가 무엇인가요?>
>>> q.subject = 'What is pybo?' ⇐ 객체 필터의 데이터를 변경
>>> q.save() ⇐ save 함수를 이용해서 DB에 반영
>>> q = Question.objects.get(id=1)
>>> q
<Question: What is pybo?>
>>> q = Question.objects.get(id=1)
>>> q.delete() ⇐ delete 메서드를 호출하면 DB에도 즉시 반영
(1, {'pybo.Question': 1})
>>> rs = Question.objects.all()
>>> rs
<QuerySet [<Question: 두번째 질문입니다.>]>

>>> q = Question.objects.get(id=2)
>>> q
<Question: 두번째 질문입니다.>
>>> from django.utils import timezone
>>> a = Answer(question=q, content='네 자동으로 생성됩니다.', create_date=timezone.now())
>>> a.save()

>>> a = Answer.objects.get(id=1)
>>> a
<Answer: Answer object (1)>
>>> a.question
<Question: 두번째 질문입니다.>
>>> a = Answer.objects.get(id=1)
>>> a
<Answer: Answer object (1)>
>>> a.question
<Question: 두번째 질문입니다.>
>>> q = Question.objects.get(id=2)
>>> q.answer_set.all() ⇐ 연결되어있는모델명_set 형식으로 참조
<QuerySet [<Answer: Answer object (1)>]>
>>> exit()
(mysite) c:\python\projects\mysite> python manage.py createsuperuser
Username (leave blank to use 'crpark'): admin
Email address: myanjini@gmail.com
Password: p@ssw0rd
Password (again): p@ssw0rd
This password is too common.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.
(mysite) c:\python\projects\mysite> python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
March 08, 2024 - 16:48:25
Django version 3.1.3, using settings 'config.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.


pybo\admin.py
from django.contrib import admin
from .models import Question
admin.site.register(Question)

pybo\admin.py
from django.contrib import admin
from .models import Question
class QuestionAdmin(admin.ModelAdmin):
search_fields = ['subject']
admin.site.register(Question, QuestionAdmin)

pybo\views.py
from django.shortcuts import render
from .models import Question
def index(request):
question_list = Question.objects.order_by('-create_date')
context = { 'question_list' : question_list }
return render(request, 'pybo/question_list.html', context)
c:\python\projects\mysite\templates\pybo\question_list.html
템플릿 파일이 저장되는 위치

{% if question_list %}
<ul>
{% for question in question_list %}
<li><a href="/pybo/{{ question.id }}/">{{ question.subject }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>질문이 없습니다.</p>
{% endif %}
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [ BASE_DIR / 'templates' ],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

Today is...

뭔가 많이 한 것 같은데 겨우 1주일 지났다 ㅋㅋㅋㅋ
그만큼 하루하루가 갖는 의미가 크다는 것이기도 하고,
아직 기초가 많이 부족한데,
프로젝트 하기 전까지 공부할 시간이 여유가 있다는 것! 아마도..??
그렇게 믿고 싶다 ㅋㅋㅋ
주말에도 공부는 하되, 하루는 푹 쉬려고 한다!
그래야 또 다음주 생활할 수 있을 것 같아서!
아 나 다음주 예비군에 이런저런 일이 많구나
주말 내내 공부해야하나~
내일 컨디션 봐서 ㅎ
한주동안 고생했고!
무엇보다 지각 한번도 안한점!! 잘했다 ㅎㅎ
담주도 파이팅!