學習Django(1)

先把github鏈接放上來:
https://github.com/q100036q/python_demo_learning_logs

第一:安裝Django

在windows系統下安裝和使用Django很簡單,而且為了創建新的工程項目,可以創建一個虛擬的環境來獨立的編程。
創建新的虛擬項目和安裝Django的流程如下:

1.新建一個工程路徑,打開控制臺,切換到這個路徑下。

2.輸入下面代碼創建一個虛擬環境:

    python -m venv ll_env

3.激活虛擬環境,有兩種方法:第一是直接輸入:

    ll_env\Scripts\activate

上述代碼進行創建,第二種是,打開ll_env\Scripts文件夾,按住shift點擊鼠標右鍵,打開命令窗口再把activate.bat拖進去。這種方法適合第一次之后的打開,就不用再命令行手動操作了。

4.創建并激活虛擬環境后,就可安裝Django了,輸入下面代碼:

    pip install Django

第二:在Django中創建項目

1.創建項目路徑,用下面創建一個名為learning_log 的文件夾:

    django-admin.py startproject learning_log .

可是經過測驗,上面教程中的代碼無效,在網上只能找到另一種方案,輸入下面代碼:

    django-admin startproject learning_log .

最后的點不能省略,這個命令末尾的句點讓新項目使用合適的目錄結構,manage.py這個文件會和ll_env文件夾同級,否則將會放進learning_log 文件夾下。
現在在ll_env文件夾同級目錄下,新出現了learning_log文件夾和manage.py文件。

2.創建數據庫。使用manage.py文件進行數據庫的遷移指令,可以新建一個文件數據庫:

    python manage.py migrate 

這時候在ll_env文件夾同級目錄下又出現了一個名為db.sqlite3的數據庫文件。

3.查看項目是否能執行。

    python manage.py runserver

上述代碼能夠運行一個服務器,并顯示出來url路徑,這時候我們可以通過瀏覽器輸入它來訪問這個本地服務器。

第三:創建一個應用程序

1.在第二步運行了一個服務器的情況下,重新再manage.py的路徑下打開一個命令行窗口,并執行激活(第一步的第3條)。

2.執行命令startapp,它可以創建一個在同級路徑下的應用程序。

    python manage.py startapp learning_logs 

可以看到,文件夾路徑下多了一個名為learning_logs的文件夾,這個和之前第二步第1條創建的learning_log有很大的區別,具體看下圖:


2019226-172748.jpg

可以看到兩個文件夾內容完全不同??梢赃@么理解,learning_log是我們控制中心,存放一些配置相關的內容,而learning_logs是我們自己編寫程序的部分,用來管理數據。

3.定義模型,其實也就是創建各種各樣的類,來達到目的,目前這個工程主要是用來保存數據,這里再models.py文件下定義兩個類,一個用于保存標題,另一個保存內容,后者需要鏈接到前者。先看代碼:

#models.py   
from django.db import models
class Topic(models.Model):
  text = models.CharField(max_length = 200);
  date_added = models.DateTimeField(auto_now_add = True);

  def __str__(self):
    return self.text;

class Entry(models.Model):
  topic = models.ForeignKey(Topic,on_delete = models.CASCADE);
  text = models.TextField();
  date_added = models.DateTimeField(auto_now_add=True);

  class Meta:
    verbose_name_plural = 'entries';

   def __str__(self):
      if len(self.text) > 50:
          return self.text[:50] + '...';
      else:
          return self.text;

models.CharField是儲存字符或文本數據,models.TextField類似,但是是沒有長度限制,顯示在web上出來是一個文本框。
1)這里重點一個是on_delete = models.CASCADE這段代碼,如果不加會報錯,主要是因為Django更新至2.0以上版本了。
2)方法str() 告訴Django,呈現條目時應顯示哪些信息。
3)我們在Entry 類中嵌套了Meta 類。Meta 存儲用于管理模型的額外信息,在這里,它讓我們能夠設置一個特殊屬性,讓Django在需要時使用Entries 來表示多個條目。如果沒有這個類, Django將使用Entrys來表示多個條目。(這段還沒搞懂)。
4)Entry的第一個屬性topic 是一個ForeignKey 實例。外鍵是一個數據庫術語,它引用了數據庫中的另一條記錄;這些代碼將每個條目關聯到特定的主題。每個主題創建時,都給它分配了一個鍵(或ID)。需要在兩項數據之間建立聯系時,Django使用與每項信息相關聯的鍵。

