Django ——自強學堂學習筆記

(一)、啟動服務器

E:\ScienceSoft\Python\Django\Django_project>python manage.py runserver 0.0.0.0:8
000
Performing system checks...

System check identified no issues (0 silenced).
July 22, 2017 - 17:00:33
Django version 1.11.3, using settings 'Django_project.settings'
Starting development server at http://0.0.0.0:8000/
Quit the server with CTRL-BREAK.

(二)、創建數據庫表 或 更改數據庫表或字段

E:\ScienceSoft\Python\Django\Django_project>python manage.py makemigrations
No changes detected

E:\ScienceSoft\Python\Django\Django_project>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  No migrations to apply.

Django 1.7.1及以上 用以下命令

1. 創建更改的文件

python manage.py makemigrations

2. 將生成的py文件應用到數據庫

python manage.py migrate
這種方法可以在SQL等數據庫中創建與models.py代碼對應的表,不需要自己手動執行SQL。

(三) 、使用開發服務器:python manage.py runserver
3.1清空數據庫
命令會詢問是 yes 還是 no, 選擇 yes 會把數據全部清空掉,只留下空表
python manage.py flush
3.2 創建超級管理員
python manage.py createsuperuser

按照提示輸入用戶名和對應的密碼就好了郵箱可以留空,用戶名和密碼必填

修改 用戶密碼可以用:

python manage.py changepassword username
我的用戶名和密碼:sky和Q。。。。123

E:\ScienceSoft\Python\Django\Django_project>python manage.py createsuperuser
Username (leave blank to use 'administrator'): sky
Email address:
Password:
Password (again):
This password is too short. It must contain at least 8 characters.
This password is entirely numeric.
Password:
Password (again):
This password is too common.
This password is entirely numeric.
Password:
Password (again):
This password is too short. It must contain at least 8 characters.
Password:
Password (again):
Superuser created successfully.

(四)、安裝bpython
(五)、 Django與數據庫
Django 會自動進入在settings.py中設置的數據庫:


問題:
1、Django入門:python manage.py dbshell錯誤
學習SQLite是為了在Django上用,因此我更關注與Django相關的。
解決:

1、下載sqlite3【[http://www.sqlite.org/sqlite-shell-win32-x86-3071401.zip](http://www.sqlite.org/sqlite-shell-win32-x86-3071401.zip)】 
2、將sqlite3.exe文件放入(C:\Windwos\System32)中 ,如果是win 7 64位系統則放入C:\Windows\SysWOW64
3、E:\ScienceSoft\Python\Django\Django_project> manage.py dbshell
E:\ScienceSoft\Python\Django\Django_project>python manage.py dbshell
CommandError: You appear not to have the 'sqlite3' program installed or on your
path.

E:\ScienceSoft\Python\Django\Django_project>python manage.py dbshell
SQLite version 3.7.14.1 2012-10-04 19:37:12
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite>

django-admin.py dbshell可以打開sqlite3命令行shell。該命令需要DJANGO_SETTINGS_MODULE中指定相應的數據庫。它與整個django相關的。如果打開項目指定的數據庫shell,需要利用manage.py 代替上面的django-admin.py。
如沒安裝sqlite3,會提示:
Error: You appear not to have the 'sqlite3' program installed or no your path.
由于python只是集成了sqlite3的庫文件,并不提供sqlite3程序。要用它的shell要安裝下。
sqlite3一些常見命令
SQL;直接執行sql語句。
.help 幫助
.database 查看數據庫
.exit .quit 退出
.table 查看表
.dump table 查看SQL語句

(六) 、 Django 視圖與網址
urls.py :網址
views.py:正則表達式對應于其中的一個函數(或者generic類)
1.創建項目Django_project
django-admin startproject Django_project
Django_project
├── manage.py
└── Django_project
├── init.py
├── settings.py
├── urls.py
└── wsgi.py
我們會發現執行命令后,新建了一個 Django_project 目錄,其中還有一個Django_project 目錄,這個子目錄 Django_project中是一些項目的設置 settings.py 文件,總的urls配置文件 urls.py 以及部署服務器時用到的 wsgi.py 文件, init.py 是python包的目錄結構必須的,與調用有關。
我們到外層那個 Django_project目錄下(不是Django_project中的Django_project目錄)

(七)、 新建一個應用(app), 名稱叫 learn

image.png

1.添加app到settings.py中
settings.py:


INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # 添加部分如下:添加新的app

    'learn',
]

新建的 app 如果不加到 INSTALL_APPS 中的話, django 就不能自動找到app中的模板文件(app-name/templates/下的文件)和靜態文件(app-name/static/中的文件)

2.定義視圖函數(訪問頁面時的內容)
learn目錄下的view.py:

from django.shortcuts import render

# Create your views here.
# 定義視圖函數(訪問頁面時的內容)
from django.http import HttpResponse


def index(request):
    return HttpResponse(u"我的新建 APP !")

第一行是聲明編碼為utf-8, 因為我們在代碼中用到了中文,如果不聲明就報錯.

第二行引入HttpResponse,它是用來向網頁返回內容的,
就像Python中的 print 一樣,只不過 HttpResponse 是把內容顯示到網頁上。

3.怎么讓網址和函數關聯起來呢?定義視圖函數相關的URL(網址) (即規定 訪問什么網址對應什么內容)
Django_project\Django_project下的urls.py:

from django.conf.urls import url
from django.contrib import admin

