Django教程(一)基础:环境搭建、views、urls、templates
一、环境搭建:
Django采用了MVC的软件设计模式,即模型M,视图V和控制器C。
Python 安装:Django本身是纯Python编写的,所以安装框架的第一步是确保你已经安装了Python。https://www.python.org/downloads/
如果安装在windows下,设置Python环境变量: 右击计算机->属性->高级->环境变量->修改系统变量path,添加Python安装地址。
django安装:总是有两个版本,稳定版和开发版trunk。最新版的django总是在https://www.djangoproject.com/download/可以找到。
下载名字类似于Django-1.10.2-final.tar.gz压缩文件。解压缩之后运行python setup.py install,像操作大多数Python库一样。
django默认安装在python的site-packages目录下:Python/Lib/site-packages/django。如果是windows环境,django的环境变量配置:将 C:/Python33/Lib/site-packages/django;C:/Python33/Scripts添加到path中,同以上python的配置。
在linux下安装django:
tar xzvf Django-*.tar.gz cd Django-* sudo python setup.py install #下载源码安装包的安装方式
pip install Django==1.10 #pip安装方式
pipinstall
--upgrade pip #升级
import Django django.VERSION #查看安装是否成功,及版本
windows下安装django:
pip install Django==1.11.2
安装数据库:首先,需要安装和配置数据库服务器本身;或者使用已存在的数据库服务器;如果只是开发测试,使用django自带的sqlite3也是可以的。然后安装连接数据库的库。
连接数据库的库或驱动:mysql---MySQLdb,mariadb----pyar...,PostgreSQL---PsyCopg,MSSQL--pymssql
创建数据库表或更改数据库表、字段
# 1. 创建更改的文件 python manage.py makemigrations # 2. 将生成的py文件应用到数据库 python manage.py migrate
项目: 是 Django 实例的一系列设置的集合,它包括数据库配置、Django 特定选项以及应用程序的特定设置。为了安全,通常将项目目录放在文档根目录之外。
如果在运行django-admin时,看到权限拒绝的提示,应当修改这个文件的权限。cd /usr/local/bin转到django-admin.py所在的目录,运行命令chmod +x django-admin.py
# django-admin #查看django-admin帮助
# django-admin startproject 项目名mysite #创建项目
# cd mysite #django的后续操作都需在项目目录下操作
# python manage.py startapp myapp #创建application程序
# cd ..
# tree mysite #查看项目目录结构,如下
mysite
├── manage.py #一个实用的命令行工具,可以让你以各种方式与该django项目进行交互
├── myapp #项目下的程序
│ ├── admin.py #后台,可以用很少量的代码就拥有一个强大的后台
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations #数据库版本的控制记录
│ │ └── __init__.py
│ ├── models.py #与数据库操作相关,存入或读取数据
│ ├── forms.py #表单,用户在浏览器上输入数据提交,对数据的验证工作以及输入框的生成等工作
│ └── urls.py #网址入口,关联到对应的views.py中的一个函数或者generic类,访问网址就对应一个函数。
│ └── views.py #处理用户发出的请求,从urls.py中对应过来, 通过渲染templates中的网页可以将显示内容。
└── mysite #项目的容器
| ├── __init__.py #空文件,表示这是一个python包
| ├── settings.py #该Django项目的设置/配置
| ├── urls.py #该Django项目的URL声明; 一份由Django驱动的网站"目录"。
| └── wsgi.py #一个WSGI兼容的Web服务器的入口,以便运行你的项目。
├── templates #存放公共模板的目录,后面将创建
├── static #存放css等静态资源的目录,后面将创建
创建app应用:一个项目一般包含多个应用,一个应用也可以用在多个项目中。
运行开发服务器:
# cd mysite #django的操作都需在项目目录下
# python manage.py runserver #运行开发服务器,默认为 http://127.0.0.1:8000/ # python manage.py runserver 8080 #以其它端口运行开发服务器 # python manage.py runserver 0.0.0.0:8000 #和他人共享开发服务器
注意:以上运行开发服务器,仅可用于开发环境
生产环境启动服务器:
搭建多个互不干扰的开发环境:开发环境,用 virtualenv 来管理多个开发环境,virtualenvwrapper 使得virtualenv变得更好用。
linux下,安装virtualenv
(sudo) pip install virtualenv virtualenvwrapper
修改~/.bash_profile或其它环境变量相关文件(如 .bashrc ),添加以下语句
export WORKON_HOME=$HOME/.virtualenvs export PROJECT_HOME=$HOME/workspace source /usr/local/bin/virtualenvwrapper.shsource
~/.bash_profile #重新加载配置文件,让配置生效
Windows 下,安装:
pip install virtualenvwrapper-win
更改配置环境:计算机,属性,高级系统设置,环境变量,添加WORKON_HOME
创建开发环境:
mkvirtualenv myenv1:创建运行环境myenv1
workon myenv1: 工作在 myenv1环境 或 从其它环境切换到 myenv1 环境
deactivate: 退出终端环境
其它的:
rmvirtualenv ENV:删除运行环境ENV
mkproject mic:创建mic项目和运行环境mic
mktmpenv:创建临时运行环境
lsvirtualenv: 列出可用的运行环境
lssitepackages: 列出当前环境安装了的包
创建超级管理员:
python manage.py createsuperuser # 按照提示输入用户名和对应的密码就好了,用户名和密码必填 python manage.py changepassword username # 修改 用户密码
导出、导入数据:
python manage.py dumpdata appname > appname.json
python manage.py loaddata appname.json
管理命令行:
Django 项目环境终端:python manage.py shell
数据库命令行:python manage.py dbshell
二、视图与URL
把我们新定义的app加到settings.py中的INSTALL_APPS中:
INSTALLED_APPS = [ 'myapp', ]
新建的 app 如果不加到 INSTALL_APPS 中的话, django 就不能自动找到app中的模板文件(app-name/templates/下的文件)和静态文件(app-name/static/中的文件)
1. 定义视图函数(访问页面时的内容)
# coding:utf-8 from django.http import HttpResponse def index(request): return HttpResponse(u"欢迎...!")
第一行是声明编码为utf-8, 因为我们在代码中用到了中文,如果不声明就报错.
第二行引入HttpResponse,它是用来向网页返回内容的。就像Python中的 print 一样,只不过 HttpResponse 是把内容显示到网页上。
2.定义视图函数关联的URL(网址)
from django.conf.urls import url from django.contrib import admin from learn import views as learn_views urlpatterns = [ url(r'^$', learn_views.index), url(r'^admin/', admin.site.urls), ]
示例:
# myapp/views.py from django.http import HttpResponse def add(request): a = request.GET['a'] b = request.GET['b'] c = str(int(a) + int(b)) return HttpResponse('c=' + c) # mysite/urls.py from myapp import views as app_views urlpatterns = [ url(r'^myapp/add/$', app_views.add) ] # mysite/settings.py INSTALLED_APPS = ['myapp',]
bash# python manage.py runsever 9001
测试:http://localhost:9001/myapp/add/?a=2&b=22
3.采用 /add/3/4/ 这样的网址的方式,更改views.py、urls.py:
# myapp/views.py
def add(request, a, b): #a,b作为参数传递
c = str(int(a) + int(b))
return HttpResponse('c=' + c) # mysite/urls.py url(r'^myapp/add/(\d+)/(\d+)$', app_views.add, name='add')
以上urls.py中的name ,可以用于在 templates, models, views ……中得到对应的网址,相当于“给网址取了个名字”,只要这个名字不变,网址变了也能通过名字获取到。
4.name
INSTALLED_APPS = [
'myapp',
]
myapp加入到settings.py的INSTALLED_APPS列表以后,在使用render时,django会自动找到INSTALLED_APPS中列出的各个app下的templates中的文件。
示例:
# myapp/views.py def index(request): return render(request, 'myapp/home.html') # mypp/templates/myapp/home.html <!DOCTYPE html> <html> <head> <title>xxx</title> </head> <body> <a href="/myapp/add/4/5/">计算 4+5</a> </body> </html> # urls.py urlpatterns = [ url(r'^$', app_views.index, name='home'), url(r'^myapp/add/a/b/$', app_views.add, name='add'), ]
以上示例,在templates目录下多加了一级子目录myapp,是为了避免模板重名可能会带来的问题。
django查找模板时侯,是在公共的templates目录和各app的templates目录查找。如果html文件不是直接在templates目录下,而是在templates目录的子目录下,在render的时侯加上子目录的路径。
问题:以上代码中, /add/a/b/,网址写死了。如果网址发生更改,对应的模板、视图、甚至model,都需进行相应的更改,代价很大。
解决办法:在写url的时侯使用name,不论url怎么变,如果在模板、视图、model使用的是变量name,那么即使url变了,只要name不变,其他代码也不受影响。在需要更改的时侯,用reverse转换name。
不带参数的: {% url 'name' %} 带参数的:参数可以是变量名 {% url 'name' 参数 %}
如,href="/myapp/add/4/5/" 更改为 href="{% url 'add' 4 5 %}"
5.reverse :跳转URL函数,第一个参数是name,第二个参数是args
from django.urls import reverse reverse('add', args=(3, 5)) # '/myapp/new_add/3/5' reverse('add', args=(50, 9)) #'/myapp/new_add/50/9'
在上面4的示例中,使用name,在服务器上解决了url变更的问题。
假如用户收藏夹中有 /add/4/5/ ,但此URL已经改为/new_add/4/5/ 了,虽然在服务器端使用了name命名视图函数,使服务器端的内部跳转不会有问题,但客户端收藏的直接的URL,并不知道name,因此客户端并不能知道URL已发生了改变!
如何让用户收藏的旧的URL自动跳转新的URL?Django不会帮你做这个,需要自己在views.py里L写一个跳转方法(用reverse转换URL、用HttpResponseRedirect重定向URL);并在urls.py中将旧的URL指向跳转视图:
# myapp/views.py from django.urls import reverse def old_add_redirect(request, a, b): return HttpResponseRedirect(reverse('add', args=(a, b))) #用reverse得到新的URL,用HttpResponseRedirect重定向到新的URL # urls.py url(r'^myapp/add/(\d+)/(\d+)/$', app_views.old_add_redirect), #旧URL,关联跳转函数 url(r'^myapp/new_add/(\d+)/(\d+)$', app_views.add, name='add') #新URL,仅改变了URL地址
三、模板
1.在前面我们都是用简单的 HttpResponse 来把内容显示到网页上,本节将讲解如何使用渲染模板的方法来显示内容。
示例:
# mysite/settings.py INSTALLED_APPS = ['learn', ] # learn/views.py from django.shortcuts import render def home(request): return render(request, 'learn/home.html') # mysite/urls.py from learn import views as learn_views urlpatterns = [ url(r'^$', learn_views.home, name='home'),] # learn/templates/learn/home.html <!DOCTYPE html> <html> <head> <title>欢迎光临</title> </head> <body> 欢迎光临hahahaha, this is hoempage with learn application. </body> </html>
默认配置下,Django 的模板系统会自动找到app下面的templates文件夹中的模板文件。
2. 公用模板:网站模板的设计,一般的,我们做网站有一些通用的部分,比如 导航,底部,访问统计代码等等
<!DOCTYPE html> <html> <head> <title>{% block title %} 这是动态标题!如重写,将覆盖;如没重写,将继承{% endblock %} - 这是公共标题</title> </head> <body> {% include 'header.html' %} {% include 'nav.html' %} {% block content %} <div>这是动态内容!如重写,将覆盖;如没重写,将继承</div> {% endblock %} {% include 'footer.html' %} </body> </html>
如果需要,写足够多的 block 以便继承的模板可以重写该部分,include 是包含其它文件的内容,就是把一些网页共用的部分拿出来,重复利用,改动的时候也方便一些,还可以把广告代码放在一个单独的html中,改动也方便一些,在用到的地方include进去。其它的页面继承自 base.html 就好了,继承后的模板也可以在 block 块中 include 其它的模板文件。
比如我们的首页 home.html,继承或者说扩展(extends)原来的 base.html,可以简单这样写,重写部分代码(默认值的那一部分不用改)
{% extends 'base.html' %} {% block title %}learn home{% endblock %} {% block content %} {% include 'ad.html %} 这是learn的首页 {% endblock %}
注意:模板一般放在app下的templates中,Django会自动去这个文件夹中找。但 假如我们每个app的templates中都有一个 index.html,当我们在views.py中使用的时候,直接写一个 render(request, 'index.html'),Django 能不能找到当前 app 的 templates 文件夹中的 index.html 文件夹呢?(答案是不一定能,有可能找错)
Django 模板查找机制: Django 查找模板的过程是在每个 app 的 templates 文件夹中找(而不只是当前 app 中的代码只在当前的 app 的 templates 文件夹中找)。各个 app 的 templates 形成一个文件夹列表,Django 遍历这个列表,一个个文件夹进行查找,当在某一个文件夹找到的时候就停止,所有的都遍历完了还找不到指定的模板的时候就是 Template Not Found (过程类似于Python找包)。这样设计有利当然也有弊,有利是的地方是一个app可以用另一个app的模板文件,弊是有可能会找错了。所以我们使用的时候在 templates 中建立一个 app 同名的文件夹,这样就好了。
这就需要把每个app中的 templates 文件夹中再建一个 app 的名称,仅和该app相关的模板放在 app/templates/app/ 目录下面,就不会混淆。
3.模板中的循环、条件判断,常标签、过滤器
标签:for,if 这样的功能也都是标签,用 {% 标签 %}表示
过滤器:用{{ 变量|方法 }}表示。管道符号后面的功能,比如{{ var|length }},求变量长度的 length 就是一个过滤器。
变量:用 {{ 变量 }}表示
如果需要将一个或多个变量共享给多个网页或者所有网页使用,比如在网页上显示来访者的IP,这个可以使用 Django 上下文渲染器 来做。
实例一,显示一个基本的字符串在网页上:
# learn/views.py # _*_ coding: utf-8 _*_ from django.shortcuts import render def home(request): string = "hahahahahhahaha" return render(request, 'learn/home.html', {'string': string}) # learn/templates/learn/home.html {{ string }}
在视图中我们传递了一个字符串名称是 string 到模板 home.html,在模板中这样使用它:{{ string }}
实例二,基本的 for 循环 和 List内容的显示:
# learn/views.py from django.shortcuts import render def home(request): language = ["HTML", "CSS", "jQuery", "Python", "Django"] return render(request, 'learn/home.html', {'language': language}) {# learn/templates/learn/home.html #} {% for i in language %} {{ i }} {% endfor %}
实例三,显示字典中的内容:
# learn/views.py def home(request): info_dict = {'site': 'mysite', 'content': 'learn', 'address': 'bj'} return render(request, 'learn/home.html', {'info_dict': info_dict}) # learn/templates/learn/home.html 站点:{{ info_dict.site }} 内容:{{ info_dict.content }}
使用for循环字典代替之
{# learn/templates/learn/home.html #} {% for key, value in info_dict.items %} {{ key }}: {{ value }} {% endfor %}
实例四,在模板进行 条件判断和 for 循环的详细操作:
# learn/views.py def home(request): List = map(str, range(100)) return render(request, 'learn/home.html', {'Lt': List}) # {}中的key,是传递给模板的变量名 {# learn/templates/learn/home.html #} {% for item in Lt %} {{ item }}, {% endfor %}
“{{ item }},”, 巧用“,”将元素隔开。
但最后一个元素后也有逗号,如何解决?利用变量forllop.last,可以判断是不是循环到了最后一项。如果是最后一项,则为真;否则为假。
{# learn/templates/learn/home.html #}
{% for item in Lt %}
{{ item }}{% if not forloop.last %},{% endif %}
{% endfor %}
在for循环中还有很多有用的东西,如下:
变量 | 描述 |
---|---|
forloop.counter | 索引从 1 开始算 |
forloop.counter0 | 索引从 0 开始算 |
forloop.revcounter | 索引从最大长度到 1 |
forloop.revcounter0 | 索引从最大长度到 0 |
forloop.first | 当遍历的元素为第一项时为真 |
forloop.last | 当遍历的元素为最后一项时为真 |
forloop.parentloop |
用在嵌套的 for 循环中, 获取上一层 for 循环的 forloop |
当列表中可能为空值时用 for empty:
{% for athlete in athlete_list %} <li>{{ athlete.name }}</li> {% empty %} <li>抱歉,列表为空</li> {% endfor %}
4.as语句,将内容取别名,相当于定义了一个新的变量,可以在此模板多次使用。
{% url 'add' 3 5 as url_add %} <a href="{{ url_add }}"link: {{ url_add }}</a>
5.比较操作
==, !=, >=, <=, >, < 这些比较都可以在模板中使用,比如
{% if var >= 90 %} 优秀 {% elif var >= 80 %} 良好 {% elif var >= 60 %} 及格 {% else %} 不及格啊! {% endif %}
and, or, not, in, not in 也可以在模板中使用。假如我们判断 num 是不是在 0 到 100 之间:
{% if num <= 100 and num >= 0 %}
num在0到100之间
{% else %}
数值不在范围之内!
{% endif %}
假如我们判断 'xy' 在不在一个列表变量 List 中:
{% if 'xy' in List %] 在列表中 {% endif %}
获取当前用户: {{ request.user }}
如果用户登录了,显示用户名;如果没有登录,请登录。
{% if request.user.is_authenticated %} {{ request.user.username }},你好! {% else %} 请登录,<a href="url login">click here to login</a> {% endif %}
获取当前网址: {{ request.path }}
获取当前 GET 参数: {{ request.GET.urlencode }}
判断 delete 参数是不是 1 来删除当前的页面内容
<a href="{{ request.path }}?{{ request.GET.urlencode }}&delete=1">当前网址加参数 delete</a>
posted on 2014-06-01 20:26 myworldworld 阅读(184) 评论(0) 收藏 举报