開發環境
安裝最新版的Django版本
Django實際是一個平臺搭建工作,內含一些命令,能夠快速的完成平臺搭建
- 安裝最新版本的Django
$ pip install django
- django-admin.py添加到我們的環境變量
方便之后通過Django的命令直接操作
項目創建
1.項目創建
到項目指定目錄下
$django-admin.py startproject my_blog
- 建立Django app
到項目指定目錄下
$python manage.py startapp article
- 添加APP
在my_blog/my_blog/settings.py(注意:應該是項目根目錄底下的配置文件)
INSTALLED_APPS = (
...
'article', #這里填寫的是app的名稱
)
- 運行程序
到項目指定目錄下
$python manage.py runserver localhost:9000
- 命令總結
python manage.py <command> [options] #Django Command
python manange.py -h幫助文檔
django-admin.py startproject my_blog #創建項目
python manage.py startapp article #創建app
python manage.py runserver localhost:9000 #啟動Django中的開發服務器
項目設置
數據庫設置
- Django Model
- 每一個Django Model都繼承自django.db.models.Model
- 在Model當中每一個屬性attribute都代表一個database field
- 通過Django Model API可以執行數據庫的增刪改查, 而不需要寫一些數據庫的查詢語句
- 設置數據庫
Django項目建成后, 默認設置了使用SQLite數據庫, 在 my_blog/my_blog/settings.py 中可以查看和修改數據庫設置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
- 創建models
在my_blog/article/models.py下編寫如下程序:
from django.db import models
# Create your models here.
class Article(models.Model) :
title = models.CharField(max_length = 100) #博客題目
category = models.CharField(max_length = 50, blank = True) #博客標簽
date_time = models.DateTimeField(auto_now_add = True) #博客日期
content = models.TextField(blank = True, null = True) #博客文章正文
#python2使用__unicode__, python3使用__str__
def __str__(self) :
return self.title
class Meta: #按時間下降排序
ordering = ['-date_time']
- 同步數據庫
$ python manage.py migrate #命令行運行該命令
$ python manage.py makemigrations
- Django Shell
$ python manage.py shell
Admin
Django有一個優秀的特性, 內置了Django admin后臺管理界面, 方便管理者進行添加和刪除網站的內容.
- 設置Admin
可以在my_blog/my_blog/settings.py中查看
同時也已經添加了進入后臺管理的url, 可以在my_blog/my_blog/urls.py中查看 - 創建超級用戶
$ python manage.py createsuperuser
現在可以在瀏覽器中輸入localhost:9000/admin輸入賬戶和密碼進入后臺管理
Views和URL
- 網頁程序的邏輯
request進來->從服務器獲取數據->處理數據->把網頁呈現出來
- url設置相當于客戶端向服務器發出request請求的入口, 并用來指明要調用的程序邏輯
- views用來處理程序邏輯, 然后呈現到template(一般為GET方法, POST方法略有不同)
- template一般為html+CSS的形式, 主要是呈現給用戶的表現形式
- 簡單Django Views和URL
Django中views里面的代碼就是一個一個函數邏輯, 處理客戶端(瀏覽器)發送的HTTPRequest, 然后返回HTTPResponse,那么開始在my_blog/article/views.py中編寫簡單的邏輯
#現在你的views.py應該是這樣
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
def home(request):
return HttpResponse("Hello World, Django")
那么如何使這個邏輯在http請求進入時, 被調用呢, 這里需要在my_blog/my_blog/urls.py中進行url設置
from django.conf.urls import url
from django.contrib import admin
from article import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', views.home),
]
url()函數有四個參數, 兩個是必須的:regex和view, 兩個可選的:kwargs和name
- regex是regular expression的簡寫,這是字符串中的模式匹配的一種語法, Django 將請求的URL從上至下依次匹配列表中的正則表達式,直到匹配到一個為止。
- View當 Django匹配了一個正則表達式就會調用指定的view邏輯, 上面代碼中會調用article/views.py中的home函數
- kwargs任意關鍵字參數可傳一個字典至目標view
- name命名你的 URL, 使url在 Django 的其他地方使用, 特別是在模板中
Django Views和URL更近一步
現在我們這樣做, 在my_blog/article/views.py加入如下代碼:
def detail(request, my_args):
return HttpResponse("You're looking at my_args %s." % my_args)
在my_blog/my_blog/urls.py中設置對應的url
from django.conf.urls import url
from django.contrib import admin
from article import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', views.home),
url(r'^(?P<my_args>\d+)/$', views.detail, name='detail'),
]
^(?P<my_args>\d+)/$這個正則表達式的意思是將傳入的一位或者多位數字作為參數傳遞到views中的detail作為參數, 其中?P<my_args>定義名稱用于標識匹配的內容
Template使用
my_blog(項目根目錄)下添加文件名, 文件夾名為templates
在my_blog/my_blog/settings.py下設置templates的位置
TEMPLATE_PATH = os.path.join(BASE_DIR, 'templates')
TEMPLATES = (
...
DIRS: [TEMPLATE_PATH],
)
- 第一個template
templates/test.html 簡單第一個 template html文件
注意:要添加<meta charset="utf-8">,否則會出現編碼錯誤
<!--在test.html文件下添加-->
<!DOCTYPE html>
<meta charset="utf-8">
<html>
<head>
<title>Just test template</title>
<style>
body {
background-color: red;
}
em {
color: LightSeaGreen;
}
</style>
</head>
<body>
<h1>Hello World!</h1>
<strong>{{ current_time }}</strong>
</body>
</html>
{{ current_time }}是Django Template中變量的表示方式
在article/views.py中添加一個函數邏輯
def test(request) :
return render(request, 'test.html', {'current_time': datetime.now()})
然后設置對應的url在my_blog/my_blog/urls.py下
url(r'^test/$', views.test),
render()函數中第一個參數是request 對象, 第二個參數是一個模板名稱,第三個是一個字典類型的可選參數. 它將返回一個包含有給定模板根據給定的上下文渲染結果的 HttpResponse對象。
- 正式編寫template
在template文件夾下增加base.html
<!doctype html>
<meta charset="utf-8">
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="A layout example that shows off a blog page with a list of posts.">
<title>Andrew Liu Blog</title>
<link rel="stylesheet" >
<link rel="stylesheet" >
<link rel="stylesheet" >
</head>
<body>
<div id="layout" class="pure-g">
<div class="sidebar pure-u-1 pure-u-md-1-4">
<div class="header">
<h1 class="brand-title">Andrew Liu Blog</h1>
<h2 class="brand-tagline">Snow Memory</h2>
<nav class="nav">
<ul class="nav-list">
<li class="nav-item">
<a class="pure-button" >Github</a>
</li>
<li class="nav-item">
<a class="pure-button" >Weibo</a>
</li>
</ul>
</nav>
</div>
</div>
<div class="content pure-u-1 pure-u-md-3-4">
<div>
{% block content %}
{% endblock %}
<div class="footer">
<div class="pure-menu pure-menu-horizontal pure-menu-open">
<ul>
<li><a >About Me</a></li>
<li><a >Twitter</a></li>
<li><a >GitHub</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
上面這段html編寫的頁面是一個模板, 其中{% block content %} {% endblock %}字段用來被其他繼承這個基類模板進行重寫
繼續在templates文件夾下添加home.html文件
{% extends "base.html" %}
{% block content %}
<div class="posts">
{% for post in post_list %}
<section class="post">
<header class="post-header">
<h2 class="post-title">{{ post.title }}</h2>
<p class="post-meta">
Time: <a class="post-author" href="#">{{ post.date_time }}</a> <a class="post-category post-category-js" href="#">{{ post.category }}</a>
</p>
</header>
<div class="post-description">
<p>
{{ post.content }}
</p>
</div>
</section>
{% endfor %}
</div><!-- /.blog-post -->
{% endblock %}
其中:
- {% for <element> in <list> %}與{% endfor %}成對存在, 這是template中提供的for循環tag
- {% if <elemtnt> %} {% else %} {% endif %}是template中提供的if語句tag
- template中還提供了一些過濾器
修改my_blog/article/views.py, 并刪除test.html
def home(request):
post_list = Article.objects.all() #獲取全部的Article對象
return render(request, 'home.html', {'post_list' : post_list})
修改my_blog/my_blog/urls.py
注意:會出現no such table的問題,解決辦法:
- 運行’manage.py makemigrations’, 這樣可以’make new migrations’
- 然后運行’manage.py migrate’, 接著’apply them’
動態URL
目前只有一個主頁的空盒子, 而大部分時候我們希望能夠讓每篇博客文章都有一個獨立的頁面,Django給我們提供了一個方便的解決方法, 就是動態URL
- 修改my_blog/article/views.py代碼:
# -*- coding: utf-8 -*-
from django.shortcuts import render
from django.http import HttpResponse
from article.models import Article
from datetime import datetime
from django.http import Http404
# Create your views here.
def home(request):
post_list = Article.objects.all() #獲取全部的Article對象
return render(request, 'home.html', {'post_list' : post_list})
def detail(request, id):
try:
post = Article.objects.get(id=str(id))
except Article.DoesNotExist:
raise Http404
return render(request, 'post.html', {'post' : post})
id是每個博文的唯一標識, 所以這里使用id對數據庫中的博文進行查找
- my_blog/my_blog/urls.py中修改url設置:
from django.conf.urls import url
from django.contrib import admin
from article import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', views.home, name = 'home'),
url(r'^(?P<id>\d+)/$', views.detail, name='detail'),
]
- 在templates下建立一個用于顯示單頁博文的界面 post.html
#post.html
{% extends "base.html" %}
{% block content %}
<div class="posts">
<section class="post">
<header class="post-header">
<h2 class="post-title">{{ post.title }}</h2>
<p class="post-meta">
Time: <a class="post-author" href="#">{{ post.date_time|date:"Y /m /d"}}</a> <a class="post-category post-category-js" href="#">{{ post.category }}</a>
</p>
</header>
<div class="post-description">
<p>
{{ post.content }}
</p>
</div>
</section>
</div><!-- /.blog-post -->
{% endblock %}
可以發現只需要對home.html進行簡單的修改, 去掉循環就可以了.
- 修改home.html和base.html, 加入動態鏈接和主頁, 歸檔, 專題和About Me按鈕
<!--home.html-->
{% extends "base.html" %}
{% block content %}
<div class="posts">
{% for post in post_list %}
<section class="post">
<header class="post-header">
<h2 class="post-title"><a href="{% url "detail" id=post.id %}">{{ post.title }}</a></h2>
<p class="post-meta">
Time: <a class="post-author" href="#">{{ post.date_time |date:"Y /m /d"}}</a> <a class="post-category post-category-js" href="#">{{ post.category }}</a>
</p>
</header>
<div class="post-description">
<p>
{{ post.content }}
</p>
</div>
<a class="pure-button" href="{% url "detail" id=post.id %}">Read More >>> </a>
</section>
{% endfor %}
</div><!-- /.blog-post -->
{% endblock %}
- base.html:
<!--base.html-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="A layout example that shows off a blog page with a list of posts.">
<title>Andrew Liu Blog</title>
<link rel="stylesheet" >
<link rel="stylesheet" >
<link rel="stylesheet" >
</head>
<body>
<div id="layout" class="pure-g">
<div class="sidebar pure-u-1 pure-u-md-1-4">
<div class="header">
<h1 class="brand-title"><a href="{% url "home" %}">Andrew Liu Blog</a></h1>
<h2 class="brand-tagline">Snow Memory</h2>
<nav class="nav">
<ul class="nav-list">
<li class="nav-item">
<a class="button-success pure-button" href="/">Home</a>
</li>
<li class="nav-item">
<a class="button-success pure-button" href="/">Archive</a>
</li>
<li class="nav-item">
<a class="pure-button" >Github</a>
</li>
<li class="nav-item">
<a class="button-error pure-button" >Weibo</a>
</li>
<li class="nav-item">
<a class="button-success pure-button" href="/">Pages</a>
</li>
<li class="nav-item">
<a class="button-success pure-button" href="/">About Me</a>
</li>
</ul>
</nav>
</div>
</div>
<div class="content pure-u-1 pure-u-md-3-4">
<div>
{% block content %}
{% endblock %}
<div class="footer">
<div class="pure-menu pure-menu-horizontal pure-menu-open">
<ul>
<li><a >About Me</a></li>
<li><a >Twitter</a></li>
<li><a >GitHub</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</body>
</html>