4.激活模型,要使用模型,必須讓Django將應用程序包含到項目中。這里需要用learning_log中的settings.py文件,并在INSTALLED_APPS里包含learning_logs內容:

#settings.py
INSTALLED_APPS = (
--snip--
'django.contrib.staticfiles',
# 我的應用程序
'learning_logs',
)

5.接下來,修改數據庫,使其能保存我們在models.py中定義的模型:

    python manage.py makemigrations learning_logs

接著進行數據庫的遷移,為我們的新模型去創建一個表:

    python manage.py migrate

6.Django管理網站,首先添加一個超級管理員的權限,這樣能在web上修改添加內容:

    python manage.py createsuperuser

按照提示輸入自己的信息即可。
接著,向管理網站注冊模型,之前定義的兩個模型,在這里要進行注冊,注冊的代碼寫在admin.py中:

#admin.py      
from django.contrib import admin;
from learning_logs.models import Topic,Entry;

admin.site.register(Topic);
admin.site.register(Entry);

最后就可以訪問http://localhost:8000/admin/ ,輸入賬號密碼進入后臺,此時可以針對Topic和Entry進行編輯了,由于綁定外鍵的關系,一定要有一個Topic內容,才能去添加Entry。

7.Django shell,可以使用shell來探索存儲在項目數據庫中的數據。

python manage.py shell

上面代碼可以運行到shell中,運行下面腳本,查看下我們數據庫的內容:

 from learning_logs.models import Topic
 topics = Topic.objects.all()
 for topic in topics:
    print(topic.id, topic)
  t = Topic.objects.get(id=1)
  t.text
  t.entry_set.all()

最后這條t.entry_set.all(),為通過外鍵關系獲取數據,可使用相關模型的小寫名稱、下劃線和單詞set。

8.遇到的問題:

1)每次修改模型(manage.py文件),要重啟shell;
2)有的時候如果增加了新模型,要去修改admin.py增加新的注冊。
3)一般情況下,不需要重啟服務器,但是如果一直不響應的情況下,可以ctrl+c關閉,在使用第二步的第3條重啟。
4)關閉shall的方法:ctrl+z再回車即可。

第四:映射URL

簡單的說就是設置打開瀏覽器的頁面。這里先修改默認的主頁。

1.修改主目錄url內容,打開項目主文件夾learning_log中的文件urls.py,這里添加內容:

#urls.py(learning_log/urls.py)
from django.contrib import admin;
from django.urls import path,include;
from django.conf.urls import url;

urlpatterns = [
  path('admin/', admin.site.urls),
  # path(r'',include('learning_logs.urls',namespace = 'learning_logs')),
  url(r'',include('learning_logs.urls',namespace = 'learning_logs'))
]

在Django1.11中路由函數為url(),在Django2中路由函數改成了path(),不過路由函數向下兼容,在Django2中同樣可以使用url()函數,這里列出兩種寫法,注意引入對應的模塊,這里加載指向learning_logs.urls這個文件,namespace只是為了和別的url作區分。

2.添加新目錄下的url,填寫現在我們需要在文件夾learning_logs中創建另一個urls.py文件,內容如下:

#urls.py
from django.conf.urls import url;
from . import views;
app_name='learning_logs'

urlpatterns = [
  url(r'^$',views.index,name = 'index'),
]

