騰訊雲Django+

準備工具

1、騰訊雲服務器(當然其它的阿里雲之類的也是沒問題的,選擇騰訊雲是因爲騰訊雲有學生價;阿里雲也有但是我一直學生認證不了。。。沒辦法;另外聽說華爲雲的性能要好很多但是沒有學生價)。
2、接下來是申請域名,按照官網的步驟來就可以了。
3、ssh( Secure Shell)遠程訪問工具,我選擇的是SecureCRT。這個用於遠程訪問我們的服務器。
4、winSCP 由於遠程傳輸文件。

安裝部分

安裝python3.6

這部分參考這篇博客

  1. 輸入 sudo add-apt-repository ppa:jonathonf/python-3.6
 A plain backport of *just* Python 3.6. System extensions/Python libraries may or may not work.
Don't remove Python 3.5 from your system - it will break.
 More info: https://launchpad.net/~jonathonf/+archive/ubuntu/python-3.6
Press [ENTER] to continue or ctrl-c to cancel adding it

也就是說騰訊雲服務器上默認安裝了python2.7.11和python3.5.2的python版本。一般來書這兩個版本也夠用了。但是python新版本還是添加了一些新特性,雖然前段時間python3.7已經出來了,但是相對來說python3.6應該算是又穩定且也有大部分最新的特性。因此我選擇安裝3.6的版本。

現在我想要安裝3.6 的版本,如果直接使用命令:

sudo apt-get install python3.6

sudo apt-get install python3.6 命令解釋:
sudo在/etc/sudoers中設置了可執行sudo指令的用戶。若其未經授權的用戶企圖使用sudo,
則會發出警告的郵件給管理員。用戶使用sudo時,必須先輸入密碼,之後有5分鐘的有效期限,
超過期限則必須重新輸入密碼。

apt-get 一個下載的命令參數有install 安裝 update 更新 remove 移除 check 檢查。
比如: sudo apt-get install samba-3.0-7 下載並安裝一個名字爲samba-3.0-7的程序。

我們發現是安裝不了的。因爲我不是經常使用linux,因此希望在使用的過程中熟悉linux的一些命令,所以對於一些命令也會做一些解釋。關於apt-get更加詳細的內容可以參考這裏

接下來我按照網上的說明來做個安裝python3.6的嘗試(可能有坑):

1、 sudo add-apt-repository ppa:jonathonf/python-3.6
命令解析:
什麼是ppa?
PPA,表示Personal Package Archives,也就是個人軟件包集
很多軟件包由於各種原因吧,不能進入官方的Ubuntu軟件倉庫。爲了方便Ubuntu用戶使用,
launchpad.net提供了ppa,允許用戶建立自己的軟件倉庫,自由的上傳軟件。PPA也被用來對一些打算進入
Ubuntu官方倉庫的軟件,或者某些軟件的新版本進行測試。
Launchpad是Ubuntu母公司canonical有限公司所架設的網站,是一個提供維護、支援或聯絡Ubuntu開發
者的平臺。
add-apt-repositor不是內建指令,需要安裝,安裝命令如下:
sudo apt-get install python-software-properties 可以看到這個東西實際上是一個python腳本
添加源地址、密鑰等內容,只需要一條簡單的命令即可:
sudo add-apt-repository ppa:user/ppa-name

2、輸入 sudo apt-get update 

3、輸入命令 sudo apt-get install python3.6 

4、設置python3之間的優先級和py2和py3的優先級
python默認爲Python2,現在修改爲Python3:
sudo update-alternatives --install /usr/bin/python python /usr/bin/python2 100 
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 150

通過上面這兩條語句之後,python的默認版本爲python3.5.1,現在要將3.5.1改爲3.6:
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.5 1
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.6 2

5、安裝pip
sudo apt-get install python3-pip

步驟1的解析參考這篇博客
步驟4關於設置命令優先級的指令參考這篇博客
親測上面的步驟是沒問題的^_^

