"게시판만들기 3. 게시글 쓰기"의 두 판 사이의 차이
110번째 줄: | 110번째 줄: | ||
board/create.html을 만들고 body 안에 다음이 들어가게 한다.<syntaxhighlight lang="html+django"> | board/create.html을 만들고 body 안에 다음이 들어가게 한다.<syntaxhighlight lang="html+django"> | ||
<body> | <body> | ||
− | + | <!--해당 링크로 보낼거니, action속성은 없어도 된다.--> | |
<form action="{% url 'board:create' %}" method="POST"> | <form action="{% url 'board:create' %}" method="POST"> | ||
{% csrf_token %} | {% csrf_token %} | ||
118번째 줄: | 118번째 줄: | ||
</body> | </body> | ||
+ | </syntaxhighlight>action옵션 값을 비워두면 해당 링크로 요청을 보낸다. | ||
+ | |||
+ | <nowiki>{{form}}</nowiki>는 폼으로부터 전달된 객체. 입력을 위한 코드를 자동으로 작성한다. | ||
+ | ===에러표시 하기=== | ||
+ | 적합한 제목형태가 아니거나, 모델에서 제약한 데이터 형식에 맞지 않는 경우 에러가 뜨는데, 어떤 부분에서 에러가 났는지 사용자에게 알려주어야 한다. 탬플릿에 다음과 같이 추가하자. | ||
+ | |||
+ | {% csrf_token %} 태그 아래에 넣으면 적당하다.<syntaxhighlight lang="html"> | ||
+ | {% if form.errors %} <!--폼에서 에러가 난 경우--> | ||
+ | <div class="alert alert-danger" role="alert"> | ||
+ | {% for field in form %}<!--모든 필드를 뒤지며 에러를 찾는다.--> | ||
+ | {% if field.errors %} | ||
+ | <strong>{{ field.label }}</strong><!--에러가 난 필드의 라벨에 굵음 처리--> | ||
+ | {{ field.errors }}<!--어떤 에러인지 보여준다.--> | ||
+ | {% endif %} | ||
+ | {% endfor %} | ||
+ | </div> | ||
+ | {% endif %} | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | ===폼을 안쓸 때 에러표시하기=== | ||
+ | 딱히 방법은 없다. view의 context 안에 error_message라고 담아서 보내면 된다. | ||
+ | |||
+ | view에서 발생한 에러는 탬플릿에 <nowiki>{{error_message}}</nowiki> 변수로 전달된다. view에서 발생한 에러메시지를 그대로 보여주는 것이다. | ||
+ | view에서 try-except를 이용하거나 if를 이용해 에러메시지를 보낸다.<syntaxhighlight lang="python"> | ||
+ | try: | ||
+ | 어쩌구저쩌구 | ||
+ | except(KeyError, 조건):#에러가 나면서 조건을 만족시키면 실행 | ||
+ | context={'error_message':'담을메시지'} | ||
+ | return render(어쩌구,저쩌구,저쩌구) | ||
+ | else:#에러가 발생하지 않거나 위에 해당하는 에러가 아니면 실행 | ||
+ | 명령 | ||
+ | </syntaxhighlight>template에선 아래와 같이 사용한다.<syntaxhighlight lang="html"> | ||
+ | {% if error_message %} <!-- view에서 에러가 난 경우--> | ||
+ | <p>{{error_message}}</p><!-- 에러메시지를 보여준다. --> | ||
+ | {% endif %} | ||
+ | </syntaxhighlight>입력값을 저장이 아닌, 그대로 반환하게 하면 form을 사용할 때처럼 페이지가 새로고침 되어도 기존 입력내용들을 보존할 수 있다. | ||
== 관련 에러 == | == 관련 에러 == | ||
2021년 6월 25일 (금) 13:16 판
1 개요
게시글은 써야 맛이지.
2 글쓰기 버튼 만들기
글 목록이 보여주는 board/list.html의 표 아래에 다음을 추가한다.
<a href="{% url 'board:create' %}" class="btn btn-primary">글쓰기</a>
3 url 매핑
3.1 board.urls에 추가
urls.py 안에 필요한 기능을 다 담아주어야 한다. urlpatterns 안에 다음을 추가한다.
(뷰의 설정이나, import방식에 따라 뷰를 불러오는 방식이 달라질 수 있다.)
일반적으로 코드를 짜는 경우 | 제네릭 뷰를 사용하는 경우 |
---|---|
from django.urls import path
from . import views #해당 앱의 뷰를 불러온다.
app_name = 'board'
urlpatterns = [
...
path('create/', views.create, name='create'),#글의 작성화면
...
]
|
함수명을 바꾸어주어야 한다.
views.클래스뷰명.as_view()), 형태로. 클래스형 뷰임을 지정해주기 위해. |
4 form 작성
board/forms.py를 만든 후 다음과 같이 입력한다.
자동으로 에러검사도 해주고 편리해 사용하지 않을 이유가 없어 form을 적극적으로 활용한다.
from django import forms
from .models import Writing # 폼을 적용할 모델을 불러온다.
class WritingForm(forms.ModelForm):
class Meta:
model = Writing # 사용할 모델
fields = ['subject', 'content'] # 폼으로 입력할 필드를 입력해준다.
# fields에 '__all__'을 따옴표까지 함께 넣어주면 모든 필드를 가져오라는 명령이 된다.
5 view 작성
board.views.py에 다음과 같은 함수를 추가한다.
일반적으로 페이지를 불러오는 것과 데이터를 저장하는 데 같은 링크를 사용한다.
페이지 요청방식에 따라 달리 작동하게 하면 되는데, POST요청이면 데이터를 저장.
(링크를 타고 오는 경우, GET 요청으로 들어온다.)
일반적으로 코드를 짤 경우 | 제네릭뷰(클래스형 뷰)를 쓰는 경우 |
---|---|
def create(request):
from django.shortcuts import redirect
from .forms import WritingForm
from django.utils import timezone # 시간입력용
if request.method == 'POST': # 포스트로 요청이 들어온다면... 글을 올리는 기능.
form = WritingForm(request.POST) # 폼을 불러와 내용입력을 받는다.
if form.is_valid(): # 폼에서 에러처리. 문제가 없으면 다음으로 진행.
writing = form.save(commit=False) # commit=False는 저장을 잠시 미루기 위함.(입력받는 값이 아닌, view에서 다른 값을 지정하기 위해)
writing.author = request.user # 추가한 속성 author 적용
writing.create_date = timezone.now() #현재 작성일시 자동저장
writing.save()
return redirect('board:list') #작성이 끝나면 목록화면으로 보낸다.
else: #포스트 요청이 아니라면.. form으로 넘겨 내용을 작성하게 한다.
form = WritingForm()
context = {'form': form} # 폼에서 오류가 있으면 오류의 내용을 담아 create.html로 넘긴다.
# 없으면 그냥 form 작성을 위한 객체를 넘긴다.
return render(request, 'board/create.html', context)
글 작성view 뿐 아니라 수정view를 작성할 때에도 마찬가지이다. |
from django.views import generic
from django.urls import reverse_lazy # 이건 뭐지;;?
class create(generic.CreateView):
model = Question
feilds = ['필드명', '필드명',...] # 작성할 필드명 지정
template_name_suffix='_create'
# 사용하는 탬플릿 명을 '모델명_create.html'로 바꾼다는 의미. 접미사만 바꾼다.
# 기본 탬플릿은 '모델명_form.html'로 나타난다.
def form_valid(self, form): # 폼에 이상이 없으면 실행.
temp = form.save(commit=False) # 임시 저장. 폼 외의 다른 내용을 조작하고 싶을 때 사용한다.
조작
temp.save() # 최종 저장
return super().form_valid(form)
def get_success_url(self): # 기존 함수를 덧쓴다. 작성 후에 해당 글을 보여주게끔.
return reverse('pool:detail', kwargs={'pk': self.object.question.pk})
|
6 template 작성
board/create.html을 만들고 body 안에 다음이 들어가게 한다.
<body>
<!--해당 링크로 보낼거니, action속성은 없어도 된다.-->
<form action="{% url 'board:create' %}" method="POST">
{% csrf_token %}
{{ form }}
<input type="submit" value="제출">
</form>
</body>
action옵션 값을 비워두면 해당 링크로 요청을 보낸다.
{{form}}는 폼으로부터 전달된 객체. 입력을 위한 코드를 자동으로 작성한다.
6.1 에러표시 하기
적합한 제목형태가 아니거나, 모델에서 제약한 데이터 형식에 맞지 않는 경우 에러가 뜨는데, 어떤 부분에서 에러가 났는지 사용자에게 알려주어야 한다. 탬플릿에 다음과 같이 추가하자.
{% csrf_token %} 태그 아래에 넣으면 적당하다.
{% if form.errors %} <!--폼에서 에러가 난 경우-->
<div class="alert alert-danger" role="alert">
{% for field in form %}<!--모든 필드를 뒤지며 에러를 찾는다.-->
{% if field.errors %}
<strong>{{ field.label }}</strong><!--에러가 난 필드의 라벨에 굵음 처리-->
{{ field.errors }}<!--어떤 에러인지 보여준다.-->
{% endif %}
{% endfor %}
</div>
{% endif %}
6.2 폼을 안쓸 때 에러표시하기
딱히 방법은 없다. view의 context 안에 error_message라고 담아서 보내면 된다.
view에서 발생한 에러는 탬플릿에 {{error_message}} 변수로 전달된다. view에서 발생한 에러메시지를 그대로 보여주는 것이다.
view에서 try-except를 이용하거나 if를 이용해 에러메시지를 보낸다.
try:
어쩌구저쩌구
except(KeyError, 조건):#에러가 나면서 조건을 만족시키면 실행
context={'error_message':'담을메시지'}
return render(어쩌구,저쩌구,저쩌구)
else:#에러가 발생하지 않거나 위에 해당하는 에러가 아니면 실행
명령
template에선 아래와 같이 사용한다.
{% if error_message %} <!-- view에서 에러가 난 경우-->
<p>{{error_message}}</p><!-- 에러메시지를 보여준다. -->
{% endif %}
입력값을 저장이 아닌, 그대로 반환하게 하면 form을 사용할 때처럼 페이지가 새로고침 되어도 기존 입력내용들을 보존할 수 있다.
7 관련 에러
7.1 Cannot assign "<SimpleLazyObject: <django.contrib.auth.models.AnonymousUser object at *********>>": "Writing.author" must be a "User" instance.
이 에러는 로그인이 되지 않았을 때 유저객체를 모델에 연결하지 못해 발생하는 에러이다.