Class Based View
https://docs.djangoproject.com/en/3.2/topics/class-based-views/
만들어진 이유
어떨 때 사용해야하는가?
Function Based View
Class Based View
REST API 만들 때 유용
CBV의 장점
CBV 사용 가이드라인
제너릭 뷰의 4가지 분류
model
queryset
queryset
을 사용하면 model
속성은 무시된다.template_name
context_object_name
paginate_by
date_field
form_class
success_url
def get_qeuryset()
queryset
속성을 반환한다. queryset
속성이 지정되지 않은 경우 모델 매니저 클래스의 all() 메소드를 호출해 QuerySet 객체를 생성해 반환한다.def get_context_data(**kwargs)
def get_queryset()
메소드 오버라이딩앱이름/templates/앱이름/about1.html
만들기앱이름/urls.py
from django.urls import path
from django.views.generic import TemplateView
urlpatterns = [
path('about/', TemplateView.as_view(template_name="앱이름/about1.html")),
]
앱이름/templates/앱이름/about2.html
만들기
앱이름/views.py
from django.views.generic import TemplateView
class AboutView(TemplateView):
template_name = "앱이름/about2.html"
앱이름/urls.py
from django.urls import path
from some_app.views import AboutView
urlpatterns = [
path('about2', AboutView.as_view()),
]
앱이름/models.py
python manage.py makemigrations
python manage.py migrate
from django.db import models
class Article(models.Model) :
title = models.CharField(max_length=50)
django seed를 통해 더미데이터 넣어주기
python manage.py seed articles --number=10
앱이름/urls.py
path('index/', views.index)
앱이름/views.py
from .models import Article
def index(request) :
if request.method=="GET" :
articles = Articles.objects.all()
context = {
'articles' : articles
}
return render(request, 'articles/index.html', context)
앱이름/templates/앱이름/index.html
만들어주기
앱이름/urls.py
from views import IndexView
urlpatterns = [
...
path('index2/', IndexView.as_view())
]
앱이름/views.py
from djagno.views import View
class IndexView(View) :
def get(self, request) : # request.method GET 방식일 때 작동할 내용
articles = Articles.objects.all()
context = {
'articles' : articles
}
return render(request, 'articles/index2.html', context)
https://docs.djangoproject.com/en/3.2/topics/class-based-views/generic-display/
https://docs.djangoproject.com/en/3.2/ref/class-based-views/generic-display/#listview
django 코드로 보기
class ListView(MultipleObjectTemplateResponseMixin, BaseListView)
class BaseListView(MultipleObjectMixin, View):
class MultipleObjectMixin(ContextMixin)
앱이름/urls.py
path('', ArticleListView.as_view(), name='index')
앱이름/views.py
앱이름/article_list.html
을 찾을 수 없다는 에러가 뜨게 됨앱이름/클래스이름_list.html
으로 연결되게 함 - 클래스이름 맨앞은 소문자로 변경됨from django.views.generic import ListView
class ArticleListView(ListView) :
model = Article
앱이름/templates/앱이름/article_list.html
만들기
object_list
로 가져올 수 있음<h1>
article index
</h1>
{{ object_list }}
{% for object in object_list %}
{% object.title %}
{% endfor %}
object라고 쓰는게 불편하니 바꿔보자
앱이름/views.py > ArticleListView
from django.views.generic import ListView
class ArticleListView(ListView) :
model = Article
context_object_name = 'articles' # object가 articles가 됨
queryset = Article.objects.order_by('-id') # 이걸로 순서도 정해줄 수 있음
앱이름/templates/앱이름/article_list.html
<h1>
article index
</h1>
{{ articles }}
{% for article in articles %}
{% article.title %}
{% endfor %}
추가 컨텍스트 넣기
앱이름/views.py > ArticleListView
from django.views.generic import ListView
class ArticleListView(ListView) :
model = Article
context_object_name = 'articles' # object가 articles가 됨
def get_context_data(self, **kwargs) :
context = super().get_context_data(self, **kwargs)
# class MultipleObjectMixin(ContextMixin) 내용 확인
context['name'] = 'change'
return context
앱이름/urls.py
path('<int:pk>/', ArticleDetailVeiw.as_view(), name='detail')
앱이름/views.py
앱이름/article_detail.html
을 찾을 수 없다는 에러from django.views.generic import DetailView
class ArticleDetailVeiw(DetailVeiw) :
model= Article
앱이름/templates/앱이름/article_detail.html
만들기
<h1>
article index
</h1>
{{ articles }}
{% for article in articles %}
{% article.title %}
{% endfor %}
앱이름/models.py
python manage.py makemigrations
python manage.py migrate
from django.db import models
from django.urls import reverse
class Article(models.Model) :
title = models.CharField(max_length=50)
def get_absolute_url(self):
return reverse('articles:detail', kwargs={'pk': self.pk})
# 글을 작성하고면 해당 글의 detail페이지로 이동
앱이름/views.py
from django.views.generic import CreateView
class ArticleCreateView(CreateView) :
model = Article
fields = '__all__'
# 앱이름/article_form.html 으로 연결됨
앱이름/urls.py
path('create/', ArticleCreateView.as_view(), name='create')
앱이름/templates/앱이름/article_form.html
<h1>
form
</h1>
<form action="" method="POST">
{% csrf_token %}
{{ form }}
<input type="submit">
</form>
앱이름/views.py
from django.views.generic import UpdateView
class ArticleUpdateView(UpdateView) :
model = Article
fields = '__all__'
# 앱이름/article_form.html 으로 연결됨
앱이름/urls.py
path('<int:pk>/update/', ArticleUpdateView.as_view(), name='update')
앱이름/views.py
from django.views.generic import DeleteView
from django.urls import reverse_lazy
class ArticleDeleteView(DeleteView) :
model = Article
success_url = reverse_lazy('articles:index')
# delete에 성공하면 어디로 redirect 시킬지
# reverse_lazy의 경우 urls.py 의 app_name과 url_name을 참조해서 url을 만드는 역할
앱이름/urls.py
path('<int:pk>/delete/', ArticleDeleteView.as_view(), name='delete')
앱이름/templates/앱이름/article_confirm_delete.html
<h1>
delete
</h1>
<p>
정말 삭제하시겠습니까?
</p>
<form action="" method="POST">
{% csrf_token %}
<input type="submit">
</form>
accounts 앱 만들기
python manage.py startapp accounts
'accounts',
추가메인/urls.py
path('accounts/', include('django.contrib.auth.urls')),
127.0.0.1/accounts/login 으로 접속하게 되면 에러가 남
registration/login.html 을 찾는 에러를 만나게 됨
accounts/templates/registration/login.html
<form action="" method="POST">
{% csrf_token %}
{{ form }}
<input type="submit">
</form>
settings.py
LOING_REDIRECT_URL = 'articles:index'
추가앱이름/models.py
from django.db import models
from djagno.conf import settings
class Article(models.Model) :
title = models.CharField(max_length=50)
user = models.Foreign(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
def get_absolute_url(self):
return reverse('articles:detail', kwargs={'pk': self.pk})
앱이름/views.py > ArticleCreateView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import UpdateView
class ArticleCreateView(LoginRequiredMixin, UpdateView) : # LoginRequiredMixin 을 추가하여 로그인이 된 상태에서만 접근할 수 있도록 -> 로그인 안한 상태면 로그인 페이지로 이동됨
model = Article
fields = ('title', )
def form_valid(self, form) : # 글쓸 때 user 정보를 사용하기 위함
form.instance.user = self.request.user # 로그인 한 사람
return super().form_valid(form)
앱이름/urls.py
from django.urls import path
from . import views
app_name = 'movies'
urlpatterns = [
path('review/<int:review_pk>/', views.review_detail),
]
앱이름/views.py
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
from django.shortcuts import get_object_or_404
from .models import Review
from .serializers import ReviewSerializer
@api_view(['GET', 'PUT', 'DELETE'])
def review_detail(request, review_pk):
review = get_object_or_404(Review, pk=review_pk)
if request.method == 'GET': # 리뷰 자세히 보기
serializer = ReviewSerializer(review)
return Response(serializer.data)
elif request.method == 'PUT': # 리뷰 수정
serializer = ReviewSerializer(review, data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
elif request.method == 'DELETE': # 리뷰 지우기
review.delete()
data={
'delete' : f"reivew {review_pk}번 글이 삭제 되었습니다"
}
return Response(data, status.HTTP_204_NO_CONTENT)
앱이름/urls.py
from django.urls import path
from . import views
from .views import Review_detail
app_name = 'movies'
urlpatterns = [
path('review/<int:review_pk>/', Review_detail.as_view()),
]
앱이름/views.py
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import status
from django.shortcuts import get_object_or_404
from .models import Review
from .serializers import ReviewSerializer
class Review_detail(APIView) :
def get_reivew(self, review_pk) :
review = get_object_or_404(Review, pk=review_pk)
return review
def get(self, request, review_pk) :
review = self.get_reivew(review_pk)
serializer = ReviewSerializer(review)
return Response(serializer.data)
def put(self, request, review_pk) :
review = self.get_reivew(review_pk)
serializer = ReviewSerializer(review, data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
def delete(self, request, review_pk) :
review = self.get_reivew(review_pk)
review.delete()
data={
'delete' : f"reivew {review_pk}번 글이 삭제 되었습니다"
}
return Response(data, status.HTTP_204_NO_CONTENT)