# 添加
from learn import views as learn_views # 取別名

urlpatterns = [
    # 添加
    url(r'^$', learn_views.index), # new

    url(r'^admin/', admin.site.urls),

]

一共修改了settings.py, views.py,urls.py,apps.py
啟動服務器 python manage.py runserver,http://127.0.0.1:8000/在瀏覽器中打開后顯示:views.py中的內容

image.png

Django中的 urls.py 用的是正則進行匹配的,如果不熟悉,您可以學習正則表達式以及Python正則表達式
(七)、開始再新建項目Developer
在網頁上做加減法
修改Developer/calc下的views.py:

from django.shortcuts import render

# Create your views here.
from django.shortcuts import render

# Create your views here.
from django.http import HttpResponse
# 在網頁上做加減法
def add(request):

    a = request.GET['a']

    b= request.GET['b']

    c = int(a)+int(b)

    return HttpResponse(str(c))

# 注:request.GET 類似于一個字典,更好的辦法
# 是用 request.GET.get('a', 0) 當沒有傳遞 a 的時候默認 a 為 0

在修改Developer下的urls.py:
添加一個網址來對應我們剛才新建的視圖函數

from django.conf.urls import url
from django.contrib import admin

from calc  import views as calc_views
urlpatterns = [
 # 添加一個網址來對應learn下的views.py中新建的視圖函數
    url(r'^add/$', calc_views.add, name='add')
#  name相當于“給網址取了個名字”,只要這個名字不變,網址變了也能通過名字獲取到
    #url(r'^admin/', admin.site.urls),
]

啟動服務器 python manage.py runserver 8001,http://127.0.0.1:8001/add/在瀏覽器中打開后顯示:views.py中的內容

image.png

這是因為我們并沒有傳值進去,我們在后面加上?a=4&b=5,即訪問 http://127.0.0.1:8001/add/?a=4&b=5
就可以看到網頁上顯示一個 9,試著改變一下a和b對應的值試試看?
注意:如果打開8000端口會訪問失敗,原因是前面創建的項目已將占用了端口8000
所以此處改為8001

image.png
image.png

2.采用 /add/3/4/ 這樣的網址的方式
修改 calc/views.py文件,再新定義一個add2 函數
views.py:

ws here.
from django.http import HttpResponse
# 在網頁上做加減法
def add(request):

    a = request.GET['a']

    b= request.GET['b']

    c = int(a)+int(b)

    return HttpResponse(str(c))

def add2(request, a, b):

    c = int(a) + int(b)

    return HttpResponse(str(c))

接著修改Developer/urls.py 文件,再添加一個新的 url


可以看到網址中多了 (\d+), 正則表達式中 \d 代表一個數字,+ 代表一個或多個前面的字符,寫在一起 \d+ 就是一個或多個數字,用括號括起來的意思是保存為一個子組
每一個子組將作為一個參數,被 views.py 中的對應視圖函數接收。
http://127.0.0.1:8001/add/24/5/在瀏覽器中打開:

image.png

4.創建首頁視圖和url
Developer下的urls.py:

"""
from django.conf.urls import url
from django.contrib import admin

from calc  import views as calc_views
urlpatterns = [

 # 添加一個網址來對應learn下的views.py中新建的視圖函數
    url(r'^add/$', calc_views.add, name='add'),
    #url(r'^admin/', admin.site.urls),
    # 再添加一個新的url
    url(r'^add/(\d+)/(\d+)/$', calc_views.add2, name='add2'),
    # index是views.py中的函數名
    url(r'^$', calc_views.index, name='home')
    ]

先建一個首頁的視圖和url修改 calc/views.py:

from django.http import HttpResponse
from django.shortcuts import render

# Create your views here.
# render是渲染模板

# Create your views here.

def  index(request):
    return render(request, 'home.html')
# 在網頁上做加減法
def add(request):

    a = request.GET['a']

    b= request.GET['b']

    c = int(a)+int(b)

    return HttpResponse(str(c))

def add2(request, a, b):

    c = int(a) + int(b)

    return HttpResponse(str(c))

將 'calc' 這個 app 加入到 Developer/settings.py 中
settings.py:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'calc',
]

在 calc 這個 app 中新建一個 templates 文件夾,在templates中新建一個 home.html (關于模板更詳細的可以稍后看下一節)

文件 calc/templates/home.html 中寫入以下內容(保存時用 utf8 編碼)

home.html:

<!DOCTYPE html>
<html>
<head>
    <title>Django學習</title>
</head>
<body>
<a href="/add/24/5/">計算 24+5</a>
</body>
</html>

修改Developer/urls.py:

"""
from django.conf.urls import url
from django.contrib import admin

from calc  import views as calc_views
urlpatterns = [

 # 添加一個網址來對應learn下的views.py中新建的視圖函數
    url(r'^add/$', calc_views.add, name='add'),
    #url(r'^admin/', admin.site.urls),
    # 再添加一個新的url
    url(r'^add/(\d+)/(\d+)/$', calc_views.add2, name='add2'),
    # index是views.py中的函數名
    url(r'^$', calc_views.index, name='home')
    ]

運行開發服務器,我們訪問 http://127.0.0.1:8001/可以看到:

image.png

