Django - 複習與功能加強

日期:2020/05/10

講師:Arashi

Outline

  • 複習 - 建立APP

  • 複習 - 複習 - 建立 Models 與 Admin 帳號

  • 複習 - 建立首頁

  • 複習 - 建立 Posts

  • 複習 - CSS 與 Base

  • 功能增加 - Navbar

  • 功能增加 - 照片牆

  • 功能增加 - Admin 介面調整

  • References

複習 - 建立 APP

設置虛擬環境

$ cd [your project]
$ python -m venv [virtual-environment-name]
$ pip install virtualenv
$ cd [your project]
$ virtualenv [virtual-environment-name]
  • Windows
  • Mac

進入虛擬環境

$ venv\Scripts\activate 
$ source venv/bin/activate 
  • Windows
  • Mac

安裝 Django

(venv) django$ pip install django
(venv) django$ django-admin startproject mysite
venv
mysite
├── manage.py
└── mysite
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    ├── wsgi.py
    └── asgi.py

更改時間與語言設定

LANGUAGE_CODE = 'zh-Hant'

TIME_ZONE = 'Asia/Taipei'

mysite/mysite/settings.py

建立 APP

$ python manage.py startapp trips
venv
mysite/
├── manage.py
├── mysite   
└── trips
    ├── __init__.py
    ├── admin.py
    ├── app.py
    ├── migrations
    ├── model.py
    ├── tests.py
    └── views.py

設定檔增加剛建立的 APP

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    #新增
    'trips',
]

mysite/mysite/settings.py

複習 - 建立 Models 與 Admin 帳號

from django.conf import settings
from django.db import models
from django.utils import timezone


class Post(models.Model):
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    title = models.CharField(max_length=200)
    text = models.TextField()
    created_date = models.DateTimeField(default=timezone.now)
    published_date = models.DateTimeField(blank=True, null=True)

    def publish(self):
        self.published_date = timezone.now()
        self.save()

    def __str__(self):
        return self.title

定義 object

mysite/trips/models.py

$ cd 到 manage.py 在的地方
$ python manage.py makemigrations
$ python manage.py migrate

新增 tables 到 資料庫內

from django.contrib import admin
# 新增
from .models import Post

# 新增
admin.site.register(Post)

設定管理後台

mysite/trips/admin.py

$ python manage.py createsuperuser

建立 Admin 帳號

$ python manage.py runserver

測試看看

複習 - 建立首頁

建立首頁

from django.shortcuts import render	
# 新增
from trips.models import Post
 
# 新增 
def home(request):
    post_list = Post.objects.all()
    return render(request, 'home.html', {
        'post_list': post_list,
    })

mysite/trips/views.py

建立首頁

from django.contrib import admin
from django.urls import path
# 新增
from trips.views import home

urlpatterns = [
    path('admin/', admin.site.urls), 
  	# 新增
    path('home/', home),
]

mysite/mysite/urls.py

建立首頁

在trips 同層的資料夾內 建立一個 templates 資料夾

venv
mysite/
├── manage.py
├── mysite   
├── trips
└── templates
    

建立首頁

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>My blog</title>
  </head>
  <body>
    <h1>Hello !it is my blog</h1>
    <div class="container">
        {% for post in post_list %}
            <div class="post">
                <h2><a href="#">{{ post.title }}</a></h2>
                <p>{{ post.created_date }}</p>
                <p>{{ post.text }}</p>
            </div>
        {% endfor %}
    </div>
  </body>
</html>

mysite/templates/home.html

在 templates 內建立一個 home.html

更改settings.py

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
      	# 修改
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
      
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },

mysite/mysite/settings.py

$ python manage.py runserver

測試看看

複習 - 建立 Post

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>{{ post.title }} | My Adventure</title>

</head>
<body>
  <div class="post">
      <h2><a href="#">{{ post.title }}</a></h2>
      {{ post.created_date }}
      {{ post.text }}
  </div>
</body>
</html>

mysite/templates/post.html

建立文章頁面

