Old Branch

Django - tweetme 소셜서비스 구현해보기 (13) - Create Tweet View

woolbro 2019. 10. 30. 01:37
반응형

이번 포스팅에서는 지난 포스팅에서 작성한 Form을 가지고 view를 만들어 보도록 하겠습니다.

 

이미 작성했던 전체 리스트를 보여주는 view, 하나의 Detail Tweet을 보여주는 view 두가지를 작성 했는데요, 이번 포스팅에서는

 

위의 view들과 같이 작동하는 Create, Update, Delete View 들을 작성 해 보려고 합니다.

 

이번 포스팅의 모든 소스코드는 Github에 업로드 되어 있습니다.

 

 


1.  Create View 작성하기

글을 작성할 때 필요한 view를 작성을 해 보도록 하겠습니다.

 

tweet의 models.py에 create_view를 작성 해 줍니다.

from django.views.generic import DetailView, ListView, CreateView
from .forms import TweetModelForm

class TweetCreateView(CreateView):
    form_class = TweetModelForm
    template_name = 'tweets/create_view.html'

template_name을 create_view.html로 명시 해 주었으니, 필요한 html을 만들어주어야 합니다.

 

template > tweets > html파일을 아래와 같이 작성 해 줍니다.

<from class = 'form' method='POST' action=''>
    {% csrf_token %}
    {{form.as_p}}
    <input type="submit" value="Twwet"/>
</form>

이제, view와 template은 연결이 되었습니다. 이 연결된 view 를 url로 이어주도록 하겠습니다.

 

tweet의 urls.py에서 TwwetCreateView를 /create의 url을 갖도록 이어줍니다.

from django.conf.urls import url,include
from django.conf import settings
from .views import *

urlpatterns = [
    url(r'^$', TweetListView.as_view(), name='list'),
    url(r'^create/$', TweetCreateView.as_view(), name='create'),
    url(r'^(?P<pk>\d+)/$', TweetDetailView.as_view(), name='detail')
]

서버를 가동시키고, localhost:8000/tweet/create로 접속 해 줍니다.

 

위와같은 결과화면이 나오게 됩니다.

 

방금 작성한 TweetCreateView는 user가 tweet을 작성 할 수 있도록 해 주는 view입니다. 위의 화면을 보면, 작성 form 중에 content외에 user를 선택 할 수도 있도록 작성이 되어 있는데요, 

 

지난 포스팅에서 작성 한 form에서 User 란을 없애주도록 합시다.

 

tweet의 forms.py에서 아래의 User 부분을 주석처리 해 줍니다.

from django import forms

from .models import Tweet

class TweetModelForm(forms.ModelForm):
    class Meta:
        model = Tweet
        fields = [
            #"user", #이 부분을 주석처리 해 주세요
            "content"
        ]

다시한번 화면을 확인 해 보면, user란이 없어 진 것을 확인 할 수 있습니다.

 

이제 완료 된 화면을 사용 해보도록 하겠습니다. 글을 작성하고 Tweet을 눌러주면!!

 

.....

에러를 보니 tweet.user_id는 비어있을수 없다고 나와있는데, 우리가 이전에 forms.py에서 User를 주석처리 해주어서 선택을 못합니다.

 

때문에 일어나는 현상인데, views.py의 TweetCreateView에 다음과 같이 추가 해 주도록 하겠습니다.

class TweetCreateView(CreateView):
    form_class = TweetModelForm
    template_name = 'tweets/create_view.html'
    success_url = "/tweet/create/"
    def form_valid(self, form):
        form.instance.user = self.request.user
        return super(TweetCreateView,self).form_valid(form)

여기서, success_url과 def form_valid를 추가 해 주었습니다.

먼저 def form_valid는 위의 오류인 user가 들어가지 않는 문제를 해결 해 줍니다.

form의 유저는 request를 주는 유저를 가지고 스스로에게 리턴 주기 때문에 전송하는 form은 user를 가져갈 수 있게 됩니다.

 

success_url은, template에서 전송을 마친 후 redirect하는 곳인데요, /tweet/create/로 주어서 다시 작성 폼으로 돌아가도록 설정 해 주었습니다.

 

위의 view는 클래스로 작성한 view이고, 함수형으로 작성하면 아래와 같습니다.

def tweet_create_view(request):
    form = TweetModelForm(request.POST or None)

    if form.is_valid():
        instance = form.save(commit = False)
        instance.user = request.user
        instance.save()
    context={
        "form" : form
    }
    return render(request, 'tweets/create_view.html',context)

 

 