當我點擊計算24+5后,會顯示計算結果
我們計算加法的時候用的是 /add/4/5/ ,后來需求發生變化,比如改成 /4_add_5/,但在網頁中,代碼中很多地方都寫死的 /add/4/5/,比如模板中可能是這么寫的
<a href="/add/4/5/">計算 4+5</a>
如果這樣寫“死網址”,會使得在改了網址(正則)后,模板(template),視圖(views.py,用以用于跳轉),模型(models.py,可以用用于獲取對象對應的地址)用了此網址的,都得進行相應的更改,修改的代價很大,一不小心,有的地方沒改過來,就不能用了。我們先說一下如何用 Python 代碼獲取對應的網址(可以用在 views.py,models.py等各種需要轉換得到網址的地方):

我們在終端上輸入(推薦安裝 bpython, 這樣Django會用 bpython的 shell)
http://www.jb51.net/article/79498.htm
我使用這種方法安裝bpython——克隆bpython的Git倉庫:git clone https://github.com/bpython/bpython/
bpython是一個Python Shell。

如果你系統里安裝了Python3,它才能以Python3運行。

建議使用virtualenv,自己編譯一套py3的環境,然后在py3的環境上運行bpython。

使用py3的virtualenv

首先編譯Python3.X: py3

生成py3 virtualenv

virtualenv py3env -p py3/bin/python3

使用新的virtualenv環境

source py3env/bin/activate

使用bpython

bpython
Windows環境64位機器

使用pip安裝curses

pip install E:\downloads\curses-2.2-cp27-none-win_amd64.whl
curses-2.2-cp27-none-win_amd64.whl下載地址
http://www.lfd.uci.edu/~gohlke/pythonlibs/#curses
x下載后,打開cmd,進入文件的存放目錄,運行結果如下
E:\ScienceSoft\Python>pip install curses-2.2-cp35-none-win_amd64.whl
Processing e:\sciencesoft\python\curses-2.2-cp35-none-win_amd64.whl
Installing collected packages: curses
Successfully installed curses-2.2
注意:cp35是python3.5
cp27是python2.7
http://blog.csdn.net/c465869935/article/details/51586077
ImportError: No module named fcntl錯誤解決, 將資源fcntl.py下載下來,放到python的安裝目錄下的\Lib目錄內即可。我的是放到D:\Python27\Lib目錄下了。
我的是C:\Users\Administrator\AppData\Local\Programs\Python\Python35\Lib
結果又遇到ImportError: No module named 'termios'
百度后有的說需要用cygwin. cygwin是一個在windows平臺上運行的unix模擬環境
https://jingyan.baidu.com/article/48a42057accae3a92525045a.html
https://jingyan.baidu.com/article/9c69d48f9ecb0613c8024e5d.html
https://jingyan.baidu.com/article/6b97984d83dfe51ca2b0bf0e.html
如何測試cygwin是否成功?https://www.zhihu.com/question/24213717
查閱 Cygwin 包列表https://www.ibm.com/developerworks/cn/aix/library/au-spunix_cygwin/#resources
小結:
ctrl+f:網站彈出搜索框快捷鍵
http://www.lfd.uci.edu/~gohlke/pythonlibs/#curses,再安裝bpython
bpython一直安裝不了,所以只好安裝了ipython
如下:pip install ipython

image.png
image.png
image.png

退出用quit;
我們在終端上輸入(推薦安裝 bpython, 這樣Django會用 bpython的 shell,但是如下圖啟動的是ipython的shell,即因為我安裝的是ipython)
python manage.py shell


image.png
image.png

我的項目是在Developer目錄下,該目錄下有calc文件