Python虛擬環境安裝以及使用

這部分參考這篇博客
主要步驟以及命令:
1、安裝虛擬環境工具

在沒有pip指令的情況:
sudo apt install python-virtualenv
sudo easy_install virtualenvwrapper

如果安裝了pip可以使用下面的指令:
sudo pip install virtualenv
sudo pip install virtualenvwrapper

virtualenv是虛擬環境,virtualenvwrapper對virtualenv的命令進行了封裝,使得其更加友好。
2、使用上面安裝好的虛擬環境工具

1.創建虛擬環境:
mkvirtualenv 虛擬環境名
例如:mkvirtualenv mywork 會創建一個名爲mywork的虛擬環境,創建的虛擬環境都保存在/home/.virtualenvs目錄下,創建成功後會自動進入該虛擬環境。

上面的指令是使用默認的python版本,我們也可以指定python版來創建虛擬環境:
mkvirtualenvs -p python路徑 虛擬環境名
例如:mkvirtualenv -p /usr/bin/python2 mywork

細節:不需要進入到/home/.virtualenvs目錄,在任何目錄下都可以執行命令,創建的虛擬環境的位置都一樣。
注意:創建虛擬環境是需要在聯網下進行,否則創建失敗

可能遇到的問題:
在使用mkvirtualenv安裝虛擬環境時,可能提示找不到命令,一般是腳本文件沒有加入系統路徑。
解決方法有兩種:
第一種:
1.找到virtualenvwrapper的腳本文件:whereis virtualenvwrapper
2.進入該目錄 cd /usr/local/python3/bin
3.執行腳本激活virtualenvwrapper :source virtualenvwrapper.sh
4.可以正常使用命令了。

第二種:
第一種方法每次機器重啓之後會失效,要重新執行之前的操作
如果將命令添加到環境變量就可以解決這問題,一勞永逸:
1. 打開系統環境變量文件:sudo vi ~/.bashrc
2.在末尾添沒次開機時我們希望系統執行的命令:source /usr/local/python3/bin/virtualenvwrapper.sh
3.保存後執行:source ~/.bashrc

2、虛擬環境的查看和使用
刪除虛擬環境:rmvirtualenv [虛擬環境名稱]
例如:rmvirtualenv mywork
 注意:如果目前的位置在虛擬環境中,需要先退出虛擬環境,然後才能執行刪除
 注意:可以在任何目錄執行刪除操作,如果不知道名字,可以rmvirtualen + 兩次Tab鍵,提示所有的虛擬環境
 
退出虛擬環境:deactivate

進入虛擬環境:workon 虛擬環境名
注意:按workon+兩次tab鍵會提示所有的虛擬環境

查看虛擬環境中安裝的python包
pip list
pip freeze

在虛擬環境中安裝python包
進入虛擬環境,在終端輸入:pip install 包的名字
注意:一定不要使用sudo pip,否則會安裝在全局的環境中。

上面再更新了pip3之後會報錯:會提示找到一個main模塊:
解決方法參考這篇博客

安裝Django

只需要在虛擬環境中執行pip install --user django就會直接安裝最新的django包。

django極簡使用方法

在安裝好上面的這些基本工具之後,就可以開始創建一個django工程。

1、 到你想要將工程創建的目錄下輸入如下命令:
django start-project  [工程名]
2、啓動開發服務器
輸入命令:python manage.py runserver
或者指定端口號:python manage.py runserver 【端口號】
上面的這兩條啓動命令默認只監聽本地連接。
如果要添加服務器連接可以使用下面的命令:
python manage.py runserver 0.0.0.0:【端口號】
這樣非本地連接也可以訪問服務器
3 、創建一個新的應用:
python manage.py startapp 【應用名】
4、把我們新定義的app加到settings.py中的INSTALL_APPS中
5、
修改文件:mysite/mysite/settings.py
中的:
INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
 
    'learn',
)

實現網頁的hello world

在我們創建應用learn的views.py中修改內容添加一下內容:

