환경
- Ubuntu Server 22.04
- VSCode Insider
- Remote SSH Extension
- Python 3.10 venv
- Django 5.1.1
- SQLite 3.37.2
준비
# 프로젝트, env 생성은 지난 포스팅 참고
source django_env/bin/activate
# 프로젝트 폴더를 옮겼다면
# vi django_env/bin/activate에서 virtual_env 경로를 바꿔줘야함 😫
# vi django_env/bin/pip 의 shebang 경로 (#!)도 바꿔준다
# @test_proj/polls : 템플릿 준비
mkdir -p templates/polls && \
touch templates/polls/index.html && \
touch templates/polls/detail.html
touch templates/polls/result.html
실행
1. The Templates
<!-- 컨텍스트와 템플릿 지역 변수 안 햇갈리는게 포인트 🤡 -->
<!-- 그냥 리엑트 쓰면 안되? 😁 -->
<!-- /templates/polls/index.html -->
{% if qs %}
<ul>
{% for q in qs %}
<!-- <li><a href="/polls/{{ q.id }}">{{ q.question_text }}</a></li> -->
<!-- OR use the 'name' argument from the urls.py -->
<li><a href="{% url 'polls:detail' q.id %}">{{ q.question_text }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No question</p>
{% endif %}
<!-- -------------------------- -->
<!-- /templates/polls/detail.html -->
{% if err %}
<p style="background-color: salmon; color:black">{{ err }}</p>
{% endif %}
<!-- 이게 double quote 없이 된다고 ? 😮 ... 난 쓸거임 -->
<form action="{% url 'polls:vote' q.id %}" method="post">
<!-- token for the form 🥴-->
{% csrf_token %}
<h2>{{ q.question_text }}</h2>
<!-- METHODS IN CONTEXT: NO PARENTHESIS -->
{% for c in q.choice_set.all %}
<!-- increment by 1 -->
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ c.id }}">
<label for="choice{{ forloop.counter }}">
{{ c.choice_text }}
</label>
<br>
{% endfor %}
<input type="submit" value="Vote">
</form>
<!-- -------------------------- -->
<!-- /templates/polls/result.html -->
<h2>{{ q.question_text }}</h2>
<!-- METHODS IN CONTEXT: NO PARENTHESIS -->
{% for c in q.choice_set.all %}
<label>
{{ c.choice_text }} votes: {{ c.votes }}
</label>
<br>
{% endfor %}
2. views.py
# polls/views.py
from django.http import Http404, HttpResponse
from .models import *
from django.shortcuts import render, get_object_or_404
from django.db.models import F
# polls 루트
def index(request):
qs = Question.objects.order_by('-pub_date')[:5]
context = {'qs': qs}
return render(request, 'polls/index.html', context)
# 질문별 상세 페이지
def detail(request, question_id):
# try:
# q = Question.objects.get(pk=question_id)
# except Question.DoesNotExist:
# raise Http404("404 nope")
# OR
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/detail.html', {'q': q})
# 상세 페이지 CRUD
def vote(request, question_id):
q = get_object_or_404(Question, pk=question_id)
try:
# 'choice' == the name attrib of the input tag
ch = q.choice_set.get(pk=request.POST['choice'])
# 선택 안 했을때 & 페이지가 로드 된 후 테이블이 없어진 경우 & 기타 integrity
except (KeyError, Choice.DoesNotExist):
return render(request, 'polls/detail.html', {'q': q, 'err': 'You must choose!'})
else:
# DB에서 연산하게 함 ( += 1 ㄴㄴ)
ch.votes = F('votes') + 1
ch.save()
# 인자 튜플임 !!🐱🐉
return HttpResponseRedirect(reverse('polls:result', args=(question_id,)))
def result(request, question_id):
q = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/result.html', {'q': q})
3. urls.py
# polls/urls.py
from django.urls import path
from . import views
# 중복된 name 방지하기 위해서 namespace specify (임의 지정 가능)
# index에서 {% url 'polls:detail' q.id %}로 수정해줘야 함
app_name = 'polls' # urls.py 안에 있는 app_name을 찾게 predefine 돼있음
urlpatterns = [
path('', views.index, name='index'),
# 🤢
path('<int:question_id>', views.detail, name='detail'),
# for vote post request
path('<int:question_id>/vote/', views.vote, name='vote'),
# result
path('<int:question_id>/result', views.result, name='result'),
]
'W | eb' 카테고리의 다른 글
Django CRUD: API (0) | 2024.10.09 |
---|---|
Django CRUD: Serialize (0) | 2024.10.08 |
Django CRUD: Admin (1) | 2024.10.08 |
Django MVC(MTV) (0) | 2024.10.07 |
HTML (0) | 2024.10.02 |