Django / form
Web/Django

Django / form

뉴비뉴 2019. 7. 1.

Form

블로그 글을 추가하거나 수정 기능

폼(양식, forms) 으로 강력한 인터페이스를 만들 수 있다.

 

장고 폼이 좋은 이유는 아무런 준비 없어도 양식을 만들 수 있고, ModelForm을 생성해 자동으로 모델을 결과물에 저장할 수 있다는 것이다.

 

-폼을 하나 만들어서 Post 모델에 적용해보자

-forms.py 라는 파일을 만든다.

-blog/forms.py

from django import forms # blog/forms 를 import 한다
from .models import Post


class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        field = ('title', 'text',)

class Meta : 폼을 만들기 위해서 어떤 model이 쓰여야 하는지 장고에 알려주는 구문이다. (model = Post)

 

이제 뷰에서 이 폼을 사용해 템플릿에서 보여주기만 하면 된다.

다음에는 링크, URL, 뷰 그리고 템플릿을 만들어보겠다.

URL

url(r'^post/new/$', views.post_new, name='post_new')
#post에 new라는 주소로 들어오게되면 views.post_new 뷰를 호출할 것이고, 이 패턴의 이름은 post_new 이다.

하지만 views.post_new 라는 view를 생성해주지 않았기 때문에 views.py에 가서

#views.py
from .forms import PostForm

def post_new(request):
    form = PostFrom()
    return render(request, 'blog/post_edit.html', {
        'form' : form,
    })

http://127.0.0.1:8000/post/new/ 에 접속해도 post_new안에 아무것도 정의하지 않았기 때문에 오류 페이지가 뜬다.

post_edit.html 작성

{% extends "blog/base.html"%}

{% block content %}
    <h1>New post</h1>
    <form method="POST" class="post-form">{% csrf_token%}
        {{ form.as_p }}
        <button type="submit" class="save btn btn-primary">Save</button>
    </form>
{% endblock %}

class="save btn btn-primary" 부분을 default로도 변경할 수 있다.

django form 에서 기본적인 틀을 제공해주는거 같다.

Form과 페이지링크

<a href="{% url 'post_new' %}" class="top-menu"><span class="glyphicon glyphicon-plus"></span></a>

+버튼을 누르면

[01/Jul/2019 16:33:30] "GET /post/new/ HTTP/1.1" 200 1378

위에서 댓글을 작성해서 SAVE 버튼을 누르면 

[01/Jul/2019 16:33:31] "POST /post/new/ HTTP/1.1" 200 1378

POST로 /post/new/ 로 데이터를 보낸다. 보내면 views.py 로 이동하게 된다.

게시글 업로드나 파일 업로드를 하면 request.POST 와 request.FILES에 데이터가 담겨 전송되게 된다.

 

끝으로, 새 블로그 글을 작성한 다음에 post_detail 페이지로 이동하게 끔 만들어보자.

#views.py

# request.POST, request.FILES

if request.method == 'POST': # 현재 요청이 POST라면
   form = PostForm(request.POST, request.FILES) # PostForm을 생성할 때 POST와 FILES에서 값을 가져와서 Form 생성
   if form.is_valid(): # 유효성 검사 빠진 값은 없는지 등등 # 실패하게되면 form에서 오류를 갖고 있게 된다.
      post = form.save(commit=False) # commit=False 란 넘겨진 데이터를 바로 Post모델에 저장하지 말라는 뜻이다.
      # 왜냐하면 작성자를 추가한 다음 저장해야되니까 그렇다. 대부분의 경우에는 commit=False를 쓰지 않고 바로 
      # form.save()를 사용해서 저장한다. 하지만 여기서는 작성자 정보를 추가하고 저장해야 하므로 commit=False
      # 를 사용하는 것이다.
      post.author = request.user
      post.published_date = timezone.now()
      post.save() # 변경사항(작성자 정보를 포함)을 유지할 것이고 새 블로그 글이 만들어질 것이다.
      return redirect('post_detail', post.pk) 
else:
   from = PostForm() # 빈 폼

하지만 /admin 에서 로그아웃이 되고, 새로운 글을 작성해서 넣으려고하면 오류가 발생한다.

해당 오류는 post.author = request.user 에서 발생한다. 왜냐하면 비인증 상태이기 때문에 그렇다.

request.user 로그인 유저 정보를 가져오는 것인데 로그아웃 되어있기 때문에 비인증 유저 정보가 가져와졌기 때문에

오류가 발생한다.

폼 수정하기(post_edit)

# post_detail.html

<a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}"><span class="glyphicon glyphicon-pencil"></span></a>
#버튼 추가

#views.py

def post_edit(request, pk):
    post = get_object_or_404(Post, pk=pk)

    return render(request, 'blog/post_edit.html', {
    })
#post_edit 생성

#urls.py

url(r'^post/(?P<pk>\d+)/edit/$', views.post_edit, name='post_edit'),
#url 추가 ex) http://127.0.0.1:8000/post/15/edit/

수정버튼 생성완료

#views.py
#post_new 의 if구문을 가져와서 붙여넣기 한 뒤 instance=post를 form = PostForm() 안에 추가

def post_edit(request, pk):
    post = get_object_or_404(Post, pk=pk)
    if request.method == 'POST':
        form = PostForm(request.POST, request.FILES, instance=post) #
        if form.is_valid():
            post = form.save(commit=False)
            post.author = request.user
            post.published_date = timezone.now()
            post.save()
            return redirect('post_detail', post.pk) 
    else:
        form = PostForm(instance=post) #
    return render(request, 'blog/post_edit.html', {
        'form': form #
    })

보안

로그인한 유저만 글 작성이 가능하게 만들고 싶다.

+버튼을 로그인한 유저만 보이게 하고 싶다.

{% if user.is_authenticated %} # 현재 유저가 login이 되어있다면 보여주겠다.
    <a href="{% url 'post_new' %}" class="top-menu">
        <span class="glyphicon glyphicon-plus"></span>
    </a>
{% endif%}

하지만 url 을 안다면 로그인을 하지 않아도 접속할 수 있다. 그걸 방지하기 위해서는

@login_required 를 해주면 된다. 하지만 너무 심화과정이기 때문에 나중에 보도록 하자.

 

 

댓글

💲 추천 글