from django.http import HttpResponse

def hello(request):
    return HttpResponse("Hello world")

顯然這樣寫完之後我們的網頁內容沒有一點變化,還是停留在django的歡迎界面。
接下來我們需要將我們添加的內容和我們的網頁關聯起來。
配置URLconf
將現在的網頁和視圖配置關聯起來

from django.contrib import admin
from django.urls import path
from learn import views as learn_views  # new

urlpatterns = [
        path('hello/', learn_views.index, name='index'),
    path('admin/', admin.site.urls),
]

上面有一個name屬性,下面我們重點說一下這個屬性的作用。

URL name詳解

簡單說,name 可以用於在 templates, models, views ……中得到對應的網址,相當於“給網址取了個名字”,只要這個名字不變,網址變了也能通過名字獲取到。
爲了進一步弄清這個問題,我們先建一個首頁的視圖和url:在learn這個應用的views.py中添加一下代碼

def index(request):
    return render(request, 'home.html')

我們在 learn 這個 app 中新建一個 templates (文件夾的名字必須要是這個)文件夾,在templates中新建一個 home.html
文件 learn/templates/home.html 中寫入以下內容:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>學習Django</title>
</head>

<body>
<a href="/add/4/5/"> 計算 4+5</a>
</body>
</html>

在上面的home.html文件中,使用了絕對的地址"/add/4/5/"作爲引用。如果以後更改了頁面就要一個地方一個地方修改。這裏有一個解決辦法:使用django提供的reverse函數可以很好的解決這個問題。下面簡單的介紹一下這個函數的基本用法

reverse 接收 url 中的 name 作爲第一個參數,我們在代碼中就可以通過 reverse() 來獲取對應的網址(這個網址可以用來跳轉,也可以用來計算相關頁面的地址),只要對應的 url 的name不改,就不用改代碼中的網址。

不帶參數的:
{% url 'name' %}
帶參數的:參數可以是變量名
{% url 'name' 參數 %}
例如:
<a href="{% url 'add2' 4 5 %}">link</a>
因此之前的代碼<a href="/add/4/5/"> 計算 4+5</a>
可以寫成:
<a href="{% url 'add2' 4 5 %}"> 計算 4+5</a>

當 urls.py 進行更改,前提是不改 name(這個參數設定好後不要輕易改),獲取的網址也會動態地跟着變。

另外,比如用戶收藏夾中收藏的URL是舊的,如何讓以前的 /add/3/4/自動跳轉到現在新的網址呢?
具體思路是,在 views.py 寫一個跳轉的函數:
from django.urls import reverse  # Django 1.10.x - Django 2.x
def old_add2_redirect(request, a, b):
    return HttpResponseRedirect(
        reverse('add2', args=(a, b))
    )
    
urls.py中添加如下代碼:
    path('new_add/<int:a>/<int:b>/', learn_views.old_add2_redirect),  # 這裏居然不可以用正則表達式
    path('add2/<int:a>/<int:b>/', learn_views.add2, name='add2'),
    在測試的時候發現這裏用正則表達式的限制起始字符的表達式的話要出錯。

模板使用

網站模板的設計,一般的,我們做網站有一些通用的部分,比如 導航,底部,訪問統計代碼等等。nav.html, bottom.html, tongji.html

可以寫一個 base.html 來包含這些通用文件(include)

<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}默認標題{% endblock %} - 自強學堂</title>
</head>
<body>
 
{% include 'nav.html' %}
 
{% block content %}
<div>這裏是默認內容,所有繼承自這個模板的,如果不覆蓋就顯示這裏的默認內容。</div>
{% endblock %}
 
{% include 'bottom.html' %}
 
{% include 'tongji.html' %}
 
</body>
</html>

如果需要,寫足夠多的 block 以便繼承的模板可以重寫該部分,include 是包含其它文件的內容,就是把一些網頁共用的部分拿出來,重複利用,改動的時候也方便一些,還可以把廣告代碼放在一個單獨的html中,改動也方便一些,在用到的地方include進去。其它的頁面繼承自 base.html 就好了,繼承後的模板也可以在 block 塊中 include 其它的模板文件。