E:\ScienceSoft\Python\Django\Django_project\Developer>python manage.py shell
Python 3.5.0 (v3.5.0:374f501f4567, Sep 13 2015, 02:27:37) [MSC v.1900 64 bit (AM
D64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 6.1.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: from django.core.urlresolvers import reverse
manage.py:1: RemovedInDjango20Warning: Importing from django.core.urlresolvers i
s deprecated in favor of django.urls.
  #!/usr/bin/env python

In [2]: from django.urls import reverse

In [3]: reverse('add2', args(4,5))
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-3-e32011ea2241> in <module>()
----> 1 reverse('add2', args(4,5))

NameError: name 'args' is not defined

In [4]: reverse('add2', args=(444,555))
Out[4]: '/add/444/555/'

In [5]: reverse('add2', args=(4,5))
Out[5]: '/add/4/5/'

In [6]:

現在只要對應的 url 的name不改,就不用改代碼中的網址
因為我們使用reverse來接收url中的name作為第一個參數,通過reverse()來獲取
對應的網址(這個網址可以用來跳轉,也可以用來計算相關頁面的地址)
在網頁模板中也是一樣,可以很方便的使用。
template/home.html:

<!DOCTYPE html>
<html>
<head>
    <title>Django學習</title>
</head>
<body>
<a href="/add/24/5/">計算 24+5</a>
<!--
不帶參數的:
{% url 'name' %}
帶參數的:參數可以是變量名
{% url 'name' 參數 %}
-->
<a href="{% url 'add2' 34 5 %}">link</a>
<!--
這樣就可以通過{% url 'add2' 4 5 %}獲取到對應的網址/add/4/5
-->
</body>
</html>

當 urls.py 進行更改,前提是不改 name(這個參數設定好后不要輕易改),獲取的網址也會動態地跟著變注意看重點 add 變成了 new_add,但是后面的 name='add2' 沒改,這時 {% url 'add2' 4 5 %} 就會渲染對應的網址成 /new_add/4/5/

urls.py :

"""Developer URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin

from calc  import views as calc_views
urlpatterns = [

 # 添加一個網址來對應learn下的views.py中新建的視圖函數
    url(r'^add/$', calc_views.add, name='add'),
    #url(r'^admin/', admin.site.urls),
    # 再添加一個新的url
    # 當urls.py更改,前提是不改name
    # url(r'^add/(\d+)/(\d+)/$', calc_views.add2, name='add2'),
    
    url(r'^new_add/(\d+)/(\d+)/$', calc_views.add2, name='add2'),
  
    # index是views.py中的函數名
    url(r'^$', calc_views.index, name='home')
    ]

用在 views.py 或 models.py 等地方的 reverse函數,同樣會根據 name 對應的url獲取到新的網址
想要改網址的時候,修改 urls.py 中的正則表達式部分(url 參數第一部分),name 不變的前提下,其它地方都不需要修改

另外,比如用戶收藏夾中收藏的URL是舊的,如何讓以前的 /add/3/4/自動跳轉到現在新的網址呢?

要知道Django不會幫你做這個,這個需要自己來寫一個跳轉方法:

具體思路是,在 views.py 寫一個跳轉的函數:view.py:
view.py:

from django.http import HttpResponse
from django.shortcuts import render

# Create your views here.
# render是渲染模板
# 跳轉
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse


# Create your views here.

def  index(request):
    return render(request, 'home.html')
# 在網頁上做加減法
def add(request):

    a = request.GET['a']

    b= request.GET['b']

    c = int(a)+int(b)

    return HttpResponse(str(c))

def add2(request, a, b):

    c = int(a) + int(b)

    return HttpResponse(str(c))

# 寫一個跳轉的函數,讓以前的 /add/3/4/自動跳轉到現在新的網址

def old_add2_redirect(request, a, b):

    return HttpResponseRedirect(

        reverse('add2', args=(a, b))

        )

urls.py:

"""Developer URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin

from calc  import views as calc_views
urlpatterns = [

 # 添加一個網址來對應learn下的views.py中新建的視圖函數
    url(r'^add/$', calc_views.add, name='add'),
    #url(r'^admin/', admin.site.urls),
    # 再添加一個新的url
    # 當urls.py更改,前提是不改name
    # url(r'^add/(\d+)/(\d+)/$', calc_views.add2, name='add2'),
    # 跳轉
    url(r'^add/(\d+)/(/d+)/$', calc_views.old_add2_redirect),
#     TypeError: old_add2_redirect() missing 3 required positional arguments: 'reques
# ', 'a', and 'b'
#  url(r'^add/(\d+)/(/d+)/$', calc_views.old_add2_redirect())這樣寫會報上述錯
    url(r'^new_add/(\d+)/(\d+)/$', calc_views.add2, name='add2'),
  
    # index是views.py中的函數名
    url(r'^$', calc_views.index, name='home')
    ]

這樣,假如用戶收藏夾中有 /add/4/5/ ,訪問時就會自動跳轉到新的 /new_add/4/5/ 了
開始可能覺得直接寫網址簡單,但是用多了你一定會發現,用“死網址”的方法很糟糕。
報錯的時候根據網頁的提示更改,如下:

image.png
image.png

在前面的幾節中我們都是用簡單的 django.http.HttpResponse 來把內容顯示到網頁上
本節將講解如何使用渲染模板的方法來顯示內容

三、第三個項目:新建項目progect3
1.創建project3 項目和應用(名稱為learn3)如下:

E:\ScienceSoft\Python\Django>django-admin startproject project3

E:\ScienceSoft\Python\Django>cd project3

E:\ScienceSoft\Python\Django\project3>python manage.py startapp learn3

  1. 把 learn 加入到 settings.INSTALLED_APPS中
    settings.py:
# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'learn3',
]

3.打開 learn3/views.py 寫一個首頁的視圖
views.py:

from django.shortcuts import render

# Create your views here.
def home(request):

    return render(request, 'home.html')
  1. 在 learn目錄下新建一個 templates 文件夾,里面新建一個 home.html
    目錄的結構是這樣的:
    progect3
    ├── learn3
    │ ├── init.py
    │ ├── admin.py
    │ ├── migrations
    │ │ └── init.py
    │ ├── models.py
    │ ├── templates
    │ │ └── home.html
    │ ├── tests.py
    │ └── views.py
    ├── manage.py
    └── progect3
    ├── init.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py
    4 directories, 12 files
    本節將講解如何使用渲染模板的方法來顯示內容。
  2. 在 home.html 中寫一些內容
    home.html:
<!DOCTYPE html>
<html>
  <head>
    <title>如何使用渲染模板的方法來顯示內容</title>

  </head>
  <body>
Django學習教程之一:自強學堂
  </body>
</html>
  1. 將視圖函數對應到網址,更改 project3/urls.py
    urls.py:
from django.conf.urls import url
from django.contrib import admin
# 1
from learn3 import views as learn3_views
urlpatterns = [
    url(r'^$', learn3_views.home, name='home'),
    url(r'^admin/', admin.site.urls),
]


python manage.py runserver

image.png

模板補充知識:

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

nav.html, bottom.html, tongji.html

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

注意:模板一般放在app下的templates中,Django會自動去這個文件夾中找。

templates/base.html:


其它的頁面繼承自 base.html 就好了,繼承后的模板也可以在 block 塊中 include 其它的模板文件
如我們的首頁頁面home.html,繼承base.html,寫法如下:
base.html:

<!DOCTYPE html>
<html>
<head>
    
    <title>{% block title%}默認標題{% endblock %} - 自強學堂</title>
</head>
<body>

{%  include 'nav.html' %}

{% block content %}
<div>這里是默認內容,所有繼承自這個模板的,如果不覆蓋就顯示這里的默認內容</div>
{% endclock %}

{% include 'bottom.html' %}

{% include 'tongji.html' %}
</body>
</html>

home.html:

<!DOCTYPE html>
<html>
  <head>
    <title>如何使用渲染模板的方法來顯示內容</title>

  </head>
  <body>
Django學習教程之一:自強學堂
{% extends 'base.html' %}

{% block title %}自強學堂——Django學習筆記首頁頁面{% endblock %}

{% block content %}
{% include 'ad.html' %}

這里是首頁,歡迎光臨

{% endblock %}
  </body>
}