我們來看看正則表達式r'^$' 。其中的r 讓Python將接下來的字符串視為原始字符串,而引號告訴Python正則表達式始于和終于何處。脫字符(^ )讓Python查看字符串的開頭,而美元符號讓Python查看字符串的末尾??傮w而言,這個正則表達式讓Python查找開頭和末尾之間沒有任何東西的URL。Python忽略項目的基礎URL(http://localhost:8000/),因此這個正則表達式與基礎URL匹配。
url() 的第二個實參指定了要調用的視圖函數。請求的URL與前述正則表達式匹配時,Django將調用views.index (這個視圖函數將在下一節編寫)。第三個實參將這個URL模式的名稱指定為index,讓我們能夠在代碼的其他地方引用它。每當需要提供到這個主頁的鏈接時,我們都將使用這個名稱,而不編寫URL。

3.編寫視圖內容,視圖函數接受請求中的信息,準備好生成網頁所需的數據,再將這些數據發送給瀏覽器,這個依據模板代碼來實現不同的效果,這里我們修改views.py文件:

#views.py
from django.shortcuts import render
def index(request):
    """學習筆記的主頁"""
    return render(request, 'learning_logs/index.html')

URL請求與我們剛才定義的模式匹配時,Django將在文件views.py中查找函數index() ,再將請求對象傳遞給這個視圖函數。

4.編寫網頁模板。在文件夾learning_logs中新建一個文件夾,并將其命名為templates。在文件夾templates中,再新建一個文件夾,并將其命名為learning_logs。在最里面的文件夾learning_logs中,新建一個文件,并將其命名為index.html,再在這個文件中編寫如下代碼:

#index.html
<p>Learning Log</p>
<p>Learning Log helps you keep track of your learning, for any topic you'relearning about.</p>

這樣就完成了主頁的編輯。

5.幾個要點:

1)urls.py文件中的urlpatterns不能寫錯,否則會報錯。
2)新創建的子文件夾的urls.py文件需要添加下面這行代碼,否則會報錯:

app_name='learning_logs'

這是因為之前定義了namespace屬性, [app_name]代表你的應用的名稱。
3)這篇代碼編寫完成后不用重啟服務器,在setting.py中設置了DEBUG = True,瀏覽器會自動刷新我們剛保存的代碼。但是,實際運用中DEBUG不能設置為true。

第五:創建其它網頁:

這段是對網頁和之前的數據綁定,把之前存入數據庫的內容展示出來。

1.模板繼承,可以創建一個父模板,讓其他模板(網頁代碼)都繼承它,可以方便統一修改。

下面,為了給幾個子網頁都添加一個統一的內容,父模板僅僅制作帶鏈接的標題,可以讓子模板點擊回到主頁。base.html內容如下:

#base.html
<p>
<a href="{% url 'learning_logs:index' %}">Learning Log</a>
<!--><a href="{% url 'learning_logs:topics' %}">Topics</a><-->
</p>
{% block content %}{% endblock content %}

有網頁制作相關知識的就知道<p>是一個段落標簽,<a>是一個超鏈接標簽,href指向一個鏈接,這里{%%}是一個模板標簽,內容就指向了learning_logs下的index文件,即主頁。{% block content %}{% endblock content %}是一對占位符,具體內容由子模板指定。中間這段被注釋的代碼在后面顯示次級界面的時候要解開注釋?,F在重新編輯index.html文件,讓他繼承父模板base.html:

#index.html
{% extends "learning_logs/base.html" %}

{% block content %}
<p>Learning Log helps you keep track of your learning,for any topic you're learning about.</p>
{% endblock content %}

extends 表示繼承的路徑內容。占位符內容就是這個子模板獨有的內容。它因為繼承自base.html,現在可以顯示如下:


2019228-172334.jpg

2.顯示主題頁面,為了增加新的下一級別的網頁,這里要去修改urls.py文件,增加了一行內容:

 #urls.py
from django.conf.urls import url;

from . import views;
app_name='learning_logs'

urlpatterns = [
  url(r'^$',views.index,name = 'index'),
  url(r'^topics/$',views.topics,name = 'topics'),
]

正則表達式中添加了topics/這一段,說明我們現在匹配的網址應該是:http://127.0.0.1:8000/topics/。其URL與該模式匹配的請求都將交給views.py中的函數topics() 進行處理。接下來,我們去這個文件中把它添加上:

#views.py
from django.shortcuts import render;

from .models import Topic;

def index(request):
    return render(request,'learning_logs/index.html');

def topics(request):
    topics = Topic.objects.order_by('date_added');
    context = {'topics':topics}
    return render(request,'learning_logs/topics.html',context)

這里是一個難點,可能都已經忘記了之前我們做的操作了,這時候翻上去看第三步的第3段,我們在models.py文件內寫下了Topic這個模型,并且定義了name和date_added這個屬性,order_by對其排序,取出所有的值,然后保存為一個字典文件,并命名為context再通過render傳遞到topics.html里接收。現在當然是創建一個名為topics.html的頁面文件了:

#topics.html
{% extends "learning_logs/base.html" %}