比如我們的首頁 home.html,繼承或者說擴展(extends)原來的 base.html,可以簡單這樣寫,重寫部分代碼(默認值的那一部分不用改)

{% extends 'base.html' %}
 
{% block title %}歡迎光臨首頁{% endblock %}
 
{% block content %}
{% include 'ad.html' %}
這裏是首頁,歡迎光臨
{% endblock %}

注意:模板一般放在app下的templates中,Django會自動去這個文件夾中找。但 假如我們每個app的templates中都有一個 index.html,當我們在views.py中使用的時候,直接寫一個 render(request, ‘index.html’),Django 能不能找到當前 app 的 templates 文件夾中的 index.html 文件夾呢?(答案是不一定能,有可能找錯)

Django 模板查找機制: Django 查找模板的過程是在每個 app 的 templates 文件夾中找(而不只是當前 app 中的代碼只在當前的 app 的 templates 文件夾中找)。各個 app 的 templates 形成一個文件夾列表,Django 遍歷這個列表,一個個文件夾進行查找,當在某一個文件夾找到的時候就停止,所有的都遍歷完了還找不到指定的模板的時候就是 Template Not Found (過程類似於Python找包)。這樣設計有利當然也有弊,有利是的地方是一個app可以用另一個app的模板文件,弊是有可能會找錯了。所以我們使用的時候在 templates 中建立一個 app 同名的文件夾,這樣就好了。

這就需要把每個app中的 templates 文件夾中再建一個 app 的名稱,僅和該app相關的模板放在 app/templates/app/ 目錄下面,
這樣,使用的時候,模板就是 “app1/index.html” 和 “app2/index.html” 這樣有app作爲名稱的一部分,就不會混淆。

Django模板中的循環,條件判斷,常用的標籤,過濾器的使用

1、列表,字典,類的實例的使用
2、循環:迭代顯示列表,字典等中的內容
3、條件判斷:判斷是否顯示該內容,比如判斷是手機訪問,還是電腦訪問,給出不一樣的代碼。
4、標籤:for,if 這樣的功能都是標籤。
5、過濾器:管道符號後面的功能,比如{{ var|length }},求變量長度的 length 就是一個過濾器。

實例一,顯示一個基本的字符串在網頁上
views.py
# -*- coding: utf-8 -*-
from django.shortcuts import render
 
def home(request):
    string = u"我在自強學堂學習Django,用它來建網站"
    return render(request, 'home.html', {'string': string})
在視圖中我們傳遞了一個字符串名稱是 string 到模板 home.html,在模板中這樣使用它:

home.html
{{ string }}


實例二,講解了基本的 for 循環 和 List內容的顯示
views.py
def home(request):
    TutorialList = ["HTML", "CSS", "jQuery", "Python", "Django"]
    return render(request, 'home.html', {'TutorialList': TutorialList})
在視圖中我們傳遞了一個List到模板 home.html,在模板中這樣使用它:

home.html
教程列表:
{% for i in TutorialList %}
{{ i }}
{% endfor %}


實例三,顯示字典中內容:
views.py
def home(request):
    info_dict = {'site': u'自強學堂', 'content': u'各種IT技術教程'}
    return render(request, 'home.html', {'info_dict': info_dict})
    
home.html
站點:{{ info_dict.site }} 內容:{{ info_dict.content }}
還可以這樣遍歷字典:
{% for key, value in info_dict.items %}
    {{ key }}: {{ value }}
{% endfor %}


實例四,在模板進行 條件判斷和 for 循環的詳細操作:
views.py
def home(request):
    List = map(str, range(100))# 一個長度爲100的 List
    return render(request, 'home.html', {'List': List})
假如我們想用逗號將這些元素連接起來:

