웹페이지에 스타일시트 적용하기
1. 설정 파일에 스태틱 디렉터리 위치 추가하기
STATIC_URL = '/static/'
STATICFILES_DIRS = [
BASE_DIR / 'static'
]
2. 스태틱 디렉터리 만들고 스타일 시트 작성하기
mkdir static
text area{
width = 100%;
}
input[type=submit] {
margin-top:10px;
}
- 답변을 등록할 때 사용하는 text area를 100%로 넓히고, <답변등록> 버튼 위에 margin을 10px 추가했다.
3. 질문 상세 템플릿에 스타일 적용하기
{% load static %}
<link rel="stylesheet" type = "text/css" href="{% static 'style.css' %}">
<h1>{{ question.subject }}<h1>
(..생략..)
- 스태틱 파일을 사용하기 위해서, 템플릿 맨 위에 {% load static %} 태그를 삽입하고, link 엘리먼트 href 속성에 {% static 'style.css' %} 삽입하면,
- static 디렉터리의 style.css 파일을 연결한다는 의미이다.
부트스트랩 활용해서 화면 꾸미기
1. 부트스트랩 다운로드
- 구글에 부트스트랩 검색
- 모든 버전 클릭
- 다운로드 받은 파일에서 bootstrap.min.js , bootstrap.min.css 파일을 static 폴더로 이동
2. 질문 목록에 템플릿에 부트스트랩 적용하기(템플릿 상속 활용)
- 장고는 템플릿 상속(extends) 기능을 제공한다.
- {% block content %}와 {% enblock %} 템플릿 태그는 이후 base.html 템플릿 파일을 상속한 파일에서 구현해야 하는 영역이 된다.
- base.html 바꾸기
{% load static %}
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" type="text/css" href="{% static 'bootstrap.min.css' %}">
<title>Hello, pybo!</title>
</head>
<body>
<!-- 네비게이션바 -->
<nav class="navbar navbar-expand-lg navbar-light bg-light border-bottom">
<div class="container-fluid">
<a class="navbar-brand" href="{% url 'pybo:index' %}">메인페이지</a>
<button class="navbar-toggler" type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="#">로그인</a>
</li>
</ul>
</div>
</div>
</nav>
<!-- 기본 템플릿 안에 삽입될 내용 Start -->
{% block content %}
{% endblock %}
<!-- 기본 템플릿 안에 삽입될 내용 End -->
</body>
</html>
- 질문 목록 템플릿, 질문 상세 템플릿 수정
{% extends 'base.html' %}
- base.html 상속해서 question_list, question_detail 업데이트 하기
{% extends 'base.html' %}
{% block content %}
html 코드
{% endblock %}
3. 질문 등록 기능 만들기
3.(1) 질문 등록 버튼 만들기
</table>
{% comment %} 질문 등록 버튼 만들기 {% endcomment %}
<a class="btn btn-primary" href="{% url "pybo:question_create" %}">질문 등록</a>
</div>
a 엘리먼트에 href 속성으로 질문 등록 URL을 {% url ‘pybo:question_create’ %}처럼 추가하고 부트스트랩 클래스“btn btn-primary”를 지정했다
3.(2) url 매핑 추가를 위해 pybo/urls.py 수정하기
# 질문 등록에 대한 URL 매핑
path("question/create/", views.question_create, name = "question_create")
3.(3) pybo/views.py 수정하기
from .forms import QuestionForm
...(생략)...
def question_create(request):
form = QuestionForm()
return render(request, "pybo/question_form.html", {'form' : form})
QuestionForm 클래스는 질문을 등록하기 위해 사용하는 장고의 폼
render 함수에 전달한 {'form' : form}은 템플릿에서 폼 엘리먼트를 생성할 때 사용한다.
3.(4) pybo/forms.py에 장고 폼 작성하기
from django import forms
from .models import Question
class QuestionForm(forms.ModelForm):
class Meta:
model = Question
fields = ['subject', 'content']
- forms.ModelForm을 상속받아 모델 폼을 만들었다
- 장고 모델 폼은 내부 클래스로 Meta 클래스를 반드시 가져야하며, Meta 클래스에는 모델 폼이 사용할 모델과 모델의 필드를 적어야한다.
3.(5) pybo/question_form.html 만들어 장고 폼 사용하기
{% extends "base.html" %}
{% block content %}
<div class="container">
<h5 class = "my-3 border-bottom pb-2">질문 등록</h5>
<form method="post">
{% comment %} 장고에서 폼 태그 내에서 액션 속성을 사용하지 않으면, 기본 페이지 url이 디폴트로 설정됩니다.
{% endcomment %}
{% csrf_token %}
{% comment %} form.as_p는 html 태그를 자동으로 만들어주는 장고의 동적기능 {% endcomment %}
{{ form.as_p}}
<button type="submit" class='btn btn-primary'>질문 저장</button>
</form>
</div>
{% endblock %}
{{ form.as_p }}는 모델 폼과 연결된 입력 항목 subject, content에 값을 입력할 수 있는 HTML 코드를 자동으로 만들어 줍니다.
3.(6) 질문 등록 화면 확인하기
3.(7) 입력 데이터 저장하기
def question_create(request):
if request.method == 'POST': # post 요청일 때는 입력한 값들을 전달받아 DB에 저장
form = QuestionForm(request.POST)
if form.is_valid():
question = form.save(commit=False)
question.create_date = timezone.now()
question.save()
return redirect('pybo:index')
else: # Get 요청일 때는 단순히 질문등록 페이지 요청
form = QuestionForm()
context = {'form': form}
return render(request, 'pybo/question_form.html', context)
- 동일한 URL 요청을 POST, GET 요청 방식에 따라 다르게 처리한다.
- QuestionForm 객체도 GET방식과 POST방식일 경우 다르게 생성한다.
- question = form.save(commit=False)는 form으로 Question 모델 데이터를 저장하기 위한 코드이다.
- 임시 저장을 사용하는 이유는 폼으로 질문 데이터를 저장할 경우 Question모델의 create_date에 값이 설정되지 않아 오류가 발생하기때문이다.
3.(8) 폼에 부트스트랩 적용하기, labels 적용해서 Subject, Content 한글로 변경하기
class QuestionForm(forms.ModelForm):
class Meta:
model = Question
fields = ['subject', 'content']
# TextInput, Textarea 공간 늘려주고, 부트스트랩 적용
widgets = {
'subject' : forms.TextInput(attrs={'class' : 'form-control'}),
'content' : forms.Textarea(attrs={'class' : 'form-control','rows' : 10 })
}
# 라벨 제목 변경해주기
labels = {
'subject' : '제목',
'content' : '내용'
}
- {{ form.as_p }} 태그는 form 엘리먼트와 입력 항목을 자동으로 생성해주므로 편리하기는 하지만 부트스트랩을 적용할 수 없다는 단점이 있다.
3.(9) 답변 등록 기능에 장고 폼 적용하기
pybo/views.py
def question_create(request):
if request.method == 'POST': # post 요청일 때는 입력한 값들을 전달받아 DB에 저장
form = QuestionForm(request.POST)
if form.is_valid():
question = form.save(commit=False)
question.create_date = timezone.now()
question.save()
return redirect('pybo:index')
else: # Get 요청일 때는 단순히 질문등록 페이지 요청
form = QuestionForm()
context = {'form': form}
return render(request, 'pybo/question_form.html', context)
3. (10) 질문 상세 템플릿에 오류 표시 영역 추가하기
question_detail.html에 적용하기
{% csrf_token %}
{% if form.errors %}
<div class="alert alert-danger" role="alert">
{% for field in form %}
{% comment %} 필드 내에 에러가 있다면 아래 방법으로 처리 {% endcomment %}
{% if field.errors %}
<div>
{% comment %} 필드의 라벨을 굵게, 필드의 오류내역 표시 {% endcomment %}
<strong>{{ field.label }}</strong>
{{ field.errors }}
</div>
{% endif %}
{% endfor %}
</div>
{% endif %}
3.(11) answer 추가하기
answer도 같은 방식으로 추가합니다.
'웹 애플리케이션 > Django(장고)' 카테고리의 다른 글
[Django] 페이징 기능 (0) | 2023.04.19 |
---|---|
[Django] 템플릿 include (0) | 2023.04.19 |
[Django] 관리자 계정 및 페이지, 동적 URL, 별칭 (0) | 2023.04.13 |
[Django] 앱 생성, 데이터베이스 연동, ORM (1) | 2023.04.13 |
[Django] 시작하기(Conda, VS코드 쉽게) (0) | 2023.04.12 |