{% block content %}
<p>Topics</p>
<ul>
    {% for topic in topics %}
    <li>
         <!-->注意,這段在下面創建topic.html的時候放開注釋,為的是創建一個指向下一層級的超鏈接,并且將topic.id 傳遞到topic.html文件中
          <a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a>
         <-->
          {{ topic }}
    </li>
    {% empty %}
    <li>No topics have been added yet.</li>
    {% endfor %}
</ul>
{% endblock content %}

依照下圖,可以看出上面代碼說的到底是啥,<ul><li>分別代表無序列表和列表項的標簽, {% for%}和 {% endfor %}用來當做一個for循環,讀取views.py傳遞過來的內容,并做成超鏈接,{{ topic }} 是將每一項名稱都顯示,不是使用一對,而是兩對,不然顯示的內容是:{ topic }。{% empty %}這個告訴了我們,這個循環內容為空的時候顯示什么東西。


2.jpg

這時候,上面第五步的第1段中的注釋代碼要解開。

3.顯示對應主題的內容。

之前,我們在定義文件的標題的同時也保存了相應的內容,這里我們點擊每個列表項之后,打開新的頁面去顯示它。為了打開新的頁面,必須去urls.py增加新的配置:

#urls.py
from django.conf.urls import url;
from . import views;
app_name='learning_logs'

urlpatterns = [
    url(r'^$',views.index,name = 'index'),
    url(r'^topics/$',views.topics,name = 'topics'),
    url(r'^topics/(?P<topic_id>\d+)/$',views.topic,name = 'topic'),
]

最后一行新增內容:在r'^$'直接加入了topics/(?P<topic_id>\d+)/這么一句正則表達式,作用就是匹配到http://localhost:8000/topics/1/這樣的URL,d+表示任意數字,(?P)為命名捕獲,是捕獲內容儲存到topic_id中,這個是python專有的語法。接下來還是根據這里設置的views.topic去views.py文件中新增topic函數:

 #views.py
 from django.shortcuts import render;
 from .models import Topic;

def index(request):
    return render(request,'learning_logs/index.html');

def topics(request):
    topics = Topic.objects.order_by('date_added');
    context = {'topics':topics}
    return render(request,'learning_logs/topics.html',context)

def topic(request,topic_id):
    topic = Topic.objects.get(id = topic_id);
    entries = topic.entry_set.order_by('-date_added');
    context = {'topic':topic,'entries':entries}
    return render(request,'learning_logs/topic.html',context)

topic函數傳入剛剛捕獲到的參數topic_id,然后根據之前在shell里學習的方法,去數據庫中讀取數據,再通過date_added倒序排序,entry_set讀取出我們之前存入數據庫中的內容(忘記的話參考第三步的第7條),存進字典新增一項。最后通過render一起傳給topic.html。

注意,這時候要把第五步第2段中topics.html文件中的注釋解開。

這時候創建這個文件:

#topic.html
{% extends "learning_logs/base.html" %}

{% block content %}
<p>Topics:{{topic}}</p>
<p>Entries:</p>
<ul>
    {% for entry in entries %}
    <li>
        <p>{{ entry.date_add|date:'M d,Y H:i'}}</p>
        <p>{{ entry.text|linebreaks }}</p>
    </li>
    {% empty %}
    <li>There are no entries for this topic yet.</li>
    {% endfor %}
</ul>
{% endblock content %}

這里其實很好理解,首先顯示Topics的值,這個在views.py里獲得了。然后通過for循環讀取entries里面的內容,并且對應的格式化顯示,|符合是一個過濾器,linebreaks 作用是將包含換行符的長條目轉換為瀏覽器能夠理解的格式。這一切完成之后,顯示內容如下圖:


3.jpg

第六:總結

總得縷了一下,django框架可以把數據庫,網頁結合起來,就不用和javaSE那樣分開做了,目前這個案例最傻的就是命名太相似,這樣要深刻理解代碼中寫的到底是指什么,代碼互相調用,文件互相調用要深刻理解,下面是我整理的調用流程:


4.jpg

下面是發現的一個容易出錯的問題,在<a>標簽頁內,'url'這個和之后的內容一定要分開,如果和下圖一樣連著,就會出現下面報錯?。?!


6.jpg
7.jpg
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,119評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,382評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,038評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,853評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,616評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,112評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,192評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,355評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,869評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,727評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,928評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,467評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,165評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,570評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,813評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,585評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,892評論 2 372

推薦閱讀更多精彩內容