1. 템플릿 상속
공통적으로 쓰는 코드를 하나 만들어 놓고 상속받아서 쓰는 것
바뀌는 부분만 block이라는 부분에 싸서 사용
- blog/templates/blog/base.html
<!DOCTYPE html>
{% load static %}
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Blog List</title>
{% load static %}
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap-theme.min.css" integrity="sha384-6pzBo3FDv/PJ8r2KRkGHifhEocL+1X2rVCTTkUfGk7/0pbek5mMa1upzvWbrUbOZ" crossorigin="anonymous">
<!-- google lobster font-->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext"
type="text/css">
<!-- 개발자 정의 CSS-->
<link rel="stylesheet" href="{% static 'css/blog.css' %}">
<!-- favicon 적용하기 -->
<link rel="shortcut icon" href="{%static 'favicon.ico'%}">
</head>
<body>
<div class="page-header">
<h1><a href="/">Django Blog</a></h1>
</div>
<div class="content container">
<div class="row">
<div class="col-md-8">
{% block content %}
{% endblock %}
</div>
</div>
</div>
{% comment "Optional note" %}
Server comment
{% endcomment %}
<!-- html Client Comment -->
</body>
</html>
- blog/templates/blog/post_edit.html
{% extends 'blog/base.html' %}
{% block content%}
{% for post in posts %}
<div class="post">
<div class="date">
<p>published : {{post.published_date}}</p>
</div>
<h1><a href="https://naver.com">{{post.title|title}}</a></h1>
<p>{{post.text|linebreaksbr}}</p>
</div>
{% empty %}
<div>요청하신 Post가 존재하지 않습니다. </div>
{% endfor %}
{% endblock %}
2. 상세페이지
- post_detail.html
{% extends 'blog/base.html' %}
{% block content%}
<div class="post">
{% if post.published_date%}
<div class="date">
{{post.published_date}}
</div>
{% endif %}
<h1>{{post.title|title}}</h1>
<p>{{post.text|linebreaksbr}}</p>
</div>
{% endblock %}
- view.py
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse
from django.utils import timezone
from .models import Post
# Post 목록
def post_list(request):
#name = 'Django'
# return HttpResponse('''
# <h2>Post List</h>
# <p>웰컴 {name}!!!</p>
# <p>{content}<p/>'''.format(name=name, content=request.content_type))
posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
return render(request, 'blog/post_list.html', {'posts': posts})
def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, 'blog/post_detail.html', {'post': post})
- urls.py
from django.urls import path
from . import views
urlpatterns = [
# loacalhost:8080/
path('', views.post_list, name='post_list'),
# localhost:8080/post/5
path('post/<int:pk>/', views.post_detail, name='post_detail_test')
]
- post_list.html
{% extends 'blog/base.html' %}
{% block content%}
{% for post in posts %}
<div class="post">
<div class="date">
<p>published : {{post.published_date}}</p>
</div>
<h1><a href="{% url 'post_detail_test' pk=post.pk %}">{{post.title|title}}</a></h1>
<p>{{post.text|linebreaksbr}}</p>
</div>
{% empty %}
<div>요청하신 Post가 존재하지 않습니다. </div>
{% endfor %}
{% endblock %}
- 결과확인
3. Django Form
https://www.w3schools.com/Bootstrap/bootstrap_ref_comp_glyphs.asp
- blog/froms.py
from django import forms
from .models import Post
# validator 함수 정의
# title 입력필드의 길이 체크 < 3
def min_length_3_validator(value):
if len(value) < 3:
raise forms.ValidationError('title은 3글자 이상 입력해주세요')
# PostFrom 클래스 선언
class PostForm(forms.Form):
# title = forms.CharField()
title = forms.CharField(validators=[min_length_3_validator])
text = forms.CharField(widget=forms.Textarea)
# PostModelFrom 클래스 선언
class PostModelForm(forms.ModelForm):
# title = forms.CharField()
# title = forms.CharField(validators=[min_length_3_validator])
# text = forms.CharField(widget=forms.Textarea)
class Meta:
model = Post
fields = ('title', 'text',)
- blog/models.py
from django.db import models
from django.utils import timezone
from django import forms
def min_length_3_validator(value):
if len(value) < 3:
raise forms.ValidationError('제목은 3글자 이상 입력해주세요')
# Create your models here.
class Post(models.Model):
# 작성자
author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
# 제목
title = models.CharField(max_length=200, validators=[min_length_3_validator])
# 내용
text = models.TextField()
# 작성일자
created_date = models.DateTimeField(default=timezone.now)
# 게시일자
published_date = models.DateTimeField(blank=True, null=True)
# 필드 추가 - 삭제할 예정
#test = models.TextField()
# 게시 일자에 현재 날짜를 대입해주는 함수
def publish(self):
self.published_date = timezone.now()
self.save()
# 객체 주소 대신 글제목을 반한해주는 toString()함수
def __str__(self):
return self.title
- blog/views.py
from django.shortcuts import render, get_object_or_404, redirect
from django.http import HttpResponse
from django.utils import timezone
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from .models import Post
from .forms import PostForm
from .forms import PostModelForm
# Post 목록
def post_list(request):
#name = 'Django'
# return HttpResponse('''
# <h2>Post List</h>
# <p>웰컴 {name}!!!</p>
# <p>{content}<p/>'''.format(name=name, content=request.content_type))
posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
return render(request, 'blog/post_list.html', {'posts': posts})
def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, 'blog/post_detail.html', {'post': post})
@login_required
def post_new(request):
if request.method == "POST":
# Form 데이터를 입력하고 등록요청 시 보여주는 부분
form = PostForm(request.POST)
# Form 데이터가 clean 한 상태
if form.is_valid():
# PostForm 으로 저장하는 법
print(form.cleaned_data)
post = Post.objects.create(author=User.objects.get(username=request.user),
published_date=timezone.now(),
title=form.cleaned_data['title'],
text=form.cleaned_data['text'])
# Post ModelForm 으로 저장하는 법
# title, text 필드의 값이 저장된다.
# post = form.save(commit=False)
# post.author = User.objects.get(username=request.user)
# post.published_date = timezone.now()
# DB에 등록됨
# post.save()
return redirect('post_detail_test', pk=post.pk)
else:
# 등록 Form 보여주는 부분
form = PostForm()
return render(request, 'blog/post_edit.html', {'form': form})
@login_required
def post_edit(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == "POST":
form = PostModelForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.author = User.objects.get(username=request.user)
post.published_date = timezone.now()
post.save()
return redirect('post_detail_test', pk=post.pk)
else:
form = PostModelForm(instance=post)
return render(request, 'blog/post_edit.html', {'form': form})
@login_required
def post_delete(request, pk):
post = get_object_or_404(Post, pk=pk)
post.delete()
return redirect('post_list')
- blog/templates/blog/base.html
<!DOCTYPE html>
{% load static %}
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Blog List</title>
{% load static %}
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap-theme.min.css" integrity="sha384-6pzBo3FDv/PJ8r2KRkGHifhEocL+1X2rVCTTkUfGk7/0pbek5mMa1upzvWbrUbOZ" crossorigin="anonymous">
<!-- google lobster font-->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext"
type="text/css">
<!-- 개발자 정의 CSS-->
<link rel="stylesheet" href="{% static 'css/blog.css' %}">
<!-- favicon 적용하기 -->
<link rel="shortcut icon" href="{%static 'favicon.ico'%}">
</head>
<body>
<div class="page-header">
{% if user.is_authenticated %}
<a href="{% url 'post_new' %}" class="top-menu">
<span class="glyphicon glyphicon-plus"></span>
</a>
<p class="top-menu">Hello {{user.username}}
<small>(<a href="{% url 'logout' %}?next={{request.path}}">Log out</a> )</small></p>
{% else %}
<a href="{% url 'post_new' %}" class="top-menu">
<span class="glyphicon glyphicon-plus"></span>
</a>
{% endif %}
<h1><a href="/">Django Blog</a></h1>
</div>
<div class="content container">
<div class="row">
<div class="col-md-8">
{% block content %}
{% endblock %}
</div>
</div>
</div>
{% comment "Optional note" %}
Server comment
{% endcomment %}
<!-- html Client Comment -->
</body>
</html>
- blog/templates/blog/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-default">Save</button>
</form>
{% endblock %}
- blog/templates/blog/post_detail.html
{% extends 'blog/base.html' %}
{% block content%}
<div class="post">
{% if post.published_date%}
<div class="date">
{{post.published_date}}
</div>
{% endif %}
{% if user.is_authenticated %}
<a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}">
<span class="glyphicon glyphicon-pencil"></span>
</a>
<a class="btn btn-default" href="{% url 'post_delete' pk=post.pk %}">
<span class="glyphicon glyphicon-remove"></span>
</a>
{% endif %}
<h1>{{post.title|title}}</h1>
<p>{{post.text|linebreaksbr}}</p>
</div>
{% endblock %}
- blog/templates/registration/login.html
{% extends "blog/base.html" %}
{% block content %}
{% if form.errors %}
<p>이름과 비밀번호가 일치하지 않습니다. 다시 시도해주세요.</p>
{% endif %}
<form method="post" action="{% url 'login' %}">
{% csrf_token %}
<table class="table table-bordered table-hover">
<tr>
<td>{{form.username.label_tag}}</td><td>{{form.username}}</td>
<td>{{form.password.label_tag}}</td><td>{{form.password}}</td>
</tr>
</table>
<input type="submit" value="login" class="btn btn-primary btn-lg"/>
<input type="hidden" name="next" value="{{next}}"/>
</form>
{% endblock %}
- blog/urls.py
from django.urls import path
from . import views
urlpatterns = [
# loacalhost:8080/
path('', views.post_list, name='post_list'),
# localhost:8080/post/5
path('post/<int:pk>/', views.post_detail, name='post_detail_test'),
# localhost:8080/post/new
path('post/new/', views.post_new, name='post_new'),
path('post/<int:pk>/edit', views.post_edit, name='post_edit'),
path('post/<int:pk>/delete/', views.post_delete, name='post_delete'),
]
- /urls.py
from django.contrib import admin
from django.urls import path, include
from django.contrib.auth import views as auth_views
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('blog.urls')),
path('accounts/login/', auth_views.LoginView.as_view(template_name="registration/login.html"), name="login"),
path('account/logout/', auth_views.LogoutView.as_view(), {'next_page': None}, name="logout"),
]
- /settings.py
https://docs.djangoproject.com/en/3.0/topics/auth/default/
'Python > Django' 카테고리의 다른 글
django 와 mongodb연동 (0) | 2020.08.17 |
---|---|
페이지네이션 (0) | 2020.08.11 |
Django 댓글기능 추가 (0) | 2020.08.07 |
Django (Migrate / URLConf / View / Template / QuerySet / Bootstrap) (0) | 2020.08.05 |
Django설치 및 설정 & 간단한 게시판 만들기 (0) | 2020.08.04 |