【記錄 】Django學習1
1、環境配置
用conda 創建名為django_env的虛擬環境,source activate進入,pip install安裝最新的Django。
另外,觀察web開發效果肯定要需要開瀏覽器,於是打算先給安裝桌面,再安裝谷歌瀏覽器:
本地安裝VNC Viewer (下載地址:https://www.realvnc.com/en/connect/download/viewer/)
伺服器上安裝 vnc4server
注意ECS入方向除指定外名單的埠默認是禁止,所以這裡需要在ECS管理裡面將vnc所用到的5900/5901埠添加允許,否則連接不了。
但是這個桌面有點問題,比如點擊瀏覽器,打開的不是瀏覽器界面而是命令行,於是繼續安裝ubuntu的界面:
sudo apt-get install x-window-system-core
sudo apt-get install gdm
sudo apt-get install ubuntu-desktop
中途遇到文件快滿了用:sudo apt-get clean && sudo apt-get update && 清理,繼續。
無用,df -h查看/dev/vda1 已經100%
du -sh *查看到logs大文件夾,刪,安裝沒問題,但是vnc打開看不到菜單欄……折騰很久,突然想到:
作為Web伺服器根本不需要圖形界面啊!-_-||需要測試效果完全可以在客戶端開瀏覽器,去訪問伺服器地址就行,這也是最常規的模式啊~
同理,上周嘗試了用sphinx,將reST格式的文檔直接組織成html,但每次看效果都是tar一個壓縮包,然後sz到本地,解壓,打開。因為在學習語法修改了好多次,每一次修改就要重複以上步驟……現在想想……簡直可恥!
剛剛用HTTPServer組織了簡單的web發布,在這裡:Welcome to first_docs documentation! (沒有域名直接粗暴上IP)
python -m http.server # python3
參考:
阿里雲ECS,Ubuntu Server 16.04安裝圖形界面遠程控制
更改pip源至國內鏡像,顯著提升下載速度 - CSDN博客
阿里雲ECS使用vnc遠程連接 - CSDN博客
Ubuntu 16.04下安裝64位谷歌Chrome瀏覽器
vncserver 看不到桌面解決辦法
使用python3的http.server模塊要注意的問題 - CSDN博客
2、創建項目
開發直接在Ubuntu16.04上完成,本地安裝pycharm,可以編輯代碼,但代碼一律上傳到遠程伺服器運行。
首先創建最最簡單的例子,創建一個項目,能訪問就行:
django-admin startproject mysite
python manage.py runserver
python manage.py migrate #第一次run有提示得執行這個
python manage.py runserver
服務端提示啟動成功,但是從客戶端訪問得到錯誤響應:
dial tcp xx.xx.xx.xx:8000: connectex: No connection could be made because the target machine actively refused it.
其實服務端已經成功啟動了,只不過這是只能在服務端用127.0.0.1:8000的地址去訪問,為了遠程訪問,需要做如下兩點:
- 修改settings.py,將ALLOWED_HOSTS列表改為[*],表示通過指定的域名才可以被訪問到,在這裡既然表示是任意的
- 啟動時帶上參數,python manage.py runserver 0.0.0.0:8000,表示對外的地址
- 阿里雲 安全組把8000埠加入白名單
3、創建應用
以上只包含了項目,沒有應用。所謂建網站其實是為了實現某種功能的,功能由應用來實現。
創建後一定要在settings.py中的INSTALL_APPS中註冊
創建應用,有兩個命令是等效的
django-admin startapp blog
python manage.py startapp blog
[命令區別django-admin和python manage.py]
4、為應用建立數據模型,並據此建立數據表
(某個數據模型屬於某個應用,而不是全網站公用同一個模型)
數據模型在./blog/models.py中,
然後由此生成一個能夠簡歷資料庫表的文件:
python manage.py makemigrations
由此創建真正的資料庫:
python manage.py migrate
教程上是用瀏覽器插件查看,當然比較方面。但是我這裡Ubuntu沒有桌面,查到sqlite3就是一個文件不支持遠程,所以只有Ubuntu上直接命令行看看
5、創建用戶
先創建superuser
python manage.py createsuperuser
再圖形界面若干普通用戶
6、添加後台管理
編輯admin.py,把BlogArticles類註冊到admin中,在這裡還可以順便新建和註冊一個BlogArticlesAdmin類,為類的展現提供更多的形式。
通過把內容存入資料庫,可以看到:
7、用代碼讀取對象內容(具提地說,這裡是展示文章標題)
首先聯繫用Django shell:(很簡單)
Python 3.6.0 |Continuum Analytics, Inc.| (default, Dec 23 2016, 12:22:00)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.contrib.auth.models import User
>>> from blog.models import BlogArticles
>>> user = User.object.get(username="admin")
Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: type object User has no attribute object
>>> user = User.objects.get(username="admin")
>>> user
<User: admin>
>>> user.username
admin
>>> user.id
3
>>> user.password
xxxxx
>>> user.email
>>> type(user)
<class django.contrib.auth.models.User>
>>>
>>>
>>> blogs = BlogArticles.objects.all()
>>> blogs
<QuerySet [<BlogArticles: BlogArticles object (1)>, <BlogArticles: BlogArticles object (2)>, <BlogArticles: BlogArticles object (3)>, <BlogArticles: BlogArticles object (4)>]>
>>> len(blogs)
4
>>> for blog in blogs:
... print(blog.title)
...
Hello Word
來自官方管理員
我喜歡的音樂
我喜歡的運動
>>> exit()
據此,寫成代碼,位於./blogs/views.py
from django.shortcuts import render
from .models import BlogArticles
# Create your views here.
def blog_title(request):
blogs = BlogArticles.objects.all()
return render(request, "blog/titles.html", {"blogs":blogs})
這段代碼是針對一個request請求,返回render之後的titles.html頁面,所謂render就是用blog變數的值傳給模板中的"blogs",讓模板中與"blogs」有關的地方(有可能並不是blogs本身而是相關,比如for blog in blogs)編程真正的值。
於是,理所當然地要去寫一個模板./blog/template/blog/titles.html。
[為什麼是這個路徑?兩個blog?]
默認從的當前應用的templates文件夾(也就是/blog/templates文件夾)下讀取html模板,所以首先要自己mkdir templates。然後在templates中,除了一個base.html還有一個blogs文件夾,前者是公用的html模板,後者是blog文件特有的html部分,titles.html繼承了base.html的內容
文件內容:
base.html
<!DOCUTYPE html>
<html lang="zn=cn">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta charset="utf-e">
<meta name="viewport content="width_=device-width, initial-scale=1">
<title>{% block title %}{% endblock %}</title>
<link rel="stylesheet" href="http:necolas.github.io/normalize.css/">
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<div class="container">
{% block content %}
{% endblock %}
</div>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script>
<script src="https://cdn.bootcss.com/bootstrp/3.3.7/js/bootstrap.min.js"></script>
</body>
</html
titles.html
{% extends "base.html" %}
{% block title %}blog titles{% endblock %}
{% block content %}
<div class="row text-center vertical-middle-sm">
<h1>我的博客</h>
</div>
<div class="row">
<div class="col-xs-12 col-md-8">
<ul>
{% for blog in blogs %}
<li>{{blog.title}}</li>
{% endfor %}
</ul>
</div>
<div class="col-xs-6 col-md-4">
<h2>廣告</h2>
<p>tianwei1992.github.io</p>
</div>
</div>
{% endblock %}
除了基本的html語法,注意一些新的東西:
{% block content %} 開始一個名叫block的塊
{% endblock %} 這個塊結束了
至此,如果給到合適的請求,就能拿到經過render以後的正確響應。
但問題是,我們想要通過/blog的URL打開這個頁面,/music的URL打開另外一個頁面,後端如何去區分不同的響應?
所以還需要將不同的URL與不同的資源綁定起來,俗稱的頁面路由。路由分網站級和應用級,一個在./mysite/mysite/urls.py中,另一個是./mysite/blog/urls.py。
./mysite/mysite/urls.py
from django.contrib import admin
from django.urls import path, include
from django.conf.urls import url, include
app_name = blog
urlpatterns = [
path(admin/, admin.site.urls),
url(r^blog/, include(blog.urls)),
]
./mysite/blog/urls.py
from django.conf.urls import url
from blog import views
urlpatterns = [
url(^$, views.blog_title, name="blog_title"),
]
8、回頭看,如何響應一個請求?
首先收到一個request,解析其中的url。
根據./mysite/mysite/urls.py中的規定,以http:xx.xx.xx.xx/blog的請求,繼續交給./mysite/blog/urls.py處理。
urlpatterns = [
url(^$, views.blog_title, name="blog_title"),
]
具體來說是上面這一句,規定了blog後面不跟其他字元的,就交給 views.blog_title這個函數處理,就是我們在views.py中定義的函數。這就意味著,具有共同特徵的一類請求就和一種特定的響應方式綁定好了。
這個函數規定了具體的處理辦法:
def blog_title(request):
blogs = BlogArticles.objects.all() # 把Django後台資料庫里BlogArticles的所有東西掏出來,先放在blogs裡面
return render(request, "blog/titles.html", {"blogs":blogs}) #把這個變數的值傳給html裡面的blogs變數({"blogs":blogs} 中的前一個,其實這兩個可以不同名)
也就是說,處理就是首先渲染blog/titles.html然後返回。這裡的渲染就是變數替換。
那麼取出blog/titles.html,看看裡面有哪些變數要替換。
首先{% extends "base.html" %},所以還去看base.html,base.html中有兩個變數要替換,{% block title %}和{% block content %},而blog/titles.html在{% extends "base.html" %}之後就是在給與了明確的答覆,規定了這兩個塊到底是什麼,替換即可。
在替換{% block content %}時發現,裡面有個blogs變數,它的值在render這一句中有指定傳入,所以也是明確的。
於是最終我們用瀏覽器訪問看到的html就是這樣啦:
左邊除了html文件,還有3個css或者js文件,其實也是這個html中指定要繼續載入的。
(這裡其實本該還有一個css,因為我寫漏了一個屬性……)
NiceNotes: 跟老齊學Django 項目實戰筆記
推薦閱讀:
TAG:Django(框架) |