</html>

但 假如我們每個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/ 目錄下面,

templates 文件夾中再建一個 app
例如:項目 project3 有兩個 app,分別為 tutorial 和 learn3

project3
├── tutorial
│ ├── init.py
│ ├── admin.py
│ ├── models.py
│ ├── templates
│ │ └── tutorial
│ │ ├── index.html
│ │ └── search.html
│ ├── tests.py
│ └── views.py
├── learn3
│ ├── init.py
│ ├── admin.py
│ ├── models.py
│ ├── templates
│ │ └── tryit
│ │ ├── index.html
│ │ └── poll.html
│ ├── tests.py
│ └── views.py
├── manage.py
└── zqxt
├── init.py
├── settings.py
├── urls.py
└── wsgi.py

這樣,使用的時候,模板就是 "tutorial/index.html" 和 "learn3/index.html" 這樣有app作為名稱的一部分,就不會混淆。

五、Django 模板進階:
本節主要講 Django模板中的循環,條件判斷,常用的標簽,過濾器的使用
1.列表,字典,類的實例的使用

2.循環:迭代顯示列表,字典等中的內容

3.條件判斷:判斷是否顯示該內容,比如判斷是手機訪問,還是電腦訪問,給出不一樣的代碼。

4.標簽:for,if 這樣的功能都是標簽。

5.過濾器:管道符號后面的功能,比如{{ var|length }},求變量長度的 length 就是一個過濾器。
如果需要將一個或多個變量共享給多個網頁或者所有網頁使用,比如在網頁上顯示來訪者的IP,這個可以使用 Django 上下文渲染器 來做。
實例一,顯示一個基本的字符串在網頁上
(1)home.html:

<!DOCTYPE html>
<html>
  <head>
    <title>如何使用渲染模板的方法來顯示內容</title>

  </head>
  <body>
Django學習教程之一:自強學堂


{{ string }}
 </body>
</html>

(2)views.py:

from django.shortcuts import render

# Create your views here.
def home(request):
    # 實例一,顯示一個基本的字符串在網頁上
    string = u"我在自強學堂學習Django,用它來建網站"
# 在視圖中我們傳遞了一個字符串(名稱是 string )到模板 home.html
    return render(request, 'home.html', {'string': string})

(3)http://127.0.0.1:8000/

image.png

實例二,講解了基本的 for 循環 和 List內容的顯示
views.py:

from django.shortcuts import render

# Create your views here.
def home(request):
    Learn3 = ["HTML", "CSS", "jQuery", "Python", "Django"]
    return render(request, 'home.html', {'Learn3': Learn3})
        # 實例一,顯示一個基本的字符串在網頁上
    #string = u"我在自強學堂學習Django,用它來建網站"
# 在視圖中我們傳遞了一個字符串(名稱是 string )到模板 home.html
# 實例二

在視圖中我們傳遞了一個List到模板 home.html,在模板中這樣使用它:
home.html:

<!DOCTYPE html>
<html>
  <head>
    <title>如何使用渲染模板的方法來顯示內容</title>

  </head>
  <body>
Django學習教程之一:自強學堂
教程列表
{%  for i in Learn3 %}
{{ i }}
for 循環要有一個結束標記
{% endfor %}
 </body>

</html>
image.png

簡單總結一下:一般的變量之類的用 {{ }}(變量),功能類的,比如循環,條件判斷是用 {% %}(標簽)
home.html:

<!DOCTYPE html>
<html>
  <head>
    <title>如何使用渲染模板的方法來顯示內容</title>

  </head>
  <body>
Django學習教程之一:自強學堂
教程列表
{%  for i in Learn3 %}
{{ i }}

{% endfor %}
 </body>

</html>
image.png

實例三,顯示字典中內容:
views.py:

from django.shortcuts import render

# Create your views here.
def home(request):
    # 實例二
    # Learn3 = ["HTML", "CSS", "jQuery", "Python", "Django"]

    # 實例三:顯示字典中的內容

    info_dict = {'site': u'自強學堂', 'content': u'各種IT技術教程'}
    return render(request, 'home.html', {'info_dict': info_dict})
        # 實例一,顯示一個基本的字符串在網頁上
    #string = u"我在自強學堂學習Django,用它來建網站"
# 在視圖中我們傳遞了一個字符串(名稱是 string )到模板 home.html

home.html

<!DOCTYPE html>
<html>
  <head>
    <title>如何使用渲染模板的方法來顯示內容</title>

  </head>
  <body>
