本教程根據慕課網<Django入門與實踐>編寫 基礎知識 什麼是django? Django是一個基於Python的高級Web開發框架, 特點:高效,快速,高度集成(不用自己弄底層),免費,開源 上網的流程 輸入URL→向目標url發送http請求→伺服器把頁面響應給瀏覽器(通過後臺編寫的代碼處理請 ...
本教程根據慕課網<Django入門與實踐>編寫
基礎知識
什麼是django?
Django是一個基於Python的高級Web開發框架, 特點:高效,快速,高度集成(不用自己弄底層),免費,開源
上網的流程
輸入URL→向目標url發送http請求→伺服器把頁面響應給瀏覽器(通過後臺編寫的代碼處理請求)→瀏覽器解析獲取到的頁面源代碼文檔(所以看到的不是html文檔)→看到網頁
目錄結構
- 項目項目目錄結構.
├── manage.py與項目進行交互的命令行工具集的入口(項目管理器)
└── myblog項目的一個容器,包含項目最基本的一些配置(不建議修改名稱,會影響配置文件)
├── __init__.py聲明模塊的文件(預設為空,使myblog為一個模塊,可以直接在代碼中引用)
├── settings.py配置文件
├── urls.py配置頁面url
└── wsgi.py(Python Web Server Gateway Interface 伺服器網關介面,python應用與Web伺服器之間的介面,)
manage.py
如root@localhost ~]#python manage.py runserver(直接輸入python manage.py可以列出命令選項)
settings.py
項目的總配置文件,包含了資料庫、web應用、時間等各種配置文件
import os # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) #項目的跟目錄 # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'qkotgzdcj-n!q#1@pwv7cyya!5$cuvqp3d=vrljrbuo48qvr5b' #啟動項目所必須的安全碼 # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True #調試,打開後異常會反饋給用戶頁面 ALLOWED_HOSTS = ['192.168.230.129'] #只允許外界通過【】內的地址訪問 # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'zzb', ] #組成項目的應用,自己創建的應用需加進去 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] #中間件,自帶的工具集 ROOT_URLCONF = 'blog.urls' #url的根文件,指向urls.py TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], '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', ], }, }, ] #模板(html文件)配置 WSGI_APPLICATION = 'blog.wsgi.application' #把myblog當做一個模塊 # Database # https://docs.djangoproject.com/en/1.11/ref/settings/#databases DATABASES = { 'default': { # 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 'ENGINE': 'django.db.backends.mysql', 'NAME':'blog', 'USER':'root', 'PASSWORD':'', 'HOST':'', 'PORT':'', 'OPTIONS':{ 'autocommit':True, }, } } #資料庫配置,使用其他資料庫需改動 # Password validation # https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] #密碼認證 # Internationalization # https://docs.djangoproject.com/en/1.11/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.11/howto/static-files/ STATIC_URL = '/static/' #靜態文件的地址 STATIC_ROOT = '/var/www/html/blog/zzb/static/'
- 應用的目錄結構
.├── admin.py (該應用的後臺管理系統配置(django自帶一個後臺管理系統,每個應用都有各自的配置文件)
├── apps.py 該應用的一些配置,1.9版本後才有。
├── __init__.py
├── migrations 數據遷移模塊
│ └── __init__.py(有這個文件說明它是一個模塊)
├── models.py 數據模塊(在其中創建數據表)使用ORM框架,類似於MVC結構中的Models(模型)
├── tests.py 自動測試模塊,在這裡編寫測試腳本(語句)
└── views.py 執行響應的邏輯代碼所在的模塊,決定了接受web的請求後如何響應(項目中大部分在這裡編寫)
正式開始創建博客系統
搭建環境(建議源碼安裝,這裡為了簡便介紹yum | pip安裝)
Python
- linux自帶Python,無需安裝,
- 低於2.7的版本與最新的Django不相容
Django(自帶一個小型的伺服器)
安裝(二選一)
- a) pip安裝(需要本地有python-pip)
[root@localhost ~]#pip install Django==1.10.2
- b) 下載源碼(執行效率更高),進入根目錄執行[root@localhost ~]#python setup.py install
判斷安裝是否完成
[root@localhost ~]# python -m django –version
將Django部署到Apache伺服器上
方法1, 直接配置
安裝mod_wsgi(yum install mod_wsgi)
修改apache配置文件(點擊跳轉後續詳解)
配置項目中wsgi (點擊跳轉後續詳解)
方法2, 引入配置文件
- 不需要執行修改配置文件中的在最後添加一步(點擊跳轉至不需執行的步驟)
- 在項目/var/www/html/目錄下添加/wsgi/django.wsgi文件,內容如下:
import os import sys import django.core.handlers.wsgi from django.conf import settings # Add this file path to sys.path in order to import settings sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')) os.environ['DJANGO_SETTINGS_MODULE'] = 'blog.settings' sys.stdout = sys.stderr DEBUG = True application = django.core.handlers.wsgi.WSGIHandler()
- 在 /etc/httpd/conf.d 下 創建blogproject(自定義).conf
內容如下:
<VirtualHost *:80> WSGIScriptAlias / /var/www/html/wsgi/django.wsgi #與上面創建的目錄相同 Alias /static/ /var/www/html/collectedstatic ServerName 192.168.230.129 #ServerName example.com #ServerAlias www.example.com
<Directory /srv/lxyproject/collectedstatic> Options Indexes FollowSymLinks AllowOverride None Require all granted </Directory> <Directory /var/www/html/wsgi/> Require all granted </Directory> ErrorLog /etc/httpd/logs/blogproject.error.log LogLevel warn </VirtualHost>
創建第一個項目
用django-admin創建項目
[root@localhost ~]#django-admin startproject blog(新命令django-admin) 會在/var/www/html/下生成一個新的文件夾blog
用manage.py創建應用
[root@localhost ~]#python manage.py startapp zzb
添加應用名到settings.py中的INSTALLED_APP里,
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'zzb', ]
修改settings.py,輸入linux本機ip
ALLOWED_HOSTS = ['192.168.230.129']
創建第一個頁面(響應)
- 修改apache配置文件(/etc/httpd/conf/httpd.conf), 修改配置文件後重啟apache
在最後添加:
LoadModule wsgi_module modules/mod_wsgi.so
ErrorLog "logs/error_log" <Directory /var/www/html/blog/blog> <Files wsgi.py> Require all granted </Files> </Directory>
- 配置wsgi.py,因為使用的不是django自帶的伺服器,而是apache,若配置相同則不需要修改
import os from django.core.wsgi import get_wsgi_application os.environ.setdefault("DJANGO_SETTINGS_MODULE", "blog.settings") application = get_wsgi_application()
- 編輯blog.views
# Create your views here. from django.http import HttpResponse def index(request): return HttpResponse(‘hello,world’)
每個函數必須返回一個響應,函數必須存在一個參數,一般約定為request,對應一個URL
- 配置urls.py(每個url都以url函數的形式寫在urlpatterns列表中。三個參數(URL(正則),對應響應方法,名稱zzb為應用名)
from django.conf.urls import url from django.contrib import admin import zzb.views as bv urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/',bv.index), ]
- 打開頁面(192.168.230.129/index)
hellow,world
URL配置增強
- 修改blog下的url(註意url後面的/問題),引入include
from django.conf.urls import url,include from django.contrib import admin urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/',include('zzb.urls) ), ]
- 在app(zzb)下新建urls.py
from django.conf.urls import url from . import views urlpatterns = [ url(r'^index/$',views.index), ]
- 瀏覽器輸入地址: http://192.168.230.129/blog/index/
hello,world
創建第一個Templates(模板)
- 在APP根目錄下創建名叫templates(小寫)的目錄,
- 在templates目錄下創建以app名為名稱的目錄,將html文件放入其中(解決templates衝突)
- 在views.py中返回render()
from __future__ import unicode_literals from django.shortcuts import render # Create your views here. from django.http import HttpResponse def index(request): return render(request,'index.html')
Models(模型)
一個model對應一張數據表,以類的形式表現,包含類一些基本欄位以及數據的一些行為. ORM(object relation mapping)對象關係映射,不需要編寫SQL語句
- 在settings.py中修改,使用MySQL代替django自帶資料庫.
DATABASES = { 'default': { # 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 'ENGINE': 'django.db.backends.mysql', 'NAME':'blog', 'USER':'root', 'PASSWORD':'', 'HOST':'', 'PORT':'', 'OPTIONS':{ 'autocommit':True, }, } }
- 在資料庫中創建名為blog的資料庫
- pip安裝pymysql插件
- 修改blog/_init_.py,添加
import pymysql pymysql.install_as_MySQLdb()
- 應用根目錄下創建models.py,並引入models模塊,創建類,繼承models.Model,類即是一張數據表,在類中創建欄位
from __future__ import unicode_literals from django.db import models # Create your models here. class Article(models.Model): title = models.CharField(max_length=32, default='Title') content = models.TextField(null=True) def _unicode_ (self): return self.title
- 生成數據表
[root@localhost ~]#python manage.py makemigrations
[root@localhost ~]#python manage.py migrate(會在app/migrations/目錄下生成移植文件)
可以通過執行[root@localhost ~]#python manage.py sqlmigrate 應用名 文件id(查看SQL語句)
- 往資料庫中寫入數據
- 取出數據
views.py中
1 # -*- coding: utf-8 -*- 2 from __future__ import unicode_literals 3 4 from django.shortcuts import render 5 6 # Create your views here. 7 from django.http import HttpResponse 8 from . import models 9 10 def index(request): 11 article = models.Article.objects.get(pk=1) 12 return render(request,'zzb/index.html',{'article':article})
- 頁面呈現數據
<!DOCTYPE HTML> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>{{ article.title }}</h1> <h3>{{ article.content }}</h3> </body> </html>
Admin(自動化數據管理界面)
可直接在admin中管理資料庫
- [root@localhost ~]#python manage.py createsuperuser
- 進入192.168.230.129/admin登錄
- 更改語言,修改settings.py中LANGUAGE_CODE= ‘zh_Hans’
- 配置應用
在應用下的admin.py中引入自身的models模塊(或者裡面的模型類)
在應用目錄下的admin.py中做如下修改
# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.contrib import admin from models import Article # Register your models here. admin.site.register(Article)
- 修改數據預設顯示的名稱
編輯應用下models.py,在Article類下添加一個方法,根據Python版本(3/2.7)選擇_str_(self)或_unicode_(self)
- 關於admin頁面沒有css樣式的解決辦法
1. 去djando的解壓包里的/doc/howto/static-files中查看幫助文檔,找到解決辦法
2. 在應用目錄下創建static目錄,在settings.py中添加STATIC_ROOT=’你的ststic的文件夾地址’
3. 在urls.py中添加修改
urlpatterns = [ # ... the rest of your URLconf goes here ... ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
4. 執行python manage.py collectstatic
博客開發
博客主頁面開發
index.html
<!DOCTYPE HTML> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1> <a href="{% url 'zzb:edit_page' 0 %}">新文章</a> </h1> {% for article in articles %} <a href="{% url 'zzb:article_page' article.id %}">{{ article.title }}</a> <br/> {% endfor %} </body> </html>
博客文章頁面開發
article_page.html
<!DOCTYPE HTML> <html lang="en"> <head> <meta charset="UTF-8"> <title>Article Page</title> </head> <body> <h1>{{ article.title }} </h1> <h3>{{ article.content }}</h3> <br/><br/> <a href="{% url 'zzb:edit_page' article.id %}">修改文章</a> </body> </html>
博客編輯頁面開發
edit_page.html
<DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Edit Page</title> </head> <body> <form action="{% url 'zzb:edit_action' %}" method="post"> {% csrf_token %} {% if article %} <input type="hidden" name="article_id" value="{{ article.id }}"> <label>文章標題 <input type="text" name = "title" value="{{ article.title }}"/> </label> <br/> <label>文章內容 <input type="text" name = "content" value="{{ article.content }}"/> </label> <br/> {% else %} <input type="hidden" name="article_id" value="0"> <label>文章標題 <input type="text" name = "title" /> </label> <br/> <label>文章內容 <input type="text" name = "content" /> </label> <br/> {% endif %} <input type="submit" value="提交"/> </form> </body> </html>
views.py配置
# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.shortcuts import render from django.http import HttpResponse from . import models def index(request): articles = models.Article.objects.all() return render(request, 'zzb/index.html', {'articles':articles}) def article_page(request, article_id): article = models.Article.objects.get(pk=article_id) return render(request,'zzb/article_page.html',{'article':article}) def edit_page(request,article_id): if str(article_id) == '0': return render(request,'zzb/edit_page.html') article = models.Article.objects.get(pk=article_id) return render(request,'zzb/edit_page.html',{'article': article}) def edit_action(request): title = request.POST.get('title','TITLE') content = request.POST.get('content','CONTENT') article_id = request.POST.get('article_id','0') if str(article_id) == '0': models.Article.objects.create(title=title,content=content) articles = models.Article.objects.all() return render(request,'zzb/index.html',{'articles':articles}) article = models.Article.objects.get(pk=article_id) article.title = title article.content = content article.save() return render(request,'zzb/article_page.html',{'article':article})
url配置
from django.conf.urls import url from . import views urlpatterns = [ url(r'^index/$', views.index), url(r'^article/(?P<article_id>[0-9]+)/$', views.article_page, name=