home.html
{% for item in List %}
    {{ item }}, 
{% endfor %}
我們會發現最後一個元素後面也有一個逗號,這樣肯定不爽,如果判斷是不是遍歷到了最後一個元素了呢?
用變量 forloop.last 這個變量,如果是最後一項其爲真,否則爲假,更改如下:
{% for item in List %}
    {{ item }}{% if not forloop.last %},{% endif %} 
{% endfor %}


實例五,模板上得到視圖對應的網址:
# views.py
def add(request, a, b):
    c = int(a) + int(b)
    return HttpResponse(str(c))
 
# urls.py
urlpatterns = patterns('',
    url(r'^add/(\d+)/(\d+)/$', 'app.views.add', name='add'),
)
 
# template.html
{% url 'add' 4 5 %}
這樣網址上就會顯示出:/add/4/5/ 這個網址,假如我們以後修改 urls.py 中的 
r'^add/<int:a>/<int:b>/$'
這一部分,改成另的,比如:
r'^jiafa/<int:a>/<int:b>/$'
這樣,我們不需要再次修改模板,當再次訪問的時候,網址會自動變成 /jiafa/4/5/

還可以使用 as 語句將內容取別名(相當於定義一個變量),多次使用(但視圖名稱到網址轉換隻進行了一次)
{% url 'some-url-name' arg arg2 as the_url %}
<a href="{{ the_url }}">鏈接到:{{ the_url }}</a>

實例六,模板中的邏輯操作:
 ==, !=, >=, <=, >, < 這些比較都可以在模板中使用,比如:
{% if var >= 90 %}
成績優秀,自強學堂你沒少去吧!學得不錯
{% elif var >= 80 %}
成績良好
{% elif var >= 70 %}
成績一般
{% elif var >= 60 %}
需要努力
{% else %}
不及格啊,大哥!多去自強學堂學習啊!
{% endif %}
(注意:比較符號前後必須有至少一個空格!)

and, or, not, in, not in 也可以在模板中使用
假如我們判斷 num 是不是在 0 到 100 之間:
{% if num <= 100 and num >= 0 %}
num在0到100之間
{% else %}
數值不在範圍之內!
{% endif %}
假如我們判斷 'ziqiangxuetang' 在不在一個列表變量 List 中:
{% if 'ziqiangxuetang' in List %}
自強學堂在名單中
{% endif %}

實例七,模板中 獲取當前網址,當前用戶等:
7.1 獲取當前用戶:
{{ request.user }}
如果登陸就顯示內容,不登陸就不顯示內容:
{% if request.user.is_authenticated %}
    {{ request.user.username }},您好!
{% else %}
    請登陸,這裏放登陸鏈接
{% endif %}

7.2.1 獲取當前網址:
{{ request.path }}
7.2.2 獲取當前 GET 參數:
{{ request.GET.urlencode }}
7.2.3 合併到一起用的一個例子:
<a href="{{ request.path }}?{{ request.GET.urlencode }}&delete=1">當前網址加參數 delete</a>
比如我們可以判斷 delete 參數是不是 1 來刪除當前的頁面內容。

Django 模型(數據庫)

Django 模型是與數據庫相關的,與數據庫相關的代碼一般寫在 models.py 中,Django 支持 sqlite3, MySQL, PostgreSQL等數據庫,只需要在settings.py中配置即可,不用更改models.py中的代碼,豐富的API極大的方便了使用。

1、修改models.py
我們打開 learn/models.py 文件,修改其中的代碼如下:
from django.db import models
 
class Person(models.Model):
    name = models.CharField(max_length=30)
    age = models.IntegerField()

2、創建數據表
我們來同步一下數據庫(我們使用默認的數據庫 SQLite3,無需配置)
先 cd 進入 manage.py 所在的那個文件夾下,輸入下面的命令
# Django 1.7 及以上的版本需要用以下命令
python manage.py makemigrations
python manage.py migrate