2. User에 authentication 부여하기

위의 코드는 현재 우리가 admin에 로그인 한 후에, 해당 브라우저에서 계속 작업을 했기 때문에 로그인한 사용자가 남아있습니다.

그래서, request user에 우리 로그인이 없을때에는 아래와 같은 오류가 납니다.

위의 오류를 해결해주도록 하겠습니다.

 

방금 작성했던 TweetCreateView에 추가 해 주도록 하겠습니다.

class TweetCreateView(CreateView):
    form_class = TweetModelForm
    template_name = 'tweets/create_view.html'
    success_url = "/tweet/create/"

    def form_valid(self, form):
        if self.request.user.is_authenticated:    
            form.instance.user = self.request.user
            return super(TweetCreateView,self).form_valid(form)
        else:
            return self.form_invalid(form)

위의 코드를 적용했다면, request가 허가받지 않은 사용자였을 때에, tweet 은 작성되지 않고 같은자리에 계속 머물게 됩니다.

 

사용자 입장에서는 어떤 오류가 난지 모르기 때문에, 사용자에게 이유도 알려주도록 하겠습니다.

from django.shortcuts import render,get_object_or_404
from django.views.generic import DetailView, ListView, CreateView
from django.forms.utils import ErrorList
from django import forms


from .models import Tweet
from .forms import TweetModelForm
# Create your views here.

class TweetCreateView(CreateView):
    form_class = TweetModelForm
    template_name = 'tweets/create_view.html'
    success_url = "/tweet/create/"

    def form_valid(self, form):
        if self.request.user.is_authenticated:    
            form.instance.user = self.request.user
            return super(TweetCreateView,self).form_valid(form)
        else:
            form._errors[forms.forms.NON_FIELD_ERRORS] = ErrorList(["로그인 해야합니다."])
            return self.form_invalid(form)

form과 ErrorList를 각각 추가 해 주고, "로그인 해야합니다" 라는 alert을 설정 해 주도록 하겠습니다.

 

위와같이 나오면 성공입니다!

 

이런 기능들을 모아서 작성 해 주도록 하겠습니다. 위에서 작성한 form_valid를 가져와 tweet아래에 mixin.py을 생성하고 넣어주겠습니다.

tweet>mixins.py

from django.forms.utils import ErrorList
from django import forms


class FormUserNeededMixin(object):
    def form_valid(self, form):
        if self.request.user.is_authenticated:    
            form.instance.user = self.request.user
            return super(FormUserNeededMixin,self).form_valid(form)
        else:
            form._errors[forms.forms.NON_FIELD_ERRORS] = ErrorList(["로그인 해야합니다."])
            return self.form_invalid(form)

위의 내용을 작성했으니, 작성했었던 views.py의 from valid는 빼주고 위의 클래스를 적용시켜주겠습니다.

tweet>views.py

from django.shortcuts import render,get_object_or_404
from django.views.generic import DetailView, ListView, CreateView
from django.forms.utils import ErrorList
from django import forms


from .mixins import FormUserNeededMixin
from .models import Tweet
from .forms import TweetModelForm
# Create your views here.

class TweetCreateView(FormUserNeededMixin,CreateView):
    form_class = TweetModelForm
    template_name = 'tweets/create_view.html'
    success_url = "/tweet/create/"

 

views.py의 코드는 훨씬 깔끔하고 명료해졌고, Error는 관리하기 쉬워졌습니다.

적용시켜 보았으니, mixin 모듈에서 이미 작성이 되어있는 login Valid를 비슷한 방법으로 사용 해 보도록 하겠습니다.

 

tweet>views.py입니다.

from django.contrib.auth.mixins import LoginRequiredMixin
from .mixins import FormUserNeededMixin
from .models import Tweet
from .forms import TweetModelForm
# Create your views here.

class TweetCreateView(LoginRequiredMixin,FormUserNeededMixin,CreateView):
    form_class = TweetModelForm
    template_name = 'tweets/create_view.html'
    success_url = "/tweet/create/"
    login_url = "/admin/login/"

login이 필요하면, 알림만 띄우는 것이 아니라 로그인 할 수 있는 곳으로 redirect 해 주는 것이 나을 것 같네요 :)

 

위의 코드를 작성 한 후, 브라우저를 모두 끈 후에 localhost:8000/tweet/create에 넣어보면 /admin/login 창이 나오는 것을 확인 할 수 있습니다.