001-E4NKNRjrBqc. building blog by using django
@
# You should install Django
pip install Django
# After installing Django, you can use django-admin command
django-admin
@
# You can create django project
django-admin startproject myproject
cd myproject
tree .
# manage.py
# myproject
# __init__.py
# settings.py
# urls.py
# wsgi.py
# 1 directory, 5 files
@
# Since we will make blog, we use following command
python manage.py startapp blog
tree
# .
# blog
# __init__.py
# admin.py
# migrations
# __init__.py
# models.py
# tests.py
# views.py
# manage.py
# myproject
# __init__.py
# __pycache__
# __init__.cpython-35.pyc
# settings.cpython-35.pyc
# settings.py
# urls.py
# wsgi.py
# 4 directories, 13 files
@
# Open most top myproject folder by editor
@
# go to settings.py
# go to INSTALLED_APPS
# add 'blog'
@
# go to views.py
from django.shortcuts import render
def index(request):
return render(request, 'blog/index.html')
# go to urls.py
# go to urlpatterns
add url(r'^$', 'blog.views.index')
# type localhost:8000
# above one is matched with r'^$'
# then, index() in views.py is invoked
@
# Under blog/templates/blog/ folder, make index.html
@
# refresh server
python manage.py runserver
# go to localhost:8000
@
# go to index.html
# add,
Hello django
@
# If you want to add more views, go to urls.py
Find urlpatterns, add more patterns
urlpatterns = {
url(r'^admin/', include(admin.site.urls)),
url(r'^$', 'blog.views.index'),
# if localhost:8000/new/ fires, invoke post_new()
url(r'^new/', 'blog.views.post_new'),
}
@
# go to views.py
# add,
def post_new(request):
return render(request, 'blog/post_form.html')
@
# Let's talk about "model"
# We will create 2 models(post where we store posts, comment where we store comments) for blog
# go to models.py
from django.db import models
# Let's create Post class
# Post class inherits model.Model base class
class Post(model.Model):
# id member variables is automatically generated
# id = PositiveIntegerField(), primary_key
# I define member variables
# I configure title can store 100 characters
title = model.CharField(max_length=100)
# I configure content can store infinite characters
content = model.CharField()
# I configure autosave functionality of add time(only once) by using "auto_now_add=True"
created_at = models.DateTimeField(auto_now_add=True)
# I configure autosave functionality of update time(whenever) by using "auto_now=True"
updated_at = models.DateTimeField(auto_now=True)
@
# Go to settings.py
# Find INSTALLED_APPS
# You can see default apps which django provides
# django.contrib.admin
# django.contrib.auth
# django.contrib.contenttype
# django.contrib.sessions
# django.contrib.messages
# django.contrib.staticfiles
# 'blog'
python manage.py makemigrations blog
# Above apps can be applied into database by migration
python manage.py migrate
@
# Default database which is created when creating project is sqlite3
# Find db.sqlite3 file in project directory
# Open it with viewer
# You can see generated tables
# You can see blog_post table which contains each column(id, titles, content, created_at, updated_at)
# table naming convention
# appname_modelname
# blog_post
# blog app_post model
@
# go to blog/admin.py
from django.contrib import admin
from .models import Post
# I will use Post model in admin site
admin.site.register(Post)
# go to localhost:8000/admin
# you can see admin page
# this url is mapped to urls.py
# urlpatterns={
# (url(r'^admin/', include(admin.site.urls)),
# }
# Let's create admin account
python manage.py createsuperuser
username : username
email : optional(enter to pass)
password : pw
# login with created credential on admin page
# You can see Blog app Posts model
# You can add button to write post
@
# go to models.py
# in Post class, add,
def __str__(self):
return self.title
# Now, you can see title as you put
@
# Class dealing with unicode is different between python2 and python3
# In python2, you should use __unicode__()
# In python3, you should use __str__()
@
# If you use decorator "@python_2_unicode_compatible" on class Post(model.Model),
# you don't need to use __unicode__() in python2 when you use __str__()
# But I recommend you use only python3
@
# go to admin.py
# add,
class PostAdmin(admin.ModelAdmin):
list_display = ('id', 'title')
admin.site.register(Post, PostAdmin)
# You can see devided columns
# ID Title
# 1 aa
@
# When user goes to top-most path "localhost:8000", he will see "hell django"
@
# go to views.py
# add,
from .models imort Post
def index(request):
# I access via model's method
post_list = Post.objects.all()
return render(request, 'blog/index.html', {
# I will use templates
'post_list':post_list,
})
# Then, go to index.html
hello django
# I will use django template syntax to access
{% for post in post_list %}
{{post.title}}
{% endfor %}
# Go to localhost:8000, then, you can see,
# hello django
# a
# b
@
# go to urls.py
# find urlpatterns
# add,
# \d+ [0-9] over 1 times
# for example, localhost:8000/123
url(r'^(?P\d+)/$', 'blog.views.post_detail')
@
# go to views.py
# add,
# note pk
# What urls.py does is it extract url part from localhost:8000/url-part
# and then pass url(in this case, pk) to method
def post_detail(request, pk)
# In django, we can access to primary key field via pk
# This brings post whose pk is pk from database
# If there is no post corresponding to pk,
# Post.DoesnotExist exception occurs (500 error)
post = post Post.objects.get(pk=pk)
# I display brought contents
return render(request, 'blog/post_detail.html',{
'post':post,
})
@
# Create post_detail.html in templates/blog folder
{{post.title}}
{{post.content}}
# This wraps each sentence by
{{post.content|linebreaks}}
# This appends at the end of each sentence
{{post.content|linebreaksbr}}
# go to localhost:8000/1
@
# Let's make comment functionality
# go to models.py
# add,
class Comment(model.Model):
# Note that post and comments has 1:n relation
# So, we use foreign key
# In case of 1:n, something located in 1 should be decorated by foreign key
post = models.ForeignKey(Post)
author = models.CharField(max_length=10)
message = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
# At this time, comment table doesn't exist in database
# Let's make comment table in database
python manage.py makemigrations blog
python manage.py migrate
@
# To see comments in admin page, go to admin.py
# add,
from .models import Post, Comment
admin.site.register(Comment)
@
# Let's make user write comment
# go to urls.py
# find urlpatterns
# add,
url(r'^(?P\d+)/comments/new/$', 'blog.views.comment_new')
# < above pattern is localhost:8000/3453/comments/new/
@
# go to views.py
# add,
def comment_new(request, pk):
return None
@
# Let's use "form" which django provides
# create templates/blog/form.py
# add,
from django import forms
from .models import Comment
class CommentForm(forms.ModelForm):
class Meta:
# This form is form for which model? Comment model
model = Comment
# I will apply all fields
fields = '__all__'
@
# go to views.py
# add,
from .forms import CommentForm
def comment_new(request, pk):
# Following code is standardized one when you use "form"
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
form.save()
return redirect('blog.views.post_detail', pk)
else:
form = CommentForm()
return render(request, 'blog/post_form.html', {
'form':form,
})
@
# Create /blog/templates/blog/post_form.html
# add,
# go to localhost:8000/1/comments/new/
@
# Let's make comment show in view page
# go to post_detail.html
# add,
@
# go to forms.py
# replace,
fields = '__all__'
# with,
field = ('author', 'message')
@
# go to views.py
# in def comment_new()
comment = form.save(commit=False)
comment.post = Post.objects.get(pk=pk)
comment.save()
@
# Let's make editing comment functionality
# go to urls.py
# find urlpatterns
# add,
# comment_edit() takes 2 arguments(post_pk ,pk)
url(r'^(?P\d+)/comments/(?P\d+)/edit$', 'blog.views.comment_edit')
@
# go to views.py
# add,
def comment_edit(request, post_pk, pk):
# I bring comment to edit
comment = Comment.objects.get(pk=post_pk)
if request.method == 'POST':
# I pass aditional instance to be edited
form = CommentForm(request.POST, instance=comment)
if form.is_valid():
form.save()
return redirect('blog.views.post_detail', post_pk)
else:
form = CommentForm(instance=comment)
return render(request, 'blog/post_form.html', {
'form':form,
})
@
# go to post_detail.html
# add,
#
# 수정
@
# go to views.py
# add,
from .models import Post, Comment
@
# go to models.py
# add, under content = models.TextField()
# Existing post has null in photo field in database
photo = models.ImageField(blank=True, null=True)
@
# You should install Pillow library for uploading image
pip install pillow
@
# Do migration for image fiels
python manage.py makemigrations blog
python manage.py migrate
@
# Let's configure position of image
# go to settings.py
# Under STATIC_URL = '/static/'
# create,
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
# In django, there are 2 kind of resources(static and media)
# static resource means resource which is used in development stage such as css file, javascript file, image and font used in page, etc
# media resource means resource which user uploads via image fiels or file field of model
# media resource is uploded into "media" folder by "MEDIA_ROOT = os.path.join(BASE_DIR, 'media')"
@
# When you use "python manage.py runserver", runserver supports only static resource
# To resolve this issue, go to urls.py
# add,
from django.conf import settings
# under urlpatterns
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
@
# Let's make content show image
# go to post_detail.html
# under