3、使用 Django 提供的 QuerySet API
from people.models import Person
Person.objects.create(name="WeizhongTu", age=24)
我們新建了一個用戶WeizhongTu 那麼如何從數據庫是查詢到它呢?
Person.objects.get(name="WeizhongTu")
我們用了一個 .objects.get() 方法查詢出來符合條件的對象,但是大家注意到了沒有,查詢結果中顯示<Person: Person object>,這裏並沒有顯示出與WeizhongTu的相關信息,如果用戶多了就無法知道查詢出來的到底是誰,查詢結果是否正確,我們重新修改一下 learn/models.py
from django.db import models
 
class Person(models.Model):
    name = models.CharField(max_length=30)
    age = models.IntegerField()
     
    def __str__(self):
        return self.name
name 和 age 等字段中不能有 __(雙下劃線,因爲在Django QuerySet API中有特殊含義(用於關係,包含,不區分大小寫,以什麼開頭或結尾,日期的大於小於,正則等)

Django QuerySet API
這裏專門來講一下數據庫接口相關的接口(QuerySet API),當然您也可以選擇暫時跳過此節,如果以後用到數據庫相關的時候再看也是可以的。
從數據庫中查詢出來的結果一般是一個集合,這個集合叫做 QuerySet。

文中的例子大部分是基於這個 blog/models.py

from django.db import models
 
 
class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()
 
    def __str__(self):  # __str__ on Python 3
        return self.name
 
class Author(models.Model):
    name = models.CharField(max_length=50)
    email = models.EmailField()
 
    def __str__(self):  # __str__ on Python 3
        return self.name
 
class Entry(models.Model):
    blog = models.ForeignKey(Blog)
    headline = models.CharField(max_length=255)
    body_text = models.TextField()
    pub_date = models.DateField()
    mod_date = models.DateField()
    authors = models.ManyToManyField(Author)
    n_comments = models.IntegerField()
    n_pingbacks = models.IntegerField()
    rating = models.IntegerField()
 
    def __str__(self):  
        return self.headline
  1. QuerySet 創建對象的方法
from blog.models import Blog
b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
b.save()

總之,一共有四種方法
# 方法 1
Author.objects.create(name="WeizhongTu", email="[email protected]")
 
# 方法 2
twz = Author(name="WeizhongTu", email="[email protected]")
twz.save()
 
# 方法 3
twz = Author()
twz.name="WeizhongTu"
twz.email="[email protected]"
twz.save()
 
# 方法 4,首先嚐試獲取,不存在就創建,可以防止重複
Author.objects.get_or_create(name="WeizhongTu", email="[email protected]")
# 返回值(object, True/False)

當有一對多,多對一,或者多對多的關係的時候,先把相關的對象查詢出來
from blog.models import Entry
entry = Entry.objects.get(pk=1)
cheese_blog = Blog.objects.get(name="Cheddar Talk")
entry.blog = cheese_blog
entry.save()

前三種方法返回的都是對應的 object,最後一種方法返回的是一個元組,(object, True/False),創建時返回 True, 已經存在時返回 False。

  1. 獲取對象的方法(上一篇的部分代碼)
Person.objects.all() # 查詢所有
Person.objects.all()[:10] 切片操作,獲取10個人,不支持負索引,切片可以節約內存,不支持負索引,後面有相應解決辦法,第7條
Person.objects.get(name="WeizhongTu") # 名稱爲 WeizhongTu 的一條,多條會報錯
 
get是用來獲取一個對象的,如果需要獲取滿足條件的一些人,就要用到filter
Person.objects.filter(name="abc") # 等於Person.objects.filter(name__exact="abc") 名稱嚴格等於 "abc" 的人
Person.objects.filter(name__iexact="abc") # 名稱爲 abc 但是不區分大小寫,可以找到 ABC, Abc, aBC,這些都符合條件
 
Person.objects.filter(name__contains="abc") # 名稱中包含 "abc"的人
Person.objects.filter(name__icontains="abc") #名稱中包含 "abc",且abc不區分大小寫
 
Person.objects.filter(name__regex="^abc") # 正則表達式查詢
Person.objects.filter(name__iregex="^abc")# 正則表達式不區分大小寫
 
# filter是找出滿足條件的,當然也有排除符合某條件的
Person.objects.exclude(name__contains="WZ") # 排除包含 WZ 的Person對象
Person.objects.filter(name__contains="abc").exclude(age=23) # 找出名稱含有abc, 但是排除年齡是23歲的
  1. 刪除符合條件的結果
Person.objects.filter(name__contains="abc").delete() # 刪除 名稱中包含 "abc"的人
 
如果寫成 
people = Person.objects.filter(name__contains="abc")
people.delete()
效果也是一樣的,Django實際只執行一條 SQL 語句。
  1. 更新某個內容
    (1) 批量更新,適用於 .all() .filter() .exclude() 等後面 (危險操作,正式場合操作務必謹慎)
    Person.objects.filter(name__contains="abc").update(name='xxx') # 名稱中包含 "abc"的人 都改成 xxx
    Person.objects.all().delete() # 刪除所有 Person 記錄

(2) 單個 object 更新,適合於 .get(), get_or_create(), update_or_create() 等得到的 obj,和新建很類似。

    twz = Author.objects.get(name="WeizhongTu")
    twz.name="WeizhongTu"
    twz.email="[email protected]"
    twz.save()  # 最後不要忘了保存!!!
  1. QuerySet 是可迭代的,比如:
es = Entry.objects.all()
for e in es:
      print(e.headline)

Entry.objects.all() 或者 es 就是 QuerySet 是查詢所有的 Entry 條目。

注意事項:

(1). 如果只是檢查 Entry 中是否有對象,應該用 Entry.objects.all().exists()

(2). QuerySet 支持切片 Entry.objects.all()[:10] 取出10條,可以節省內存

(3). 用 len(es) 可以得到Entry的數量,但是推薦用 Entry.objects.count()來查詢數量,後者用的是SQL:SELECT COUNT(*)

(4). list(es) 可以強行將 QuerySet 變成 列表

  1. QuerySet 是可以用pickle序列化到硬盤再讀取出來的
import pickle
query = pickle.loads(s)     # Assuming 's' is the pickled string.
 qs = MyModel.objects.all()
 qs.query = query            # Restore the original 'query'.
  1. QuerySet 查詢結果排序
    作者按照名稱排序
Author.objects.all().order_by('name')
Author.objects.all().order_by('-name') # 在 column name 前加一個負號,可以實現倒序
  1. QuerySet 支持鏈式查詢
Author.objects.filter(name__contains="WeizhongTu").filter(email="[email protected]")
Author.objects.filter(name__contains="Wei").exclude(email="[email protected]")
 
# 找出名稱含有abc, 但是排除年齡是23歲的
Person.objects.filter(name__contains="abc").exclude(age=23)
  1. QuerySet 不支持負索引
Person.objects.all()[:10] 切片操作,前10條
Person.objects.all()[-10:] 會報錯!!!
 
# 1. 使用 reverse() 解決
Person.objects.all().reverse()[:2] # 最後兩條
Person.objects.all().reverse()[0] # 最後一條
 
# 2. 使用 order_by,在欄目名(column name)前加一個負號
Author.objects.order_by('-id')[:20] # id最大的20條
  1. QuerySet 重複的問題,使用 .distinct() 去重
    一般的情況下,QuerySet 中不會出來重複的,重複是很罕見的,但是當跨越多張表進行檢索後,結果併到一起,可能會出來重複的值(我最近就遇到過這樣的問題)
qs1 = Pathway.objects.filter(label__name='x')
qs2 = Pathway.objects.filter(reaction__name='A + B >> C')
qs3 = Pathway.objects.filter(inputer__name='WeizhongTu')
 
# 合併到一起
qs = qs1 | qs2 | qs3
這個時候就有可能出現重複的
 
# 去重方法
qs = qs.distinct()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章