Django ——自强学堂学习笔记

96
夏天夏星
0.1 2017.07.22 21:15* 字数 5268

(一)、启动服务器

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>
pythons数据结构与算法