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安装方式
pip install --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.sh
source ~/.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
  更多命令、帮助:python manage.py 

 二、视图与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)    收藏  举报

导航