Python版本3.5.2,Django版本1.10
創建一個Django工程,并且生成一個名字為mainsite的app
django-admin.py startproject myblog
python3 manage.py startapp mainsite
文件結構如下:
x-power@xpower-CW65S:~/chen/myblog$ tree ./ ./ ├── mainsite │?? ├── admin.py │?? ├── __init__.py │?? ├── migrations │?? │?? └── __init__.py │?? ├── models.py │?? ├── tests.py │?? └── views.py ├── manage.py └── myblog├── __init__.py├── __pycache__│?? ├── __init__.cpython-35.pyc│?? └── settings.cpython-35.pyc├── settings.py├── urls.py└── wsgi.py4 directories, 13 files
介紹一下比較重要的幾個文件的用途:
manage.py?? ?:?? ?Django用于管理網站配置的文件,是一個接受命令行指令的工具集程序。
setting.py?? ?? :?? ?就像他的名字一樣是用于對網站的配置進行設置的。(有些地方可能我的理解也不正確歡迎指正,批評!)
urls.py?? ??? ??? :?? ?用來設置每一個URL 的網址要對應的函數以及對應的方式,通常是創建一個新的網頁的時候首要編輯的文件。
wsgi.py?? ??? ?? :?? ?是用于部署網站時候用的和主機中網頁服務器的溝通接口(如Apache)。
真正的網站運行邏輯都在我們創建的App里面(這里是mainsite),這個App也體現了Django的Reuse的概念。
我們已經創建了App但是Dajngo還是不知道有這個App的,我們在setting.py中加入這個App。
INSTALLED_APPS = ('django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','mainsite', )
然后修改最后的時區設置,默認時區是Django的誕生地,我們先讓他倒時差,學習中文。
LANGUAGE_CODE = 'zh-CN'TIME_ZONE = 'Asia/Shanghai'
Django自帶了一個數據庫Sql.lite。是一個超小型數據庫,一般情況下都會用其他數據庫的。現在我們先用這個數據庫。
執行以下文件會看到生成了一個db.sqllite3的文件。
1 x-power@xpower-CW65S:~/chen/myblog$ python3 manage.py migrate 2 Operations to perform: 3 Synchronize unmigrated apps: messages, staticfiles 4 Apply all migrations: admin, auth, sessions, contenttypes 5 Synchronizing apps without migrations: 6 Creating tables... 7 Running deferred SQL... 8 Installing custom SQL... 9 Running migrations: 10 Rendering model states... DONE 11 Applying contenttypes.0001_initial... OK 12 Applying auth.0001_initial... OK 13 Applying admin.0001_initial... OK 14 Applying contenttypes.0002_remove_content_type_name... OK 15 Applying auth.0002_alter_permission_name_max_length... OK 16 Applying auth.0003_alter_user_email_max_length... OK 17 Applying auth.0004_alter_user_username_opts... OK 18 Applying auth.0005_alter_user_last_login_null... OK 19 Applying auth.0006_require_contenttypes_0002... OK 20 Applying sessions.0001_initial... OK
在默認的情況下Django的數據庫是通過Model的方式去操作的(這也是我愛Django的一點。),也就是在程序中不會直接面對數據庫和數據表,而是先創建好Model,然后通過對Model的操作達到操作數據庫的目的。這樣做日后可以很方便的更換數據庫。(總感覺哪里有點不對,日后就換?)
使用數據庫大概分為以下幾步:
- 在models.py中定義需要使用的類(繼承自models.Model)
- 詳細的設置每一個類中的變量,即數據表的每一個字段
- 使用python3 manage.py makemigrations創建數據庫和Django的中介文件。
- 使用python3 manage.py migrate 同步更新數據庫的內容。
- 操作python定義的類就相當于操作數據庫了。
如同my_blog這個名字的意思一樣,在這里我們需要有一個儲存博文的數據表。
最初的時候models.py文件的內容就是這些。
from django.db import models# Create your models here.
修改之后內容如下:
from django.db import models from django.utils import timezone # Create your models here.class Post(models.Model):title = models.CharField(max_length = 200,verbose_name = '標題')slug = models.CharField(max_length = 200,verbose_name = '作者')body = models.TextField(verbose_name = '內容')pub_date = models.DateTimeField(default = timezone.now,verbose_name = '發表時間')class Meta:verbose_name="文章內容" # 后臺表的名稱verbose_name_plural = "文章內容"ordering = ['-pub_date'] # 排序def __str__(self):return self.title # 在 Admin界面顯示的內容
verbose_name 自己試一下應該可以知道是將原來的名字給換了一下,換成中文。
在設計好表之后,執行makemigrations和migrate操作,然后創建一個超級用戶,
python3 manage.py createsuperuser
登陸進去添加五篇文章。
數據庫有了文章以后,我們就要讀取這些資料然后在首頁將其顯示出來,在這里簡單的介紹一下MTV和MVC結構。 ? ? ? ? ? ? ?? models.py主要負責定義要存取的數據模型,以Python的class 類定義,在后端Django會自動把這個類中的設置對應到數據庫系統當中去,不管是使用的是何種數據庫。如何將這些數據取出來或者時存進去的邏輯則是在View中,下面我們編寫mainsite/views.py文件。
from django.shortcuts import render from django.http import HttpResponse from .models import Post# Create your views here.def homepage(request):posts = Post.objects.all()post_list = list()for count,post in enumerate(posts):post_list.append('No.{}:'.format(str(count)) + str(post) + "<br>")return HttpResponse(post_list)
如果項目比較大的話,為了方便組織url我們需要在mainsite文件夾下新建一個urls.py文件。然后添加內容如下:
from django.conf.urls import url from . import viewsurlpatterns = [url(r'^$',views.homepage,name = 'homepage'), ]
它使用正則表達式的匹配方式(不懂的話學習一下正則表達式,非常常用),后面跟著使用那個view的路徑,最后面的name = ××× 是用于在html文件中跳轉頁面之用。
然后在myblog下的urls.py中include這個文件。修改myblog/urls.py如下:
from django.conf.urls import include, url from django.contrib import adminurlpatterns = [url(r'^admin/', include(admin.site.urls)),url(r'',include('miansite.urls',namespace = "mainsite")), ]
然后進入主頁面(http://127.0.0.1:8000/)可以看到如下:
?
?為什么只有題目呢? 我們可以查看models.py 其中最后一行 self.title。
我們可以修改views.py文件從而讓頁面變得更加的美觀。
from django.shortcuts import render from django.http import HttpResponse from .models import Post# Create your views here.def homepage(request):posts = Post.objects.all()post_list = list()for count,post in enumerate(posts):post_list.append('No.{}:'.format(str(count)) + str(post) + "<hr>")post_list.append("<small>" + str(post.body) + "</small><br><br>")return HttpResponse(post_list)
?
?
? 差不多一個簡單的網頁已經出來了,下面說一下工作邏輯,用戶提交請求,頁面服務器(如Apache),區分是靜態文件還是其他,靜態文件直接返回內容,其他的話找到setting文件,發現ROOT_URLCONF,然后從中找到相應的url對應的視圖,然后視圖進行邏輯處理,需要和數據庫進行交互的話進行交互,然后將內容放到相應的模板當中。返回給用戶。(可能說的有問題,歡迎指正!)
?
在前面我們的html編碼都在views.py文件當中,實際開發的時候是不需要這樣做的,將html和后臺分開這樣才能最大效率,最易維護。如果將其分開的話主要工作為下面幾步:
- 在setting.py中設置template文件夾的位置。
- 在urls.py中創建網址和views.py的對應關系。
- 創建html文件,做好排版并安排數據要在頁面顯示的位置。
- 在views.py中取得數據,以render函數把數據送到指定的模板文件當中。
修改setting文件中的某些內容如下。
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',],},}, ]
templates是在項目的根目錄下(BASE_DIR),然后在templates下創建一個index.html文件,內容如下:
<!DOCTYPE html> <html><head><meta charset = 'utf-8'><title>歡迎光臨我的博客</title></head><body><h1>歡迎光臨我的博客</h1><hr>{{posts}}<hr><h3>現在時刻:{{now}}</h3></body> </html>
相應的views.py的編碼如下:
from django.shortcuts import render from django.http import HttpResponse from .models import Post from datetime import datetime # Create your views here.def homepage(request):posts = Post.objects.all()now = datetime.now()post_list = list()return render(request,'index.html',{'posts':posts,'now':now})
效果如下,當然這樣瞎扯淡是不行的。
我們修改index.html文件如下:
<!DOCTYPE html> <html><head><meta charset = 'utf-8'><title>歡迎光臨我的博客</title></head><body><h1>歡迎光臨我的博客</h1><hr>{% for post in posts %}<p style = 'font-family:微軟雅黑;font-size:16pt;font-weigth:bold;'>{{post.title}}</p><p style = 'font-family:微軟雅黑;font-size:10pt;letter-spacing:1pt;'>{{post.body}}</p>{% endfor %}<hr><h3>現在時刻:{{now}}</h3></body> </html>
效果如下:
很顯然,沒有人會直接將全部內容放到首頁,將index.html改為如下:
<!DOCTYPE html> <html><head><meta charset = 'utf-8'><title>歡迎光臨我的博客</title></head><body><h1>歡迎光臨我的博客</h1><hr>{% for post in posts %}<p style = 'font-family:微軟雅黑;font-size:16pt;font-weigth:bold;'><a href = "{url 'mainsite:post' post.id}">{{post.title}}</a></p>{% endfor %}<hr><h3>現在時刻:{{now}}</h3></body> </html>
上面的鏈接一行待會解釋。
?
效果如下:
然后開始添加點擊鏈接之后的邏輯處理:
def post(request,post_id):try:post_id = int(post_id)post = Post.objects.get(id = post_id)return render(request,'post.html',{'post':post})except:return redirect('/')
怎樣才知道是用這個view呢?下面開始修改 url.在mainsite下的urls.py文件中添加內容如下:
url(r'post/(?P<post_id>\d+)/$',views.post,name = 'post'),#這里的name 就是用于在html 文件中進行跳轉的標記。
然后效果如下:
添加post.html如下:
<!DOCTYPE html> <html><head><meta charset = 'utf-8'><title>歡迎光臨我的博客</title></head><body><h1>{{post.title}}</h1><hr><p style = 'font-family:微軟雅黑;font-size:12pt;letter-spacing:2pt;'>{{ post.body }}</p><hr><h3><a href = "{% url 'mainsite:homepage' %}">回首頁</a></h3></body> </html>
? 可以看到index.html和post.html有許多相同的地方,而且對于一個正式的網站往往需要固定的頁首和頁尾。
一個正式的網站往往每一頁都需要一些固定的元素用以強調網站的風格。以本堂課的網站為例,到目前為止需要的.html文件如下:
.html文件關系說明,? base.html include header.html和footer.html?????????????????? index.html 和 post.html extends base.html 。
創建base.html文件寫入以下內容:
<!DOCTYPE html> <html><head><meta charset = 'utf-8'><title>{% block title %} {% endblock %}</title></head><body>{% include 'header.html' %}{% block headmessage %} {% endblock %}<hr>{% block content %} {% endblock %}<hr>{% include 'footer.html' %}</body> </html>
下面添加或修改.html如下
index.html
{% extends 'base.html' %} <!-- 繼承自base.html --> {% block title %}歡迎光臨我的博客{% endblock %} {% block headmessage %}<h3 style = 'font-family:楷體;'>本站文章列表</h3> {% endblock %} {% block content %}{% for post in posts %}<p style = 'font-family:微軟雅黑;font-size:14pt;font-weigth:bold;'><a href = "{% url 'mainsite:post' post.id %}">{{post.title}}</a></p>{% endfor %} {% endblock %}
?
post.html
{% extends 'base.html' %} {% block title %} {{ post.title }} - 文學天地 {% endblock %} {% block headmessage %}<h3 style = 'font-family:微軟雅黑;'>{{ post.title }}</h3><a style = 'font-family:微軟雅黑;' href = "{% url 'mainsite:homepage' %}">回首頁</a> {% endblock %} {% block content %}<p style = 'font-family:微軟雅黑;font-size:12pt;letter-spacing:2pt;'>{{ post.body }}</p> {% endblock %}
footer.html
{% if now %}<p style = 'font-family:微軟雅黑;'>現在時刻:{{ now }}</p> {% else %}<p style = 'font-family:微軟雅黑;'>本站內容取自互聯網,如有侵權請來信通知下架。</p> {% endif %}
header.html
<h1 style = 'font-family:微軟雅黑;'>歡迎觀臨 文學天地</h1>
設計這些東西的時候,你一定感覺到很煩,為什么不寫好一個css文件然后引用呢?? 下面我們開始說這一類 ”靜態文件的處理方法“。
我們采用bootstrap去寫。采用CDN
<!-- Latest compiled and minified CSS --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"><!-- Optional theme --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"><!-- Latest compiled and minified JavaScript --><script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
將base.html修改為下面
<!DOCTYPE html> <html><!-- Latest compiled and minified CSS --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"><!-- Optional theme --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"><!-- Latest compiled and minified JavaScript --><script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script><head><meta charset = 'utf-8'><title>{% block title %} {% endblock %}</title></head><body><div class = 'container-fluid'>{% include 'header.html' %}<div class = 'panel panel-default'><div class = 'panel-heading'>{% block headmessage %} {% endblock %}</div><div class = 'panel-body'>{% block content %} {% endblock %}</div><div class = 'panel-footer'>{% include 'footer.html' %}</div></body> </html>
然后此時運行起來效果如下:
漂亮了 好幾個檔次。
接著我們引入Bootstrap中Grid概念,通過row和col的設置做出來一般博客網站的側邊連同樣也是在base.html中修改。只修改body的內容
?
<div class = 'container-fluid'>{% include 'header.html' %}<div class = 'row'><div class = 'col-sm-2 col-md-2'><div class = 'panel panel-default'><div class = 'panel-heading'><h3>MENU</h3></div><div class = 'panel-body'><div class = 'list-group'><a href = "{% url 'mainsite:homepage' %}" class = 'list-group-item'>Home</a><a href = 'http://tar.so/news' class = 'list-group-item'>時事新聞</a><a href = 'http://drho.tw/news' class = 'list-group-item'>電視新聞</a></div><script type = 'text/javascript' src = 'http://feedjit.com/serve/?vv=1515&tft=3&dd=0&wid=&pid=0&proid=0&bc=FFFFFF&tc=000000&;ww=190&wne=6&srefs=0'></script><noscript><a href='http://feedjit.com/'>Live Traffic Stats<a></noscript></div></div></div><div class = 'col-sm-8 col-md-8'><div class = 'panel panel-default'><div class = 'panel-heading'>{% block headmessage %} {% endblock %}</div><div class = 'panel-body'>{% block content %} {% endblock %}</div><div class = 'panel-footer'>{% include 'footer.html' %}</div></div></div></div></div>
?