Django學習教程之一:自強學堂
站點:
{{ info_dict.site }}

內容:
{{ info_dict.content }}
</body>
}

</html>

在模板中取字典的鍵是用點info_dict.site,而不是Python中的 info_dict['site'],效果如下——???

image.png

還可以這樣遍歷字典:
views.py:

<!DOCTYPE html>
<html>
  <head>
    <title>如何使用渲染模板的方法來顯示內容</title>

  </head>
  <body>
Django學習教程之一:自強學堂
{% for key, value in info_dict.items %}
    {{ key }}: {{ value }}
{% endfor %}

</html>

image.png

其實就是遍歷這樣一個 List: [('site', u'自強學堂'), ('content', u'各種IT技術教程')]

實例四,在模板進行 條件判斷和 for 循環的詳細操作:
views.py:

from django.shortcuts import render

# Create your views here.
def home(request):
    # 實例二
    # Learn3 = ["HTML", "CSS", "jQuery", "Python", "Django"]

    # 實例三:顯示字典中的內容

    # info_dict = {'site': u'自強學堂', 'content': u'各種IT技術教程'}
    # 實例四
    List = map(str, range(100)) # 一個長度為100的 List
    return render(request, 'home.html', {'List': List})
        # 實例一,顯示一個基本的字符串在網頁上
    #string = u"我在自強學堂學習Django,用它來建網站"
# 在視圖中我們傳遞了一個字符串(名稱是 string )到模板 home.html

假如我們想用逗號將這些元素連接起來:
home.py:

<!DOCTYPE html>
<html>
  <head>
    <title>如何使用渲染模板的方法來顯示內容</title>

  </head>
  <body>
Django學習教程之一:自強學堂
{% for item in List %}
    {{ item }},
{% endfor %}

</html>
image.png

我們會發現最后一個元素后面也有一個逗號,這樣肯定不爽,如果判斷是不是遍歷到了最后一個元素了呢?

用變量 forloop.last 這個變量,如果是最后一項其為真,否則為假,更改如下

{% for item in List %}
    {{ item }}{% if not forloop.last %}, {% endif %}
{% endfor %}
image.png
image.png

在for循環中還有很多有用的東西,如下:
當列表中可能為空值時用 for empty

views.py:

from django.shortcuts import render

# Create your views here.
def home(request):
    

    athlete_list = ['sky:' '1', 'kk:''2', 'ko:' '3']
    return render(request, 'home.html', {'athlete_list ': athlete_list })

home.html:

<!DOCTYPE html>
<html>
  <head>
    <title>如何使用渲染模板的方法來顯示內容</title>

  </head>
  <body>

<ul>
{% for athlete in athlete_list %}
    <li>{{ athlete.name }}</li>
 {% empty %}
    <li>抱歉,列表為空</li>
 {% endfor %}
</ul>
image.png

上述問題提示列表為空,但是我的列表中是有值得,這是為什么???

實例五,模板上得到視圖對應的網址:

django.VERSION
(1, 11, 3, 'final', 0)
django.VERSION
(1, 11, 3, 'final', 0)
django.get_version()
'1.11.3'
Django By Example》第一章 中文翻譯 - 知乎專欄

image.png

實例七,模板中 獲取當前網址,當前用戶等:
1.修改settings.py:
Django 1.8 及以后 修改 settings.py (Django 1.11 中新建的項目已經默認加上了)

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                # 1.11的版本 Django
                'django.template.context_processors.request',
            ],
        },
    },

然后在 模板中我們就可以用 request 了。一般情況下,推薦用 render 而不是用 render_to_response
7.1 獲取當前用戶:
home.html:

<!DOCTYPE html>
<html>
  <head>
    <title>如何使用渲染模板的方法來顯示內容</title>

  </head>
<body>

{{ request.user }}
</body>
</html>
image.png

home.html:

<!DOCTYPE html>
<html>
  <head>
    <title>如何使用渲染模板的方法來顯示內容</title>

  </head>
<body>

{{ request.user }}

{% if request.user.is_authenticated %}
    {{ request.user.username }}, 您好!
{% else %}
     請登錄,這里放登陸鏈接
{% endif %}
</body>
</html>
image.png

獲取當前網址:
home.html:

<!DOCTYPE html>
<html>
  <head>
    <title>如何使用渲染模板的方法來顯示內容</title>

  </head>
<body>

<a href="{{ request.path }}?{{ request.GET.urlencode }}&delete=1">當前網址加參數 delete</a>
</body>
</html>

比如我們可以判斷 delete 參數是不是 1 來刪除當前的頁面內容。

六、Django 模型(數據庫)

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

E:\ScienceSoft\Python\Django>django-admin.py startproject learn_models

E:\ScienceSoft\Python\Django>cd learn_models

E:\ScienceSoft\Python\Django\learn_models>django-admin.py startapp people

E:\ScienceSoft\Python\Django\learn_models>


  1. 添加應用

將我們新建的應用(people)添加到 settings.py 中的 INSTALLED_APPS中,也就是告訴Django有這么一個應用。
settings.py:

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'people',
]

3.修改models.py
之前的項目實例中,沒有修改models.py文件,即模型
我們打開 people/models.py 文件,修改其中的代碼如下:
修改models.py:

from django.db import models

# Create your models here.
class Person(models.Model):

    name = models.CharField(max_length=30)

    age = models.IntegerFiled()

我們新建了一個Person類,繼承自models.Model, 一個人有姓名和年齡。