from django.shortcuts import render
from django.http import HttpResponse
from trips.models import Post

def home(request):
	post_list = Post.objects.all()

	return render(request, 'home.html', {
			'post_list': post_list,
		})

# 新增
def post_detail(request, pk):
	post = Post.objects.get(pk=pk)
	return render(request, 'post.html', {'post':post})

mysite/trips/views.py

建立文章頁面

from django.contrib import admin
# 修改
from django.urls import path, re_path
from trips.views import home, post_detail

urlpatterns = [
    path('admin/', admin.site.urls), 
    path('home/', home),  
    # 新增
    re_path(r'^post/(?P<pk>\d+)/$', post_detail, name="post_detail"),
]

mysite/mysite/urls.py

建立文章頁面

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>My blog</title>
  </head>
  <body>
    <h1>Hello !it is my blog</h1>
    <div class="container">
        {% for post in post_list %}
            <div class="post">
                <h2><a href="{% url 'post_detail' pk=post.pk %}">{{ post.title }}</a></h2>
                <p>{{ post.created_date }}</p>
                <p>{{ post.text }}</p>
            </div>
        {% endfor %}
    </div>
  </body>
</html>

mysite/templates/home.html

修改 home.html 內的 post 連結

$ python manage.py runserver

測試看看

複習 - CSS 與 Base

建立 CSS 檔案

在 trips 資料夾內建立一個 static 資料夾, 裡面再建立一個 css 資料夾

venv
mysite/
├── manage.py
├── mysite   
├── templates
└── trips
    ├── static
        └── css
h1 a {
  color: #FCA205;
}

h1{
  text-align: center;
}
body p {
    font-style:italic;
}

.post {
    color: #FCA205;
    font-family: 'Dancing Script', cursive;
}

.page-header {
    background-color: #A89797;
    margin-top: 0;
    padding: 20px 20px 20px 40px;
}

.container{
  display: flex;
  justify-content: space-around;
}

mysite/trips/static/css/blog.css

建立 blog.css

{% load static %}
<html>
<head>
    <meta charset="utf-8">
    {% block title %}
    {% endblock %}

    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
    <link rel="stylesheet" href="{% static 'css/blog.css' %}">
    <link href="https://fonts.googleapis.com/css2?family=Dancing+Script:wght@500&display=swap" rel="stylesheet"> 
</head>
<body>
    <div class="page-header">
        <h1><a href="/home">My Blog</a></h1>
    </div>
    {% block content %}
    {% endblock %}
</body>
</html>

mysite/templates/base.html

建立 base.html

{% extends "base.html" %}

{% block title %}
    <title>test blog</title>
{% endblock %}

{% block content %}
    <h1>Hello! this is my blog</h1>
    <div class="container">
        {% for post in post_list %}
        <div class="post">
            <h2><a href="{% url 'post_detail' pk=post.pk %}">{{ post.title }}</a></h2>
            <p>{{ post.created_date }}</p>
            <p>{{ post.text|linebreaksbr|slice:":30" }}</p>
        </div>
        {% empty %}
            <p>敬請期待</p>
        {% endfor %}
    </div>
{% endblock %}

mysite/templates/home.html

修改 home.html

{% extends "base.html" %}
{% block title %}
    <title>{{ post.title }} | test blog</title>
{% endblock %}

{% block content %}
    <div class="post">
        <h2><a href="#">{{ post.title }}</a></h2>
        <p>{{ post.created_date }}</p>
        <p>{{ post.text }}</p>
    </div>
{% endblock %}

mysite/templates/post.html

修改 post.html

$ python manage.py runserver

測試看看

功能增加 - Navbar

語意標籤

<body>
    # 增加
    <nav class="navbar">
        <a class="navbar-brand" href="/home">My blog</a>
        <a class="navbar-brand" href="/showImg">My Image</a>
        <a class="navbar-brand" href="https://github.com/arashi1214">My github</a>
        <a class="navbar-brand" href="/admin">Sign in</a>
    </nav>
    
    {% block content %}
    {% endblock %}
