【記錄 】Django學習1

1、環境配置

用conda 創建名為django_env的虛擬環境,source activate進入,pip install安裝最新的Django。

另外,觀察web開發效果肯定要需要開瀏覽器,於是打算先給安裝桌面,再安裝谷歌瀏覽器:

本地安裝VNC Viewer (下載地址:realvnc.com/en/connect/)

伺服器上安裝 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的地址去訪問,為了遠程訪問,需要做如下兩點:

  1. 修改settings.py,將ALLOWED_HOSTS列表改為[*],表示通過指定的域名才可以被訪問到,在這裡既然表示是任意的
  2. 啟動時帶上參數,python manage.py runserver 0.0.0.0:8000,表示對外的地址
  3. 阿里雲 安全組把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,因為我寫漏了一個屬性……)

寫漏了,所以沒卸載這個csso(╯□╰)o

NiceNotes: 跟老齊學Django 項目實戰筆記

推薦閱讀:

TAG:Django(框架) |