這里用到了兩種Field,更多Field類型可以參考教程最后的鏈接。

  1. 創建數據表
    我們來同步一下數據庫(我們使用默認的數據庫 SQLite3,無需配置)
E:\ScienceSoft\Python\Django\learn_models>python manage.py makemigrations
Migrations for 'people':
  people\migrations\0001_initial.py
    - Create model Person
E:\ScienceSoft\Python\Django\learn_models>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, people, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying people.0001_initial... OK
  Applying sessions.0001_initial... OK

我們會看到,Django生成了一系列的表,也生成了我們新建的people_person這個表,那么如何使用這個表呢?

如何使用生成的表

  1. 使用 Django 提供的 QuerySet API
    Django提供了豐富的API, 下面演示如何使用它。

E:\ScienceSoft\Python\Django\learn_models>python manage.py shell
Python 3.5.0 (v3.5.0:374f501f4567, Sep 13 2015, 02:27:37) [MSC v.1900 64 bit (AM
D64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 6.1.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: from people.models import Person

In [2]: Person.objects.create(name="LiJun")
---------------------------------------------------------------------------
IntegrityError                            Traceback (most recent call last)
~\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\backends\ut
ils.py in execute(self, sql, params)
     64             else:
---> 65                 return self.cursor.execute(sql, params)
     66

~\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\backends\sq
lite3\base.py in execute(self, query, params)
    327         query = self.convert_query(query)
--> 328         return Database.Cursor.execute(self, query, params)
    329

IntegrityError: NOT NULL constraint failed: people_person.age

The above exception was the direct cause of the following exception:

IntegrityError                            Traceback (most recent call last)
<ipython-input-2-68274b20ae3e> in <module>()
----> 1 Person.objects.create(name="LiJun")

~\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\models\mana
ger.py in manager_method(self, *args, **kwargs)
     83         def create_method(name, method):
     84             def manager_method(self, *args, **kwargs):
---> 85                 return getattr(self.get_queryset(), name)(*args, **kwarg
s)
     86             manager_method.__name__ = method.__name__
     87             manager_method.__doc__ = method.__doc__

~\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\models\quer
y.py in create(self, **kwargs)
    392         obj = self.model(**kwargs)
    393         self._for_write = True
--> 394         obj.save(force_insert=True, using=self.db)
    395         return obj
    396

~\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\models\base
.py in save(self, force_insert, force_update, using, update_fields)
    805
    806         self.save_base(using=using, force_insert=force_insert,
--> 807                        force_update=force_update, update_fields=update_f
ields)
    808     save.alters_data = True
    809

~\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\models\base
.py in save_base(self, raw, force_insert, force_update, using, update_fields)
    835             if not raw:
    836                 self._save_parents(cls, using, update_fields)
--> 837             updated = self._save_table(raw, cls, force_insert, force_upd
ate, using, update_fields)
    838         # Store the database on which the object was saved
    839         self._state.db = using

~\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\models\base
.py in _save_table(self, raw, cls, force_insert, force_update, using, update_fie
lds)
    921
    922             update_pk = meta.auto_field and not pk_set
--> 923             result = self._do_insert(cls._base_manager, using, fields, u
pdate_pk, raw)
    924             if update_pk:
    925                 setattr(self, meta.pk.attname, result)

~\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\models\base
.py in _do_insert(self, manager, using, fields, update_pk, raw)
    960         """
    961         return manager._insert([self], fields=fields, return_id=update_p
k,
--> 962                                using=using, raw=raw)
    963
    964     def delete(self, using=None, keep_parents=False):

~\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\models\mana
ger.py in manager_method(self, *args, **kwargs)
     83         def create_method(name, method):
     84             def manager_method(self, *args, **kwargs):
---> 85                 return getattr(self.get_queryset(), name)(*args, **kwarg
s)
     86             manager_method.__name__ = method.__name__
     87             manager_method.__doc__ = method.__doc__

~\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\models\quer
y.py in _insert(self, objs, fields, return_id, raw, using)
   1074         query = sql.InsertQuery(self.model)
   1075         query.insert_values(fields, objs, raw=raw)
-> 1076         return query.get_compiler(using=using).execute_sql(return_id)
   1077     _insert.alters_data = True
   1078     _insert.queryset_only = False

~\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\models\sql\
compiler.py in execute_sql(self, return_id)
   1097         with self.connection.cursor() as cursor:
   1098             for sql, params in self.as_sql():
-> 1099                 cursor.execute(sql, params)
   1100             if not (return_id and cursor):
   1101                 return

~\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\backends\ut
ils.py in execute(self, sql, params)
     78         start = time()
     79         try:
---> 80             return super(CursorDebugWrapper, self).execute(sql, params)
     81         finally:
     82             stop = time()

~\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\backends\ut
ils.py in execute(self, sql, params)
     63                 return self.cursor.execute(sql)
     64             else:
---> 65                 return self.cursor.execute(sql, params)
     66
     67     def executemany(self, sql, param_list):

~\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\utils.py in
 __exit__(self, exc_type, exc_value, traceback)
     92                 if dj_exc_type not in (DataError, IntegrityError):
     93                     self.wrapper.errors_occurred = True
---> 94                 six.reraise(dj_exc_type, dj_exc_value, traceback)
     95
     96     def __call__(self, func):

~\AppData\Local\Programs\Python\Python35\lib\site-packages\django\utils\six.py i
n reraise(tp, value, tb)
    683             value = tp()
    684         if value.__traceback__ is not tb:
--> 685             raise value.with_traceback(tb)
    686         raise value
    687

~\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\backends\ut
ils.py in execute(self, sql, params)
     63                 return self.cursor.execute(sql)
     64             else:
---> 65                 return self.cursor.execute(sql, params)
     66
     67     def executemany(self, sql, param_list):

~\AppData\Local\Programs\Python\Python35\lib\site-packages\django\db\backends\sq
lite3\base.py in execute(self, query, params)
    326             return Database.Cursor.execute(self, query)
    327         query = self.convert_query(query)
--> 328         return Database.Cursor.execute(self, query, params)
    329
    330     def executemany(self, query, param_list):

IntegrityError: NOT NULL constraint failed: people_person.age

In [3]: Person.objects.create(name="LiJun", age=24)
Out[3]: <Person: Person object>

In [4]: Person.objects.get(name="LiJun")
Out[4]: <Person: Person object>

In [5]:

查詢:我們用了一個 .objects.get() 方法查詢出來符合條件的對象
但是大家注意到了沒有,查詢結果中顯示<Person: Person object>,這里并沒有顯示出與WeizhongTu的相關信息,如果用戶多了就無法知道查詢出來的到底是誰,查詢結果是否正確,我們重新修改一下 people/models.py

  1. 使用 Django 提供的 QuerySet API
    Django提供了豐富的API, 下面演示如何使用它。
    $ python manage.py shell

from people.models import Person
Person.objects.create(name="WeizhongTu", age=24)
<Person: Person object>

我們新建了一個用戶WeizhongTu 那么如何從數據庫是查詢到它呢?

1
2
3

Person.objects.get(name="WeizhongTu")
<Person: Person object>

我們用了一個 .objects.get() 方法查詢出來符合條件的對象,但是大家注意到了沒有,查詢結果中顯示<Person: Person object>,這里并沒有顯示出與WeizhongTu的相關信息,

如果用戶多了就無法知道查詢出來的到底是誰,查詢結果是否正確,
我們重新修改一下 people/models.py:

models/py:



按 CTRL + C 退出當前的 Python shell, 重復上面的操作,我們就可以看到:

name 和 age 等字段中不能有 __(雙下劃線,因為在Django QuerySet API中有特殊含義(用于關系,包含,不區分大小寫,以什么開頭或結尾,日期的大于小于,正則等)

也不能有Python中的關鍵字,name 是合法的,student_name 也合法,但是student__name不合法,try, class, continue 也不合法,因為它是Python的關鍵字( import keyword; print(keyword.kwlist) 可以打出所有的關鍵字)

http://sqlitebrowser.org/假設你新建一個protject和一個app后沒有進行其他操作設置(setting.py),那么默認就是使用sqlite3,同步數據庫之后,會生成一個數據庫db.sqlite3,一方面可以將你在models.py中定義的類映射到數據庫的表中(會在mongoDB那篇中貼圖說明),一個類對應一個表

  1. 問題描述
    在配置完數據庫mysite/settings.py后,通常需要運行

python manage.py syncdb

為數據庫中每個應用建立一個數據庫表。
然而如果你安裝的Django Version >= 1.9,那么會出現如下問題:

gzxultra@gzxultraPC:~/django_try/mysite$ python manage.py syncdbUnknown command: 'syncdb'Type 'manage.py help' for usage.gzxultra@gzxultraPC:~/django_try/mysite$ python manage.py syncdbpython manage.py syncdbUnknown command: 'syncdbpython'Type 'manage.py help' for usage.

  1. 解決方法
    在stackoverflow上找到原因和解決方法:
    syncdb is deprecated because of the migration system.
    Now you can log your changes using makemigrations. This transforms your model changes into python code to make them deployable to another databases.
    After you created the migrations you have to apply them: migrate.
    So instead of using syncdb you should use makemigrations and then migrate.

簡言之:在Django 1.9及未來的版本種使用migrate代替syscdb.
./manage.py migrate

E:\ScienceSoft\Python\Django\learn_models> python manage.py syncdb
Unknown command: 'syncdb'
Type 'manage.py help' for usage.

E:\ScienceSoft\Python\Django\learn_models>manage.py help

Type 'manage.py help <subcommand>' for help on a specific subcommand.

Available subcommands:

[auth]
    changepassword
    createsuperuser

[contenttypes]
    remove_stale_contenttypes

[django]
    check
    compilemessages
    createcachetable
    dbshell
    diffsettings
    dumpdata
    flush
    inspectdb
    loaddata
    makemessages
    makemigrations
    migrate
    sendtestemail
    shell
    showmigrations
    sqlflush
    sqlmigrate
    sqlsequencereset
    squashmigrations
    startapp
    startproject
    test
    testserver

[sessions]
    clearsessions

[staticfiles]
    collectstatic
    findstatic
    runserver

E:\ScienceSoft\Python\Django\learn_models>
E:\ScienceSoft\Python\Django\learn_models>python manage.py syncdb
Unknown command: 'syncdb'
Type 'manage.py help' for usage.

E:\ScienceSoft\Python\Django\learn_models>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, people, sessions
Running migrations:
  No migrations to apply.
  Your models have changes that are not yet reflected in a migration, and so won
't be applied.
  Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage
.py migrate' to apply them.

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

推薦閱讀更多精彩內容