</body>

mysite/templates/base.html

.navbar {
  list-style-type: none;
  margin: 0;
  padding: 0;
  background-color: #FCA205;
}

.navbar a{
  color: #FFFFFF;
}

mysite/trips/static/css/blog.css

加上 CSS

功能增加 - 照片牆

pip install pillow

安裝 pillow 套件

更改settings.py

STATIC_URL = '/static/'
# 新增
MEDIA_ROOT = os.path.join(BASE_DIR, 'media').replace('\\', '/')
MEDIA_URL = '/media/'

mysite/mysite/settings.py

為了讓 Django 知道該去哪裡抓照片

# 新增
class Img(models.Model):
    img_url = models.ImageField(upload_to='img')

定義 Img object

mysite/trips/models.py

$ cd 到 manage.py 在的地方
$ python manage.py makemigrations
$ python manage.py migrate

更新資料庫

from django.shortcuts import render	
# 修改
from trips.models import Post, Img

def home(request):
    post_list = Post.objects.all()
    return render(request, 'home.html', {
        'post_list': post_list,
    })

def post_detail(request, pk):
	post = Post.objects.get(pk=pk)
	return render(request, 'post.html', {'post':post})

# 新增顯示圖片
def showImg(request):
    imgs = Img.objects.all()
    context = {
        'imgs' : imgs
    }
    return render(request, 'showImg.html', context)

新增顯示的頁面

mysite/trips/views.py

from django.contrib import admin
# 修改
from .models import Post, Img

admin.site.register(Post)
# 新增
admin.site.register(Img)

設定 Img 的管理後台

mysite/trips/admin.py

from django.contrib import admin
from django.urls import path, re_path
# 修改
from trips.views import home, post_detail, showImg
# 新增
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
    path('home/', home),
    re_path(r'^post/(?P<pk>\d+)/$', post_detail, name="post_detail"),
    #新增
    path('showImg/', showImg)
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

mysite/mysite/urls.py

新增路由

建立照片牆顯示頁面

{% extends "base.html" %}
{% block title %}
    <title>展示圖片</title>
{% endblock %}
{% block content %}
    {% for item in imgs %}
        <img src="{{ item.img_url.url }}", width="150"><br/>
    {% endfor %}
{% endblock %}

mysite/templates/showImg.html

在 templates 內建立一個 showImg.html

$ python manage.py runserver

測試看看

功能增加 - Admin 介面調整

檢視網站網址設定

admin.site.site_url = 'http://127.0.0.1:8000/home'

mysite/trips/admin.py

變數 功能
list_display = ( ) 列表顯示
list_filter = ( ) 列表過濾
search_fields = ( ) 搜尋指定欄位
ordering = ( ) 依照指定欄位排序

常見的自定義管理功能

自訂 Admin 介面

from django.contrib import admin
from .models import Post, Img

# 新增
class PostAdmin(admin.ModelAdmin):
    list_display = ('title', 'text', 'created_date', 'published_date', 'author_id')

# 修改
admin.site.register(Post, PostAdmin)

admin.site.register(Img)

mysite/trips/admin.py

自訂 Admin 介面

from django.contrib import admin
from .models import Post, Img

# 修改
class PostAdmin(admin.ModelAdmin):
    list_filter = ('created_date',)

    
admin.site.register(Post, PostAdmin)

admin.site.register(Img)

mysite/trips/admin.py

自訂 Admin 介面

from django.contrib import admin
from .models import Post, Img

# 修改
class PostAdmin(admin.ModelAdmin):
    search_fields = ('title',)

    
admin.site.register(Post, PostAdmin)

admin.site.register(Img)

mysite/trips/admin.py

自訂 Admin 介面

from django.contrib import admin
from .models import Post, Img

# 修改
class PostAdmin(admin.ModelAdmin):
    ordering = ('text',)

    
admin.site.register(Post, PostAdmin)

admin.site.register(Img)

mysite/trips/admin.py

References

Thank for listening

Made with Slides.com