用 Django 和 Python 構建個人日記

      網友投稿 1125 2025-03-31

      目錄

      演示視頻

      項目概況

      先決條件

      第 1 步:設置你的 django 日記

      初始化 django

      創建數據庫

      成為超級用戶

      運行開發 Web 服務器

      第 2 步:將您的日記條目添加到后端

      連接條目應用程序

      創建條目模型

      注冊入門模型

      遷移入口模型

      第 3 步:在前端顯示您的日記條目

      創建列表和詳細信息視圖

      創建您的模板

      將路線添加到您的視圖

      第 4 步:讓你的 Django 日記看起來不錯

      添加樣式表

      擴展子模板

      第 5 步:在前端管理您的日記條目

      添加視圖

      創建模板

      創建 URL

      第 6 步:改善您的用戶體驗

      處理您的成功

      獲取消息

      改善您的導航

      設計您的消息

      第 7 步:鎖定你的 Django 日記

      重用您的 Django 管理員登錄

      添加注銷鏈接

      限制訪問您的視圖

      下一步

      結論

      一個日記是個人安全的空間。在 Django 的幫助下,您可以在自己的計算機上創建日記,而無需將數據存儲在其他人的云端。通過跟隨下面的項目,您將看到在 Django 中構建一個正常運行的Web 應用程序的速度有多快,而無需任何外部依賴。

      在本教程中,您將學習如何:

      設置Django 項目

      使用標準SQLite數據庫

      使用 Django管理站點

      創建模型和基于類的視圖

      嵌套和樣式模板

      通過身份驗證保護您的日記

      本教程將指導您逐步完成最終日記。如果您剛剛開始使用 Django 并希望完成您的第一個真正的項目,那么本教程適合您!

      演示視頻

      在您日記的主頁上,您會看到一個條目列表。您可以滾動瀏覽它們并通過單擊按鈕創建新的。本教程中提供了樣式,因此您可以專注于代碼的 Django 部分。這是一個快速演示視頻,展示了它的實際效果:

      在本教程結束時,您將能夠完美地瀏覽您的日記,以按需創建、閱讀、更新和刪除條目。

      項目概況

      本教程分為多個步驟。這樣,您就可以休息并按照自己的節奏繼續。在每一步中,您都將處理日記項目的特定領域:

      設置你的 Django 日記項目

      在后端創建條目

      在前端顯示條目

      添加樣式

      在前端管理條目

      改善您的用戶體驗

      實施認證

      通過跟隨,您將探索 Web 應用程序的基礎知識以及如何添加 Django 項目的常見功能。完成本教程后,您將創建自己的個人日記應用程序,并將有一個Django 項目藍圖來構建。

      先決條件

      您不需要任何先前的 Django 知識即可完成此項目。如果您想了解有關本教程中遇到的主題的更多信息,您將在此過程中找到指向資源的鏈接。

      但是,您應該習慣于使用命令行并且具備Python 和類的基本知識。盡管了解虛擬環境和會有所幫助,但您將在學習本教程時學習如何設置所有內容。pip

      第 1 步:設置你的 Django 日記

      通過創建項目目錄并設置虛擬環境來啟動項目。此設置將使您的代碼與您機器上的任何其他項目隔離。您可以隨意命名項目文件夾和虛擬環境。在本教程中,項目文件夾命名為my-diary,虛擬環境命名為.venv:

      $ mkdir my-diary $ cd my-diary $ python3 -m venv .venv $ source .venv/bin/activate

      您的提示現在以括號中的虛擬環境名稱開頭。這是虛擬環境被激活的指示符。對于本教程的其余部分,必須激活您的虛擬環境。以下所有步驟都將在此目錄或其子目錄中進行。

      注意:要在Windows上激活您的虛擬環境,您可能需要運行以下命令:

      c:\> python -m venv .venv c:\> .venv\Scripts\activate.bat

      對于其他平臺和 shell,您可能需要使用不同的命令。

      對您的日記唯一的其他要求是 Django 本身。安裝本教程的特定版本pip:

      (.venv) $ python -m pip install Django==3.2.1

      此命令安裝 Django 和 Django 需要的一些依賴項。這就是您所需要的一切。

      初始化 Django

      滿足所有要求后,是時候啟動 Django 項目本身了。使用 Django 的命令行實用程序創建基本項目結構:

      (.venv) $ django-admin startproject diary .

      不要忘記.在上述命令的末尾添加點 (?)。點阻止 Django 為您的日記項目創建另一個目錄。

      Django 剛剛創建了一個manage.py文件和一個以diary五個文件命名的文件夾。您不必確切了解他們的工作。如果你好奇,你可以看一看這些文件。它們在開頭都包含一個解釋,描述它們為什么存在。在本教程中,您只需要編輯其中兩個:

      從現在開始,該manage.py文件將接管命令行中的管理任務。您將在本教程中遇到其中一些。

      創建數據庫

      現在你的 Django 日記項目的基礎已經準備好了,你需要一個地方來存儲你日記的未來內容。為此,您必須創建一個數據庫。

      如果沒有提供其他數據庫配置,Django默認支持多個數據庫并使用SQLite數據庫。您只需要一個SQLite數據庫,因為您是連接到它的唯一用戶,并且您的 Django 日記項目只會在本地運行。

      最好的部分是您可以使用單個命令創建 SQLite 數據庫。通過運行migrations,您可以將數據庫架構的更改應用到數據庫中:

      (.venv) $ python manage.py migrate

      當您查看項目目錄時,您應該會看到一個db.sqlite3文件。拍拍自己的肩膀:您剛剛創建了一個數據庫!

      要將項目的當前狀態與本教程的可下載文件進行比較,請單擊以下鏈接:

      獲取源代碼:?單擊此處獲取您將在本教程中使用 Django 和 Python 構建個人日記 Web 應用程序的源代碼。

      與本節相關的文件在source_code_step_1/目錄中。

      成為超級用戶

      作為您個人日記的所有者,您已經獲得了superuser.?使用以下命令聲明它:

      (.venv) $ python manage.py createsuperuser Username (leave blank to use 'root'): admin Email address: admin@example.com Password: RealPyth0n Password (again): RealPyth0n Superuser created successfully.

      系統會提示您選擇用戶名、提供電子郵件地址并設置密碼。這是你日記的關鍵,所以一定要記住它。

      運行開發 Web 服務器

      您將經常使用的另一個命令是runserver.?此命令運行輕量級開發 Web 服務器:

      (.venv) $ python manage.py runserver

      您可以指定IP 地址和端口runserver。默認情況下,服務器在端口8000上運行127.0.0.1并且只能在您的計算機上訪問。在服務器運行的情況下,您可以在瀏覽器中使用http://127.0.0.1:8000或訪問您的 Django 項目http://localhost:8000:

      這是您日記的主頁。到目前為止,只能看到火箭。這意味著安裝成功。

      重要提示:每次在瀏覽器中訪問日記項目時,如果尚未運行,則必須先啟動本地開發 Web 服務器。

      通過訪問http://localhost:8000/admin并使用您的憑據登錄來完成本教程的第一步:

      這是您自己的Django 管理站點!它是 Django最強大的功能之一。只需進行一些調整,您就可以立即管理內容和用戶。目前,在 Django 管理站點中沒有什么可看的。是時候改變它了!

      第 2 步:將您的日記條目添加到后端

      一個 Django 項目包含一個或多個應用程序。應用程序的范圍應該是有限的。一開始,區分項目和應用程序可能會令人困惑。但是在大型 Django 項目中,這種關注點分離可以保持代碼庫干凈。這種結構的另一個優點是您可以將應用程序重用于其他項目。

      連接條目應用程序

      在您的終端中,Django 開發 Web 服務器可能仍在運行。通過在終端中按Ctrl+C來停止它。

      提示:打開第二個終端窗口以在一個窗口中控制服務器并在另一個窗口中運行命令:

      導航到您的項目并激活虛擬環境后,您可以在第二個終端窗口中運行該項目即將執行的命令。

      在本教程中,您只需要一個額外的應用程序。該應用程序的主要目的是處理您的日記條目,所以讓我們調用該應用程序entries。運行命令以創建entries應用程序:

      (.venv) $ python manage.py startapp entries

      此命令entries在您的項目中創建一個包含一些預定義文件的文件夾。在本教程后面,您只需要編輯其中的三個:

      如您所見,其中一些與diary/目錄中的文件具有相同的名稱。通過單擊下面的鏈接,您可以將您的文件夾結構與目錄中的結構進行比較source_code_step_2/:

      獲取源代碼:?單擊此處獲取您將在本教程中使用 Django 和 Python 構建個人日記 Web 應用程序的源代碼。

      到目前為止,Django 不知道您剛剛創建的應用程序。要將entries應用程序連接到 Django 日記項目,請在 中的列表開頭添加配置類的路徑:INSTALLED_APPSdiary/settings.py

      # diary/settings.py INSTALLED_APPS = [ "entries.apps.EntriesConfig", "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", ]

      該entries應用程序插入到diary項目,現在,Django的發現它的配置。這些配置之一是描述您的日記條目在數據庫中的外觀的模型。

      創建條目模型

      您已經創建了數據庫。現在是時候定義存儲日記條目的數據庫表了。在 Django 中,您可以使用模型類來做到這一點。就像 Python 中的常規類一樣,模型名稱應該是單數和大寫。當您的應用程序被調用時entries,您的模型將被調用Entry。

      Entry模型的字段是日記條目將具有的元素。在前面,這些字段將顯示為表單。在后面,它們將是您的Entry數據庫表的列。本教程中的日記條目包含三個字段:

      title?是標題。

      content?是正文正文。

      date_created?是創建日期和時間。

      在 中entries/models.py,首先從導入?。然后在同一個文件中創建類,如下所示:timezonedjango.utilsEntry

      1# entries/models.py 2 3from django.db import models 4from django.utils import timezone 5 6class Entry(models.Model): 7 title = models.CharField(max_length=200) 8 content = models.TextField() 9 date_created = models.DateTimeField(default=timezone.now) 10 11 def __str__(self): 12 return self.title 13 14 class Meta: 15 verbose_name_plural = "Entries"

      通過導入timezone模塊,您可以將其timezone.now用作第9 行中的default參數date_created。這樣,如果您在創建條目時未為其定義特定值,則默認情況下將使用當前日期和時間。稍后在為日記條目創建表單時,您將使用此行為。

      除了title,?content, 和 之外date_created,Django 會自動添加id一個唯一的主鍵。該字符串表示與主鍵條目的1將是Entry object (1)默認。添加 時.__str__(),您可以自定義顯示的內容。對于日記條目,標題是更好的字符串表示形式。

      您必須調整的另一個變量是verbose_name_plural.?否則,Django 會拼出你的EntryasEntrys和 not的復數形式Entries。

      注冊入門模型

      要Entry在 Django 管理站點中查看模型,您需要在以下位置注冊它entries/admin.py:

      # entries/admin.py from django.contrib import admin from .models import Entry admin.site.register(Entry)

      當您忘記在管理站點中注冊模型時,Django 不會拋出錯誤。畢竟,并非每個模型都需要在用戶界面中進行管理。但是對于日記中最小的可行產品,您將利用內置的 Django 管理站點。

      遷移入口模型

      添加新類并在管理站點上注冊后,您需要為 Django制作遷移文件并運行它們。使用makemigrations,您可以創建遷移文件,其中包含 Django 構建數據庫的說明。使用migrate,您可以實現它們:

      (.venv) $ python manage.py makemigrations (.venv) $ python manage.py migrate

      遷移完成后,運行開發 Web 服務器,移動到瀏覽器,然后訪問 Django 管理站點http://localhost:8000/admin:

      目前,沒有列出任何條目。通過單擊添加條目為您的日記至少創建一個條目來完成此步驟。不知道寫什么?也許想想你的 Django 日記項目有一個功能齊全的后端是多么棒!

      第 3 步:在前端顯示您的日記條目

      您現在可以在 Django 管理站點中添加新條目。但是當你在瀏覽器中訪問你的日記首頁時,它仍然顯示了抖動的火箭。在這一步中,您將學習如何在前端顯示您的日記條目。

      如果您想查看此步驟結束時的代碼外觀,請單擊以下鏈接:

      獲取源代碼:?單擊此處獲取您將在本教程中使用 Django 和 Python 構建個人日記 Web 應用程序的源代碼。

      與此步驟相關的文件在source_code_step_3/目錄中。

      創建列表和詳細信息視圖

      Django 中有兩種視圖:基于函數的視圖和基于類的視圖。兩者都接受網絡請求并返回網絡響應。一般來說,基于函數的視圖給你更多的控制,但也有更多的工作。基于類的視圖給你更少的控制,但也更少的工作。

      減少工作聽起來不錯。但這并不是您在日記中使用基于類的視圖的唯一原因。您的 Django 日記將使用 Web 應用程序的典型視圖,例如顯示數據庫項目列表或其詳細信息。這就是為什么基于類的視圖是日記視圖的不錯選擇。

      Django 提供了許多開箱即用的通用視圖。在這種情況下,您將創建a和 a 的子類并將它們連接到您的模型中:DetailViewListViewEntryentries/views.py

      1# entries/views.py 2 3from django.views.generic import ( 4 ListView, 5 DetailView, 6) 7 8from .models import Entry 9 10class EntryListView(ListView): 11 model = Entry 12 queryset = Entry.objects.all().order_by("-date_created") 13 14class EntryDetailView(DetailView): 15 model = Entry

      正如所承諾的,此時沒有太多代碼需要您編寫。第Entry.objects.all()12 行的查詢將返回按主鍵排序的所有條目。增強它.order_by("-date_created")會以升序返回您的條目,最新的條目位于列表頂部。

      當你寫這樣的視圖時,Django 會在后臺做一些假設,比如視圖要渲染的模板的名稱和位置。

      創建您的模板

      使用模板,您可以動態生成 HTML。Django 期望您剛剛創建的基于類的視圖的模板位于具有特定名稱的特定位置。為您的模板創建子文件夾:

      (.venv) $ mkdir -p entries/templates/entries

      當然,模板的路徑看起來有點奇怪。但是通過這種方式,您可以確保 Django 會找到完全正確的模板,即使其他應用程序共享相同的模型名稱。在 中entries/templates/entries/,您將存儲Entry模型的所有模板文件。首先創建entry_list.html并添加以下內容:

      1 2 3{% for entry in entry_list %} 4

      14{% endfor %}

      在 Django 模板中,您甚至可以動態引用 CSS 類。當您查看

      第 5 行時,您可以看到class="{{ entry.date_created|date:'l' }}"已添加到其中。這顯示了具有特殊格式的時間戳。這樣,

      元素將工作日作為一個類,您可以稍后在 CSS 中為每個工作日指定一個獨特的顏色。

      在entry_list循環內部,您可以訪問Entry模型的字段。為了不讓列表中的信息過多,您只會在訪問條目的詳細信息頁面時顯示內容。entries/templates/entries/使用entry_detail.html作為文件名創建此詳細信息頁面并添加以下內容:

      {{ entry.date_created|date:'Y-m-d H:i' }}

      {{ entry.title }}

      {{ entry.content }}

      一個detail模板期望的是一個條目對象。這就是為什么您可以直接在此處訪問它而無需循環。

      將路線添加到您的視圖

      要查看正在運行的模板,您需要將視圖連接到URL。Django 使用一個urls.py文件來分派來自瀏覽器中用戶的傳入請求。diary項目文件夾中已經存在這樣的文件。對于條目應用程序,您必須首先創建它entries/urls.py并將路徑添加到EntryListView和EntryDetailView:

      1# entries/urls.py 2 3from django.urls import path 4 5from . import views 6 7urlpatterns = [ 8 path( 9 "", 10 views.EntryListView.as_view(), 11 name="entry-list" 12 ), 13 path( 14 "entry/", 15 views.EntryDetailView.as_view(), 16 name="entry-detail" 17 ), 18]

      第8 行和第 13 行的path()函數必須至少有兩個參數:

      一個路由字符串模式,其中包含一個 URL 模式

      對視圖的引用,它是基于類的視圖的as_view()函數

      此外,您可以將參數作為kwargs傳遞并提供name。使用名稱,您可以在 Django 項目中輕松引用視圖。因此,即使您決定更改 URL 模式,也不必更新模板。

      現在,對于網址entries的應用程序已經到位,你需要將它們連接到urlpatterns列表中diary。當您打開 時diary/urls.py,您將看到urlpatterns您的 Django 日記項目使用的。到目前為止,只有到 的路由"admin/",它是默認添加的,因此您可以訪問 Django 管理站點。要在訪問時顯示日記條目http://localhost:8000,首先需要將根 URL 分派到entries應用程序:

      # diary/urls.py from django.contrib import admin from django.urls import path, include urlpatterns = [ path("admin/", admin.site.urls), path("", include("entries.urls")), ]

      創建新模板后,手動重新啟動 Django 開發 Web 服務器。然后訪問http://localhost:8000并欣賞您的觀點:

      您可以通過點擊相應的鏈接列表或訪問看到一個條目的詳細信息http://localhost:8000/entries/1,其中1是ID一個現有的條目。

      現在一切就緒,可以在前端查看您的條目。不過,您的日記看起來仍然有些單調。讓我們在下一步中改變它!

      第 4 步:讓你的 Django 日記看起來不錯

      在此步驟中,您將為日記添加一些樣式。如果你想看一下這一步完成的代碼,那就點擊下面的鏈接,查看source_code_step_4/目錄:

      獲取源代碼:?單擊此處獲取您將在本教程中使用 Django 和 Python 構建個人日記 Web 應用程序的源代碼。

      雖然你的寫作很有創意,但日記的設計目前有點基礎。你可以開始通過創建一個調味的東西了基礎模板,在entries/templates/entries/base.html與此內容:

      {% load static %} My Diary

      Dear diary …

      {% block content %}{% endblock %}

      使用模板繼承,您不必在模板中重復標記。相反,您擴展您的子模板。然后 Django 在視圖中提供它們時會自動將它們合并在一起。

      添加樣式表

      通過{% load static %}在模板文件的開頭插入,您可以使用模板標簽和 CSS 文件的相對路徑來引用靜態{% static %}文件。建立diary.css在entries/static/css/擴大框下方查看CSS代碼,你會添加到文件中。

      diary.css 的內容顯示隱藏

      如前所述,

      條目列表中的每個元素都將其工作日作為一個類。通過樣式.Saturday和.Sunday不同,您可以輕松地在列表中發現周末。

      擴展子模板

      現在是時候將子模板與base.html父模板連接起來了。更新entries/templates/entries/entries_list.html它看起來像這樣:

      1 2 3{% extends "entries/base.html" %} 4 5{% block content %} 6 {% for entry in object_list %} 7

      17 {% endfor %} 18{% endblock %}

      該{% block %}模板標簽定義了一個子模板可以覆蓋文檔的一部分。要啟用此功能,您必須聲明您的子模板擴展了父模板并定義了一個具有相同名稱的塊元素。使用第{% extends %}3 行的模板標記,您將其定義entries/base.html為父級。{% block %}并{% endblock %}在第 5 行和第 18 行包裝將放置在content父級塊中的標記。

      做同樣的事情entries/templates/entries/entries_detail.html:

      {% extends "entries/base.html" %} {% block content %}

      {{ entry.date_created|date:'Y-m-d H:i' }}

      {{ entry.title }}

      {{ entry.content }}

      {% endblock %}

      這兩個模板都從其父模板繼承了 HTML 結構和樣式。它們共享相同的標題和

      標題,以及由diary.css.?要查看此操作,請啟動您的 Django 開發服務器并轉到http://localhost:8000:

      您現在可以有風格地閱讀您的條目。但是,當您想要創建、更新或刪除條目時,您必須轉到 Django 管理站點。當您想快速記下一些想法時,點擊次數太多了。在下一步中,您將通過將此功能添加到前端來改進您的工作流程。

      第 5 步:在前端管理您的日記條目

      當您構建和使用 Web 應用程序時,您會一直執行四個基本操作。這些操作非常常見,以至于它們經常被CRUD首字母縮寫詞所指代:

      Create

      Read

      Update

      Delete

      在 Django 管理站點中,您已經可以執行所有這些操作。在前端,您目前只能閱讀您的條目。為了類似于 Django 管理站點的功能,您將重復您已經為EntryDetailand所做的工作EntryList,添加一個視圖、一個模板和一個 URL。

      添加視圖

      在entries/views.py已經導入ListView和DetailView至今。更新您的導入語句,使其看起來像這樣:

      # entries/views.py from django.urls import reverse_lazy from django.views.generic import ( ListView, DetailView, CreateView, UpdateView, DeleteView, )

      在底部添加您的三個子類entries/views.py:

      1# entries/views.py 2 3class EntryCreateView(CreateView): 4 model = Entry 5 fields = ["title", "content"] 6 success_url = reverse_lazy("entry-list") 7 8class EntryUpdateView(UpdateView): 9 model = Entry 10 fields = ["title", "content"] 11 12 def get_success_url(self): 13 return reverse_lazy( 14 "entry-detail", 15 kwargs={"pk": self.entry.id} 16 ) 17 18class EntryDeleteView(DeleteView): 19 model = Entry 20 success_url = reverse_lazy("entry-list")

      這一次,將類連接到您的Entry模型是不夠的。對于EntryCreateViewand?EntryUpdateView,您還需要定義表單中應該顯示哪些模型字段,如第 5 行和第 10EntryDeleteView行所示。您的第 18 行僅執行刪除條目項的操作,因此您不需要定義其中的任何字段。

      此外,您需要定義在提交視圖表單后應該將用戶重定向到何處。默認情況下,.get_success_url()只返回 的值success_url。在 中EntryUpdateView,您需要覆蓋此方法。

      通過在第 15 行中提供entry.id作為關鍵字參數,您在編輯后停留在條目詳細信息頁面上。您不使用 URL,而是使用reverse_lazy按名稱引用它們,就像您在模板中所做的那樣。

      創建模板

      像以前一樣,Django 查找具有特定名稱的模板:

      對于EntryDeleteView,它是entry_confirm_delete.html。

      對于EntryCreateView,它是entry_form.html。

      因為EntryUpdateView它會?entry_update_form.html。

      當 Django 找不到 時entry_update_form.html,它會嘗試entry_form.html作為后備。您可以通過創建一個處理兩個視圖的模板entries/templates/entries/并添加一個基本提交表單來利用這一點:

      1 2 3{% extends "entries/base.html" %} 4{% block content %} 5

      6 {% csrf_token %} 7 {{ form.as_p }} 8 9
      10 {% if entry %} 11 12 13 14 {% else %} 15 16 17 18 {% endif %} 19{% endblock %}

      當此模板由 加載時CreateView,表單將為空,取消它會再次將您帶到條目列表。當由 加載時CreateUpdateView,它將預先填充條目的當前標題和內容。取消會將您帶到條目詳細信息頁面。

      有多種方法可以在模板中呈現表單。隨著{{ form.as_p }}在第7行,Django會顯示您在包裹在段落視圖中定義的字段。每當您在 Django 表單中發布內容時,您還必須在其中包含第6 行中的{% csrf_token %}模板標記。這是一種防止跨站點請求偽造的安全措施。

      與其他模板一樣,您{% extends "entries/base.html" %}在第 3 行添加以擴展基本模板。然后定義要包含在第block content4 行和第 18 行之間的標記中的內容。對entry_confirm_delete.htmlin使用相同的模式entries/templates/entries/:

      {% extends "entries/base.html" %} {% block content %}

      {% csrf_token %}

      Are you sure you want to delete "{{ entry.title }}" created on {{ entry.date_created|date:'Y-m-d' }}?

      {% endblock %}

      當您要刪除條目時,將顯示此模板。在表單中提及"{{ entry.title }}"和 會{{ entry.created_date|date:'Y-m-d' }}提醒您按下確認鍵將刪除哪個條目。

      創建 URL

      創建視圖及其模板后,創建它們的路由以在前端訪問它們。向urlpatternsin添加三個額外的路徑entries/urls.py:

      # entries/urls.py urlpatterns = [ path( "", views.EntryListView.as_view(), name="entry-list" ), path( "entry/", views.EntryDetailView.as_view(), name="entry-detail" ), path( "create", views.EntryCreateView.as_view(), name="entry-create" ), path( "entry//update", views.EntryUpdateView.as_view(), name="entry-update", ), path( "entry//delete", views.EntryDeleteView.as_view(), name="entry-delete", ), ]

      對于entry-create,您只需要一個基本create路徑。像entry-detail前面創建,entry-update并且entry-delete需要一個主鍵,以確定哪個入口應更新或刪除。

      現在,您可以直接在前端創建、更新和刪除日記條目。啟動開發web服務器,訪問http://localhost:8000/create測試。如果您想將您的代碼與本教程中的代碼進行比較,請單擊以下鏈接:

      獲取源代碼:?單擊此處獲取您將在本教程中使用 Django 和 Python 構建個人日記 Web 應用程序的源代碼。

      您可以在source_code_step_5/目錄中找到與此步驟相關的文件。

      第 6 步:改善您的用戶體驗

      使用您的日記,您可能會偶然發現一些讓導航有點煩人的怪癖。在這一步中,您將一一解決它們。您會看到界面中的微小變化會對您的日記用戶體驗產生重大影響。

      處理您的成功

      得到一些反饋總是很好的,尤其是當它是積極的時。使用消息框架,您可以快速定義在提交表單后顯示的一次性閃現消息。要使用此功能,進口messages和SuccessMessageMixin到entries/views.py:

      # entries/views.py from django.contrib import messages from django.contrib.messages.views import SuccessMessageMixin

      EntryListView并且EntryDetailView是閱讀視圖并且不處理表單。他們可能會在模板中顯示一條消息,但不會發送一條消息。這意味著您不需要SuccessMessageMixin為它們創建子類。EntryCreateView,EntryUpdateView并且EntryDeleteView,在另一方面,也通知添加到郵件存儲,所以你需要調整它們的功能:

      1# entries/views.py 2 3class EntryCreateView(SuccessMessageMixin, CreateView): 4 model = Entry 5 fields = ["title", "content"] 6 success_url = reverse_lazy("entry-list") 7 success_message = "Your new entry was created!" 8 9class EntryUpdateView(SuccessMessageMixin, UpdateView): 10 model = Entry 11 fields = ["title", "content"] 12 success_message = "Your entry was updated!" 13 14 def get_success_url(self): 15 return reverse_lazy( 16 "entry-detail", 17 kwargs={"pk": self.object.pk} 18 )

      在第 3 行和第 9行繼承SuccessMessageMixinin之后,您在第 7 行和第 12 行為它們定義 a?。特別是當您執行刪除條目等破壞性操作時,提供一切正常的反饋至關重要。要在 中顯示消息,您必須添加自定義方法并手動將自定義添加到消息框架:EntryCreateViewEntryUpdateViewsuccess_messageDeleteView.delete()success_message

      1# entries/views.py 2 3class EntryDeleteView(DeleteView): 4 model = Entry 5 success_url = reverse_lazy("entry-list") 6 success_message = "Your entry was deleted!" 7 8 def delete(self, request, *args, **kwargs): 9 messages.success(self.request, self.success_message) 10 return super().delete(request, *args, **kwargs)

      您在第 8 行需要這個額外的方法,因為DeleteView該類不是FormView.?這就是為什么你可以跳過添加SuccessMessageMixin在EntryDeleteView第3行。

      點擊下方鏈接,查看完整內容entries/views.py。您可以在source_code_step_6/目錄中找到它:

      獲取源代碼:?單擊此處獲取您將在本教程中使用 Django 和 Python 構建個人日記 Web 應用程序的源代碼。

      現在視圖發送消息,您需要增強模板以顯示它們。

      獲取消息

      消息存儲在消息存儲器中。通過循環遍歷它,您可以顯示當前在消息存儲中的所有消息。在 Django 模板中,您可以通過使用消息模板標簽來實現這一點。您構建日記和構建模板的方式,您只需要將其添加到entries/base.html:

      1 2 3

      Dear diary …

      4 5{% if messages %} 6
        7 {% for message in messages %} 8
      • 9 {{ message }} 10
      • 11 {% endfor %} 12
      13{% endif %} 14 15{% block content %}{% endblock %}

      通過將消息列表包裝{% if messages %}在第 4 行和第 12 行,您可以確保只有在存儲中有任何消息時才會有條件地顯示它。

      改善您的導航

      要創建、編輯或刪除條目,您需要記住相應的 URL,然后在地址欄中鍵入它們。多么乏味!幸運的是,您可以通過向視圖添加鏈接來解決此問題。從模板中的entry-create視圖鏈接開始entries/templates/entries/entry-list.html:

      1 2 3{% block content %} 4

      8 9{% for entry in object_list %}

      此標記將類似于其他日記條目列表項。立即向entries/templates/entries/entry_detail.html模板添加新段落以快速編輯或刪除條目:

      ?? Edit ? Delete

      {% endblock %}

      此代碼在分別鏈接到entry-update和的條目詳細信息下方添加了兩個鏈接entry-delete。

      設計您的消息

      最后,通過添加.messages和.message結尾來設置 flash 消息的樣式entries/static/css/diary.css:

      /* entries/static/css/diary.css */ /* Messages */ .messages { padding: 0; list-style: none; } .message { width: 100%; background: lightblue; padding: 1rem; text-align: center; margin: 1rem 0; }

      通過在終端中按Ctrl+C停止開發 Web 服務器并重新啟動它。然后訪問http://localhost:8000以查看您的操作更改。如果消息看起來沒有樣式,您可能需要清除瀏覽器的緩存,以便重新加載樣式表更改:

      您現在擁有一個完全用 Django 構建的完全可用的日記 Web 應用程序。盡管您的日記僅存儲在本地,但最好確保只有您可以訪問它。讓我們在開始記錄之前添加該限制。

      第 7 步:鎖定你的 Django 日記

      多么小的金鎖是用于物理日記,登錄表單是用于您的數字日志。此鎖的關鍵是您已用于登錄 Django 管理站點的名稱和密碼組合。

      重用您的 Django 管理員登錄

      Django 提供的身份驗證系統非常基礎。對于其他有普通用戶的項目,可以考慮定制。但是對于你的 Django 日記,重復使用 Django 管理站點的登錄就足夠了。稍后您會發現這一切正常。首先,讓我們注意注銷。

      添加注銷鏈接

      您通過訪問一個特殊的 URL 來注銷。Django 已經提供了一個帶有名稱的 URL,用于admin:logout將您從 Django 管理站點注銷。當您登錄并從項目中的任何位置訪問此 URL 時,Django 會自動將您注銷。要快速訪問此 URL,請在 底部添加指向它的鏈接entries/templates/entries/base.html:

      {% load static %} My Diary

      Dear diary …

      {% if messages %}
        {% for message in messages %}
      • {{ message }}
      • {% endfor %}
      {% endif %} {% block content %}{% endblock %}
      Logout

      啟動您的開發 Web 服務器,轉到您的主頁http://localhost:8000,然后單擊注銷鏈接。現在,當您訪問 時http://localhost:8000/admin,您會看到登錄表單。這意味著您已注銷。但是,當您http://localhost:8000再次訪問時,您的日記條目仍然可以訪問。是時候改變它了!

      限制訪問您的視圖

      在 Django 中,您可以定義允許誰查看哪些視圖。默認情況下,它們對訪問您網站的所有人開放。要確保視圖需要經過身份驗證的用戶才能訪問,請LoginRequiredMixin在頂部導入entries/views.py:

      # entries/views.py from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib import messages from django.contrib.messages.views import SuccessMessageMixin from django.urls import reverse_lazy from django.views.generic import ( ListView, DetailView, CreateView, UpdateView, DeleteView, ) from .models import Entry

      一旦視圖類使用LoginRequiredMixin,它首先需要成功登錄。此外,您必須定義 alogin_url以便 Django 在您未登錄時知道將您重定向到何處。 您可以創建一個繼承并定義in的基類,而不是單獨對所有類執行此操作:LoginRequiredMixinlogin_urlentries/views.py

      # entries/views.py class LockedView(LoginRequiredMixin): login_url = "admin:login"

      現在,您可以LockedView在所有其他視圖中進行繼承,這些視圖應該只能由經過身份驗證的用戶訪問。編輯entries/views.py使您的類看起來像這樣:

      # entries/views.py class EntryListView(LockedView, ListView): model = Entry queryset = Entry.objects.all().order_by("-created_date") class EntryDetailView(LockedView, DetailView): model = Entry class EntryCreateView(LockedView, SuccessMessageMixin, CreateView): model = Entry fields = ["title", "content"] success_url = reverse_lazy("entry-list") success_message = "Your new entry was created!" class EntryUpdateView(LockedView, SuccessMessageMixin, UpdateView): model = Entry fields = ["title", "content"] success_message = "Your entry was updated!" def get_success_url(self): return reverse_lazy("entry-detail", kwargs={"pk": self.object.pk}) class EntryDeleteView(LockedView, SuccessMessageMixin, DeleteView): model = Entry success_url = reverse_lazy("entry-list") success_message = "Your entry was deleted!" def delete(self, request, *args, **kwargs): messages.success(self.request, self.success_message) return super().delete(request, *args, **kwargs)

      現在,當您訪問 時http://localhost:8000,您將被重定向到 Django 登錄表單。登錄后,您將被重定向到條目列表,并看到僅對您可見的所有內容:

      就是這樣!您已經成功地在 Django 中建立了自己的個人日記。如果您想將您的代碼與項目的最終代碼進行比較,請單擊以下鏈接:

      該項目的完整代碼在source_code_step_final/目錄中。

      下一步

      您構建的日記功能齊全,隨時可用。但它也是一個很好的基礎。也許您已經對如何進一步改進日記有了一些想法。或者,您可以嘗試以下想法之一:

      為您最近的條目添加一個頁面。

      給每個工作日一個顏色。

      在 HTML標記中顯示創建日期。</p><p>為條目創建一天選擇的表情符號。</p><p>對條目列表進行分頁。</p><p>在本教程中,您了解了 Django 提供的一些基本概念和模式。希望它激發了一些深入研究這個 Python Web 框架的興趣。如果您想繼續您的旅程并了解更多信息,您可以查看以下教程:</p><p>使用 Django 的第一步:設置 Django 項目</p><p>Django 入門第 1 部分:構建投資組合應用程序</p><p>在 Django Admin 中管理用戶需要知道什么</p><p>使用 Python 自定義 Django Admin</p><p>使用 Django、Vue 和 GraphQL 構建博客</p><p>您可以將通過完成日記項目獲得的知識應用于其他 Django 教程,并將您的 Web 應用程序技能提升到一個新的水平!</p><p>結論</p><p>在本教程中,您使用 Django 從頭開始 創建了一個個人日記。您學習了如何構建一個可以日常使用的全功能 Web 應用程序。它利用了 Django 的許多優勢,包括管理站點、基于類的視圖、消息框架和模板系統。</p><p>這個 Django 項目也是您未來 Django 項目的完美基礎。您在此日記項目中完成的步驟與其他項目基本相同,例如博客或待辦事項應用程序。</p><p>在本教程中,您學習了如何:</p><p>設置Django 項目</p><p style="text-align:center"><img src="http://m.bai1xia.com/news/zb_users/cache/ly_autoimg/m/MTc0NTc.jpg" alt="用 Django 和 Python 構建個人日記" title="用 Django 和 Python 構建個人日記" /></p><p>使用標準SQLite數據庫</p><p>使用 Django管理站點</p><p>創建模型和基于類的視圖</p><p>嵌套和樣式模板</p><p>通過身份驗證保護您的日記</p><p>Django Python</p><p> <strong>版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。</strong> </p><p> <strong>版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。</strong> </p></div> <div id="sccmaum" class="article_footer clear"> <div id="sc0aoic" class="fr tag">標簽:<a href="http://m.bai1xia.com/news/tags-366.html">django</a> <a href="http://m.bai1xia.com/news/tags-124.html">Python</a> </div> <div id="2emamgo" class="bdsharebuttonbox fl share"> <div id="ok2g2u0" class="share-widget fl"> <div id="em0wks0" class="social-share" data-sites="wechat,weibo, qq, qzone"></div> </div> </div> </div> <!-- 廣告位ad4 --> <div id="s2am0yu" class="post-navigation clear"> <div id="0w0scio" class="post-previous fl"> <span>上一篇:</span><a href="http://m.bai1xia.com/news/post/108060.html">橫向打印excel的方法圖解步驟</a> </div> <div id="c00esk2" class="post-next fr"> <span>下一篇:</span><a href="http://m.bai1xia.com/news/post/137166.html">太陽能電池片<a target="_blank" href="http://m.bai1xia.com/news/tags-14319.html"style="font-weight:bold;">生產制造</a>工藝</a> </div> </div> </div> <div id="mimwgy2" class="related_article"> <div id="cma2uyi" class="box_title clear"> <span><i class="icon fa fa-paper-plane"></i>相關文章</span> </div> <div id="g2giuok" class="related_list clear"> <article class="fl"> <div id="0w0s0iq" class="related_img"><a href="http://m.bai1xia.com/news/post/14997.html"><img src="http://m.bai1xia.com/news/zb_users/cache/ly_autoimg/m/MTQ5OTc.jpg"></a></div> <div id="i0sqas0" class="related_detail"> <h3><a href="http://m.bai1xia.com/news/post/14997.html" title="python<a target="_blank" href="http://m.bai1xia.com/news/tags-2012.html"style="font-weight:bold;">辦公</a><a target="_blank" href="http://m.bai1xia.com/news/tags-1877.html"style="font-weight:bold;">自動化</a>(三) | 借助服務器定時爬數據發郵件">python<a target="_blank" href="http://m.bai1xia.com/news/tags-2012.html"style="font-weight:bold;">辦公</a><a target="_blank" href="http://m.bai1xia.com/news/tags-1877.html"style="font-weight:bold;">自動化</a>(三) | 借助服務器定時爬數據發郵件</a></h3> <div id="ckaomua" class="meta"> <span><i class="fa fa-eye"></i>1125</span> <span><i class="fa fa-clock-o"></i>2025-03-31</span> </div> </div> </article> <article class="fl"> <div id="q20o0e0" class="related_img"><a href="http://m.bai1xia.com/news/post/15246.html"><img src="http://m.bai1xia.com/news/zb_users/upload/2023/08/wenzhangerweima.jpg"></a></div> <div id="2w020so" class="related_detail"> <h3><a href="http://m.bai1xia.com/news/post/15246.html" title="[<a target="_blank" href="http://m.bai1xia.com/news/tags-124.html"style="font-weight:bold;">Python</a>3 <a target="_blank" href="http://m.bai1xia.com/news/tags-125.html"style="font-weight:bold;">網絡</a>爬蟲開發實戰] 1.4.3-Redis 的安裝">[<a target="_blank" href="http://m.bai1xia.com/news/tags-124.html"style="font-weight:bold;">Python</a>3 <a target="_blank" href="http://m.bai1xia.com/news/tags-125.html"style="font-weight:bold;">網絡</a>爬蟲開發實戰] 1.4.3-Redis 的安裝</a></h3> <div id="w2qq02w" class="meta"> <span><i class="fa fa-eye"></i>1125</span> <span><i class="fa fa-clock-o"></i>2025-03-31</span> </div> </div> </article> <article class="fl"> <div id="wcqcsaw" class="related_img"><a href="http://m.bai1xia.com/news/post/11916.html"><img src="http://m.bai1xia.com/news/zb_users/cache/ly_autoimg/m/MTE5MTY.jpg"></a></div> <div id="2omkkc0" class="related_detail"> <h3><a href="http://m.bai1xia.com/news/post/11916.html" title="Elasticsearch <a target="_blank" href="http://m.bai1xia.com/news/tags-124.html"style="font-weight:bold;">Python</a> 庫的安裝">Elasticsearch <a target="_blank" href="http://m.bai1xia.com/news/tags-124.html"style="font-weight:bold;">Python</a> 庫的安裝</a></h3> <div id="cyi2mo0" class="meta"> <span><i class="fa fa-eye"></i>1125</span> <span><i class="fa fa-clock-o"></i>2025-03-31</span> </div> </div> </article> </div> </div> <!--<p class="comment-disable sb br mb"><i class="iconfont icon-cry"></i>抱歉,評論功能暫時關閉!</p>--> </div> </div> <div id="uoq2cuq" class="sidebar"> <div class="qwiec2c" id="推薦文章" class="part clear 推薦文章"> <div id="yqkuwgm" class="top"> <h3 class="title">推薦文章</h3> </div> <div id="2i0okqy" class="side 推薦文章"><ul><ul class="hot_posts"> <li><h4><a href="http://m.bai1xia.com/news/post/132763.html" title="企業生產管理是什么,企業生產管理軟件">企業生產管理是什么,企業生產管理軟件</a></h4></li><li><h4><a href="http://m.bai1xia.com/news/post/136160.html" title="盤點進銷存軟件排行榜前十名">進盤點進銷存軟件排行榜前十名</a></h4></li><li><h4><a href="http://m.bai1xia.com/news/post/132779.html" title="進銷存系統哪個簡單好用?進銷存系統優點">進銷存系統哪個簡單好用?進銷存系統優點</a></h4></li><li><h4><a href="http://m.bai1xia.com/news/post/133648.html" title="工廠生產管理(工廠生產管理流程及制度)">工廠生產管理(工廠生產管理流程及制度)</a></h4></li><li><h4><a href="http://m.bai1xia.com/news/post/132780.html" title="生產管理軟件,機械制造業生產管理,制造業生產過程管理軟件">生產管理軟件,機械制造業生產管理,制造業生產過程管理軟件</a></h4></li><li><h4><a href="http://m.bai1xia.com/news/post/132776.html" title="進銷存軟件和ERP有什么區別?進銷存與erp軟件理解">進銷存軟件和ERP有什么區別?進銷存與erp軟件理解</a></h4></li><li><h4><a href="http://m.bai1xia.com/news/post/132974.html" title="進銷存如何進行庫存管理">進銷存如何進行庫存管理</a></h4></li><li><h4><a href="http://m.bai1xia.com/news/post/132269.html" title="excel銷售訂單管理系統(銷售訂單錄入系統)">如何利用excel制作銷售訂單管理系統?</a></h4></li><li><h4><a href="http://m.bai1xia.com/news/post/136946.html" title="數據庫訂單管理系統有哪些功能?數據庫訂單管理系統怎么設計?">數據庫訂單管理系統有哪些功能?數據庫訂單管理系統怎么設計?</a></h4></li><li><h4><a href="http://m.bai1xia.com/news/post/132312.html" title="數據庫訂單管理系統(訂單系統數據流圖)">什么是數據庫管理系統?</a></h4></li></ul></ul></div> </div> <div class="00y0ow0" id="divPrevious" class="part clear previous"> <div id="q0mmksm" class="top"> <h3 class="title">最近發表</h3> </div> <div id="yecesmu" class="side divPrevious"><ul><li><a title="寵物集市-寵物集市華東、華南、華北排行榜一覽表" href="http://m.bai1xia.com/news/post/157796.html">寵物集市-寵物集市華東、華南、華北排行榜一覽表</a></li> <li><a title="京寵展-2025年時間表" href="http://m.bai1xia.com/news/post/157795.html">京寵展-2025年時間表</a></li> <li><a title="寵物集市在深圳哪里有?時間地址最新消息" href="http://m.bai1xia.com/news/post/157794.html">寵物集市在深圳哪里有?時間地址最新消息</a></li> <li><a title="亞洲寵物展2025年展會介紹" href="http://m.bai1xia.com/news/post/157793.html">亞洲寵物展2025年展會介紹</a></li> <li><a title="京寵展信息指南" href="http://m.bai1xia.com/news/post/157792.html">京寵展信息指南</a></li> <li><a title="寵物展會2025年時間表" href="http://m.bai1xia.com/news/post/157791.html">寵物展會2025年時間表</a></li> <li><a title="亞寵展、全球寵物產業風向標——亞洲寵物展覽會深度解析" href="http://m.bai1xia.com/news/post/157790.html">亞寵展、全球寵物產業風向標——亞洲寵物展覽會深度解析</a></li> <li><a title="2025年亞洲寵物展覽會、京寵展有哪些亮點" href="http://m.bai1xia.com/news/post/157789.html">2025年亞洲寵物展覽會、京寵展有哪些亮點</a></li> <li><a title="<a target="_blank" href="http://m.bai1xia.com/news/tags-10262.html"style="font-weight:bold;">wps</a>演示添加自定義按鈕<a target="_blank" href="http://m.bai1xia.com/news/tags-823.html"style="font-weight:bold;">設置</a>動作改變按順序播放" href="http://m.bai1xia.com/news/post/118206.html"><a target="_blank" href="http://m.bai1xia.com/news/tags-10262.html"style="font-weight:bold;">wps</a>演示添加自定義按鈕<a target="_blank" href="http://m.bai1xia.com/news/tags-823.html"style="font-weight:bold;">設置</a>動作改變按順序播放</a></li> <li><a title="如何將<a target="_blank" href="http://m.bai1xia.com/news/tags-13007.html"style="font-weight:bold;">WPS</a>行中的文本調整到行中" href="http://m.bai1xia.com/news/post/119027.html">如何將<a target="_blank" href="http://m.bai1xia.com/news/tags-13007.html"style="font-weight:bold;">WPS</a>行中的文本調整到行中</a></li> </ul></div> </div> <div class="weqay2u" id="sidebar_ad" class="part clear sidebar_ad"> <div id="owwywoi" class="part sidebar_ad"></div> </div> <div class="iakgeme" id="hot_posts" class="part clear hot_posts"> <div id="0im2eok" class="top"> <h3 class="title">熱評文章</h3> </div> <ul class="hot_posts"><li><h4><a href="http://m.bai1xia.com/news/post/104011.html" title="<a target="_blank" href="http://m.bai1xia.com/news/tags-10179.html"style="font-weight:bold;">零代碼</a>開發是什么?2022<a target="_blank" href="http://m.bai1xia.com/news/tags-1.html"style="font-weight:bold;">低代碼</a>平臺排行榜">零代碼開發是什么?2022低代碼平臺排行榜</a></h4></li><li><h4><a href="http://m.bai1xia.com/news/post/131019.html" title="智能<a target="_blank" href="http://m.bai1xia.com/news/tags-14329.html"style="font-weight:bold;">進銷存庫存管理</a><a target="_blank" href="http://m.bai1xia.com/news/tags-56.html"style="font-weight:bold;">系統</a>(智慧進銷存)">智能進銷存庫存管理系統(智慧進銷存)</a></h4></li><li><h4><a href="http://m.bai1xia.com/news/post/73907.html" title="<a target="_blank" href="http://m.bai1xia.com/news/tags-14095.html"style="font-weight:bold;">在線文檔</a>哪家強?8款在線文檔編輯軟件推薦">在線文檔哪家強?8款在線文檔編輯軟件推薦</a></h4></li><li><h4><a href="http://m.bai1xia.com/news/post/102663.html" title="WPS2016怎么繪制簡單的價格表?">WPS2016怎么繪制簡單的價格表?</a></h4></li><li><h4><a href="http://m.bai1xia.com/news/post/55539.html" title="連鎖餐飲管理<a target="_blank" href="http://m.bai1xia.com/news/tags-56.html"style="font-weight:bold;">系統</a>的功能有哪些?餐飲服務系統的構成及工作程序">連鎖餐飲管理系統的功能有哪些?餐飲服務系統的構成及工</a></h4></li><li><h4><a href="http://m.bai1xia.com/news/post/132806.html" title="簡單<a target="_blank" href="http://m.bai1xia.com/news/tags-14329.html"style="font-weight:bold;">進銷存庫存管理</a>盤點">簡單進銷存庫存管理盤點</a></h4></li></ul> </div> <div class="skmwi0i" id="divLinkage" class="part clear link"> <div id="auqe0ia" class="top"> <h3 class="title">友情鏈接</h3> </div> <div id="uayaawq" class="side divLinkage"><ul><li id="kceg22a" class="link-item"><a href="http://m.bai1xia.com/" target="_blank" title="伙伴云">伙伴云</a></li><li id="gm4aa0i" class="link-item"><a href="http://m.bai1xia.com/news/category-19.html" title="進銷存管理">進銷存管理</a></li><li id="cwwiic0" class="link-item"><a href="http://m.bai1xia.com/news/category-3.html" title="低代碼">低代碼</a></li><li id="a02k0s2" class="link-item"><a href="http://m.bai1xia.com/news/tags-12.html" target="_blank" title="Excel表格">Excel表格</a></li><li id="2kkk2qy" class="link-item"><a title="誠鼎網">誠鼎網</a></li><li id="2eqcaws" class="link-item"><a title="FinClip">FinClip</a></li><li id="00iuemi" class="link-item"><a title="海特貝利常識網">海特貝利常識網</a></li></ul></div> </div> </div> </div> </section> </div> <footer class="p-footer"> <div id="ucwwi2w" class="contant_box"> <div id="k0uwiq0" class="discover_tmt"> <h5 class="" style="font-size: 1px; color: white;">伙伴云</h5> <div id="2oyw2qk" class="text_box"> <a title="toB數字化營銷SEO" style="font-size: 1px; color: white;">加搜toBSEO</a> <a title="小程序工具" style="font-size: 1px; color: white;">前端框架</a> <a title="小紅書營銷攻略" style="font-size: 1px; color: white;">小紅書營銷攻略</a> <a title="衍因科技" style="font-size: 1px; color: white;">衍因科技</a> <a title="FinClip 技術文檔" style="font-size: 1px; color: white;">小程序容器幫助中心</a> <a title="小程序開發行業洞察" style="font-size: 1px; color: white;">小程序開發行業洞察</a> <a title="全面預算管理資訊" style="font-size: 1px; color: white;">全面預算管理資訊</a> <a title="企微SCRM客戶管理干貨" style="font-size: 1px; color: white;">企微SCRM客戶管理干貨</a> <a title="3D視覺相機資訊" style="font-size: 1px; color: white;">3D視覺相機資訊</a> <a title="創冷科技無電制冷" style="font-size: 1px; color: #22292D;">創冷科技無電制冷</a> <a title="協作機器人資訊" style="font-size: 1px; color: #22292D;">協作機器人資訊</a> </div> </div> <div id="2w0uskq" class="collaboration_box"> </div> <div id="oeoyiqk" class="we_img_box clear"> <div id="cg20m0o" class="img_box"> <img src="http://m.bai1xia.com/news/zb_users/theme/zblog5_news/image/ewm.png" alt="" class="hover_tmt"> </div> </div> </div> <p class="info"> <a target="_blank" rel="nofollow">京ICP備12038259號</a> <span> <a href="#"></a></span> </p> </footer> <div class="w2qeek0" id="backtop" class="backtop"> <div id="aukwwcg" class="bt-box top"> <i class="fa fa-angle-up fa-2x"></i> </div> </div> <script charset="UTF-8" src="http://m.bai1xia.com/assets/js/sensorsdata.1.22.2.min.js"></script> <script charset="UTF-8"> var sensors = window['sensorsDataAnalytic201505']; sensors.init({ server_url: 'https://saapi.huoban.com/sa?project=production', heatmap:{scroll_notice_map:'not_collect'}, use_client_time:true, send_type:'beacon' }); sensors.quick('autoTrack'); </script> <script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?6444c045836d6bf27124085a4f62c2a8"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script> <script> (()=>{const e="https://analyze.jiasou.cc/api/v1/page_view/report/",n="9fe06d4884e0461caaa1de5651164d43";let t=null;const o=new Proxy({},{get:(e,n)=>localStorage.getItem(window.btoa(n)),set:(e,n,t)=>!!t&&(localStorage.setItem(window.btoa(n),t),!0)});new Promise((t=>{if(o.fingerprint)t();else{const a=function(){var e={};if(e.userAgent=navigator.userAgent||"",e.plugins=[],navigator.plugins&&navigator.plugins.length>0)for(var n=0;n<navigator.plugins.length;n++){var t={name:navigator.plugins[n].name||"",filename:navigator.plugins[n].filename||"",description:navigator.plugins[n].description||""};e.plugins.push(t)}e.languages=navigator.languages||[navigator.language||""],e.timezone=(new Date).getTimezoneOffset(),e.screenResolution={width:window.screen.width||0,height:window.screen.height||0,pixelDepth:window.screen.pixelDepth||0,colorDepth:window.screen.colorDepth||0};var o=document.createElement("canvas").getContext("2d"),a=[],i=["monospace","sans-serif","serif"];for(n=0;n<i.length;n++){var r=i[n];o.font="12px "+r,o.measureText("abcdefghijklmnopqrstuvwxyz0123456789").width>0&&a.push(r)}return e.fonts=a,e.cookieEnabled=navigator.cookieEnabled||!1,e.localStorage=void 0!==window.localStorage,e.sessionStorage=void 0!==window.sessionStorage,e.doNotTrack="1"===navigator.doNotTrack||"1"===window.doNotTrack||"1"===navigator.msDoNotTrack||"yes"===navigator.doNotTrack,e}();fetch(`${e}u/`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:n,f:window.btoa(JSON.stringify(a))})}).then((e=>{console.debug("browser fingerprint sent"),200===e.status&&e.json().then((e=>{console.debug("browser fingerprint received",e),o.fingerprint=e.fp,t()}))}))}})).then((()=>{e&&o.fingerprint&&fetch(e+`?${new URLSearchParams({token:n}).toString()}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({c:window.btoa(JSON.stringify({u:o.fingerprint,l:window.location.href,r:document.referrer}))})}).then((e=>{200==e.status&&e.json().then((e=>{e.track_id&&(t=e.track_id)}))}))})),window.addEventListener("beforeunload",(async n=>{t&&fetch(e+`?${new URLSearchParams({track_id:t}).toString()}`,{method:"GET",headers:{"Content-Type":"text/plain"},keepalive:!0}),n.returnValue=""}))})(); </script><script language="javascript" src="http://m.bai1xia.com/news/zb_users/plugin/ZF_ad/js/index.js?id=767"></script> <script language="javascript" src="http://m.bai1xia.com/news/zb_users/plugin/ZF_ad/js/ZF_ad__cookie.js"></script> <footer> <div class="friendship-link"> <p>感谢您访问我们的网站,您可能还对以下资源感兴趣:</p> <a href="http://m.bai1xia.com/" title="日本亚洲中午字幕乱码">日本亚洲中午字幕乱码</a> <div class="friend-links"> </div> </div> </footer> <a href="http://" target="_blank">亚洲三区在线观看无套内射</a>| <a href="http://" target="_blank">中文字幕亚洲天堂</a>| <a href="http://" target="_blank">国产精品国产亚洲精品看不卡</a>| <a href="http://" target="_blank">亚洲精品国产电影</a>| <a href="http://" target="_blank">国产成人亚洲综合在线</a>| <a href="http://" target="_blank">亚洲大尺度无码无码专线一区</a>| <a href="http://" target="_blank">久久亚洲精品国产亚洲老地址</a>| <a href="http://" target="_blank">亚洲第一成人在线</a>| <a href="http://" target="_blank">色天使亚洲综合在线观看</a>| <a href="http://" target="_blank">亚洲伦理中文字幕</a>| <a href="http://" target="_blank">最新国产成人亚洲精品影院</a>| <a href="http://" target="_blank">亚洲中文字幕一二三四区苍井空</a>| <a href="http://" target="_blank">亚洲一本之道高清乱码</a>| <a href="http://" target="_blank">亚洲一区中文字幕</a>| <a href="http://" target="_blank">亚洲人成人77777在线播放</a>| <a href="http://" target="_blank">亚洲videos</a>| <a href="http://" target="_blank">国产亚洲福利在线视频</a>| <a href="http://" target="_blank">2019亚洲午夜无码天堂</a>| <a href="http://" target="_blank">久久国产亚洲精品</a>| <a href="http://" target="_blank">亚洲AV色无码乱码在线观看</a>| <a href="http://" target="_blank">蜜芽亚洲av无码一区二区三区</a>| <a href="http://" target="_blank">亚洲国产精品成人综合色在线</a>| <a href="http://" target="_blank">色欲aⅴ亚洲情无码AV</a>| <a href="http://" target="_blank">亚洲第一区精品观看</a>| <a href="http://" target="_blank">久久久久无码专区亚洲av</a>| <a href="http://" target="_blank">国产午夜亚洲精品午夜鲁丝片</a>| <a href="http://" target="_blank">亚洲自偷自偷在线制服</a>| <a href="http://" target="_blank">亚洲精品乱码久久久久久按摩</a>| <a href="http://" target="_blank">亚洲av日韩av不卡在线观看</a>| <a href="http://" target="_blank">精品亚洲国产成AV人片传媒</a>| <a href="http://" target="_blank">亚洲综合色丁香麻豆</a>| <a href="http://" target="_blank">亚洲视频一区二区三区四区</a>| <a href="http://" target="_blank">亚洲无人区码一二三码区别图片</a>| <a href="http://" target="_blank">亚洲成av人在线观看网站</a>| <a href="http://" target="_blank">一本久到久久亚洲综合</a>| <a href="http://" target="_blank">中文字幕精品无码亚洲字 </a>| <a href="http://" target="_blank">国产亚洲中文日本不卡二区</a>| <a href="http://" target="_blank">亚洲第一综合天堂另类专</a>| <a href="http://" target="_blank">亚洲成A∨人片天堂网无码</a>| <a href="http://" target="_blank">在线亚洲午夜理论AV大片</a>| <a href="http://" target="_blank">亚洲av中文无码乱人伦在线咪咕</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body><div id="aau2k" class="pl_css_ganrao" style="display: none;"><dl id="aau2k"></dl><cite id="aau2k"></cite><noscript id="aau2k"></noscript><li id="aau2k"><button id="aau2k"><samp id="aau2k"></samp></button></li><delect id="aau2k"></delect><dfn id="aau2k"><rt id="aau2k"><code id="aau2k"></code></rt></dfn><td id="aau2k"><strike id="aau2k"><menu id="aau2k"></menu></strike></td><option id="aau2k"></option><object id="aau2k"></object><del id="aau2k"></del><code id="aau2k"></code><abbr id="aau2k"><center id="aau2k"><dd id="aau2k"></dd></center></abbr><sup id="aau2k"><center id="aau2k"><dl id="aau2k"></dl></center></sup><source id="aau2k"></source><abbr id="aau2k"></abbr><wbr id="aau2k"><fieldset id="aau2k"><table id="aau2k"></table></fieldset></wbr><td id="aau2k"></td><blockquote id="aau2k"></blockquote><wbr id="aau2k"></wbr><cite id="aau2k"></cite><cite id="aau2k"></cite><rt id="aau2k"></rt><strike id="aau2k"></strike><ul id="aau2k"></ul><dfn id="aau2k"><source id="aau2k"><dl id="aau2k"></dl></source></dfn><tbody id="aau2k"></tbody><acronym id="aau2k"><xmp id="aau2k"><strike id="aau2k"></strike></xmp></acronym><wbr id="aau2k"></wbr><dd id="aau2k"><th id="aau2k"><s id="aau2k"></s></th></dd><kbd id="aau2k"></kbd><small id="aau2k"></small><acronym id="aau2k"></acronym><samp id="aau2k"><th id="aau2k"><object id="aau2k"></object></th></samp><tr id="aau2k"><pre id="aau2k"><xmp id="aau2k"></xmp></pre></tr><tr id="aau2k"></tr><del id="aau2k"></del><kbd id="aau2k"><tbody id="aau2k"><s id="aau2k"></s></tbody></kbd><input id="aau2k"></input><option id="aau2k"><samp id="aau2k"><tbody id="aau2k"></tbody></samp></option><menu id="aau2k"></menu><object id="aau2k"><small id="aau2k"><abbr id="aau2k"></abbr></small></object><dfn id="aau2k"><source id="aau2k"><strong id="aau2k"></strong></source></dfn><noscript id="aau2k"></noscript><xmp id="aau2k"><tfoot id="aau2k"><input id="aau2k"></input></tfoot></xmp><li id="aau2k"></li><strong id="aau2k"></strong><samp id="aau2k"><th id="aau2k"><s id="aau2k"></s></th></samp><td id="aau2k"></td><em id="aau2k"><del id="aau2k"><dfn id="aau2k"></dfn></del></em><del id="aau2k"></del><td id="aau2k"></td><tr id="aau2k"></tr><strike id="aau2k"></strike><samp id="aau2k"></samp><pre id="aau2k"></pre><dl id="aau2k"></dl><code id="aau2k"></code><samp id="aau2k"></samp><li id="aau2k"></li><s id="aau2k"><small id="aau2k"><abbr id="aau2k"></abbr></small></s><dd id="aau2k"><tbody id="aau2k"><object id="aau2k"></object></tbody></dd><dd id="aau2k"></dd><sup id="aau2k"></sup><tbody id="aau2k"></tbody><noframes id="aau2k"></noframes><object id="aau2k"></object><td id="aau2k"></td><menu id="aau2k"></menu><td id="aau2k"></td><dfn id="aau2k"><rt id="aau2k"><code id="aau2k"></code></rt></dfn><option id="aau2k"></option><center id="aau2k"></center><samp id="aau2k"></samp><wbr id="aau2k"><cite id="aau2k"><table id="aau2k"></table></cite></wbr><td id="aau2k"><fieldset id="aau2k"><input id="aau2k"></input></fieldset></td><option id="aau2k"></option><center id="aau2k"></center><strong id="aau2k"></strong><rt id="aau2k"><tbody id="aau2k"><em id="aau2k"></em></tbody></rt><noscript id="aau2k"></noscript><code id="aau2k"><optgroup id="aau2k"><ul id="aau2k"></ul></optgroup></code><object id="aau2k"></object><abbr id="aau2k"></abbr><abbr id="aau2k"></abbr><object id="aau2k"></object><option id="aau2k"></option><acronym id="aau2k"></acronym><input id="aau2k"></input><wbr id="aau2k"></wbr><bdo id="aau2k"></bdo><dfn id="aau2k"><source id="aau2k"><strong id="aau2k"></strong></source></dfn><tr id="aau2k"></tr><rt id="aau2k"></rt><wbr id="aau2k"></wbr><abbr id="aau2k"></abbr><delect id="aau2k"></delect><cite id="aau2k"></cite><strike id="aau2k"><input id="aau2k"><tbody id="aau2k"></tbody></input></strike><samp id="aau2k"></samp><ul id="aau2k"><dfn id="aau2k"><rt id="aau2k"></rt></dfn></ul><dl id="aau2k"></dl><s id="aau2k"></s><strike id="aau2k"></strike><li id="aau2k"></li><wbr id="aau2k"><bdo id="aau2k"><table id="aau2k"></table></bdo></wbr><abbr id="aau2k"></abbr><tr id="aau2k"></tr><center id="aau2k"><dd id="aau2k"><th id="aau2k"></th></dd></center><blockquote id="aau2k"></blockquote><bdo id="aau2k"><abbr id="aau2k"><kbd id="aau2k"></kbd></abbr></bdo><delect id="aau2k"><tbody id="aau2k"><wbr id="aau2k"></wbr></tbody></delect><noscript id="aau2k"></noscript><tbody id="aau2k"></tbody><center id="aau2k"></center><sup id="aau2k"></sup><center id="aau2k"></center><abbr id="aau2k"></abbr><code id="aau2k"><optgroup id="aau2k"><ul id="aau2k"></ul></optgroup></code><center id="aau2k"></center><samp id="aau2k"><tbody id="aau2k"><s id="aau2k"></s></tbody></samp><noscript id="aau2k"></noscript><wbr id="aau2k"></wbr><input id="aau2k"></input><noframes id="aau2k"></noframes><xmp id="aau2k"></xmp><small id="aau2k"><option id="aau2k"><kbd id="aau2k"></kbd></option></small><center id="aau2k"></center><th id="aau2k"><object id="aau2k"><small id="aau2k"></small></object></th><bdo id="aau2k"></bdo><strike id="aau2k"><menu id="aau2k"><noscript id="aau2k"></noscript></menu></strike><bdo id="aau2k"><abbr id="aau2k"><kbd id="aau2k"></kbd></abbr></bdo><source id="aau2k"><strong id="aau2k"><optgroup id="aau2k"></optgroup></strong></source><strong id="aau2k"></strong><blockquote id="aau2k"></blockquote><delect id="aau2k"></delect><sup id="aau2k"></sup><small id="aau2k"></small><bdo id="aau2k"><abbr id="aau2k"><kbd id="aau2k"></kbd></abbr></bdo><abbr id="aau2k"><button id="aau2k"><dd id="aau2k"></dd></button></abbr><samp id="aau2k"></samp><option id="aau2k"></option><button id="aau2k"><center id="aau2k"><strong id="aau2k"></strong></center></button><source id="aau2k"></source><strike id="aau2k"></strike><bdo id="aau2k"><table id="aau2k"><kbd id="aau2k"></kbd></table></bdo><bdo id="aau2k"><abbr id="aau2k"><kbd id="aau2k"></kbd></abbr></bdo><li id="aau2k"></li><option id="aau2k"></option><delect id="aau2k"></delect><object id="aau2k"></object></div> </html> <!--60.90 ms , 17 queries , 3690kb memory , 0 error-->