此外还需一个URL分发器,将一个个URL请求分发给不同的View处理。
直接通过pip3 install去下载对应版本的Django即可。
先新建一个Django_projects文件夹,进入这个文件夹后,创建第一个项目。
django-admin startproject mysite # 创建了一个名为"mysite"的Django 项目
django project的目录结构:
mysite |--- manage.py # Django项目里的工具,可以通过它调用django shell和数据库,启动关闭项目与项目交互等 |--- mysite
|--- __init__.py |--- settings.py # 包含了项目的默认设置 |--- urls.py # 负责把URL模式映射到应用程序 |--- wsgi.py
注意:
启动Django:
python manage.py runserver 127.0.0.1:8080 # 此时已经可以启动django项目了,只不过什么逻辑也没有
通过manage.py可以创建应用
python manage.py startapp app01 # 通过执行manage.py文件来创建应用,
# 应该在这个manage.py的文件所在目录下执行这句话,因为其他目录里面没有这个文件
python manage.py startapp app02 # 每个应用都有自己的目录,每个应用的目录下都有自己的views.py视图函数和models.py数据库操作相关的文件
将URL中的路径和本地文件系统上的路径做对应关系映射:
STATIC_URL = ‘/static/‘ # 这里表示的是URL中的路径 STATICFILES_DIRS=( os.path.join(BASE_DIR,"statics"), # 这里表示的是本地文件系统的路径 )
将csrf中间件选项暂时注释:
# ‘django.middleware.csrf.CsrfViewMiddleware‘, #这里先注释掉
python manage.py runserver 127.0.0.1:8080 # 本机可以不写ip地址了 默认是本机的8000端口
django2.0之后是使用了path,但是也向下兼容使用url,导入url即可。
from django.conf.urls import url urlpatterns = [ url(正则表达式, views视图函数,参数,别名), ] # 正则表达式:一个正则表达式字符串 # views视图函数:一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串 # 参数:可选的要传递给视图函数的默认参数(字典形式) # 别名:一个可选的name参数
所谓无名分组,其实就是给视图函数传递位置参数。
将要传递的参数在放入小括号()中,然后在对应的视图函数中按顺序接收对应的参数即可。
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [# 无名分组 (给应用视图函数传递位置参数) url(r‘books/(\d{4})/$‘, views.year), # 完全匹配 url(r‘^books/(\d{4})/(\d{2})/$‘, views.year_mouth), url(r‘^books/(\d{4})/(\d{2})/(\d{2})/$‘, views.year_mouth_day), ]
# 是否开启URL访问地址后面没有/跳转至带有/的路径的配置项,默认是开启的 APPEND_SLASH=True
所谓有名分组,就是捕获URL中的值并以关键字参数形式传递给视图函数。
分组命名正则表达式组的语法是(?P<name>pattern)
,其中name
是组的名称,pattern
是要匹配的模式。
urlpatterns = [ url(r‘^articles/(?P<year>[0-9]{4})/$‘, views.year),
# 某年的,(?P<year>[0-9]{4})这是命名参数,那么函数year(request,year),形参名称必须是year这个名字
# 如果这个正则后面没有写$符号,即便是输入了月份路径,也会被它拦截下拉,因为它的正则也能匹配上 url(r‘^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$‘, views.month), url(r‘^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$‘, views.details), ]
因为一个项目中可能有多个应用,所以我们需要对URL做分发。
要将新创建的应用添加到setttings配置文件中的INSTALLED_APPS中
使用include即可完成对URL的分发:(include需要手动导入)
from django.conf.urls import url,include urlpatterns = [ # 输入不同的url找到不同的app 分发给不同的应用的urls.py url(r‘^app01/‘, include(‘app01.urls‘)), # 这时app01中的urls只需要处理app01后面的那部分url了 url(r‘^app02/‘, include(‘app02.urls‘)), ]
通过给URL定义一个别名来防止URL路径更改后URL失效。
使用别名:
# 给url匹配模式起名为 home,别名不需要改,路径就可以随便改了,别的地方要使用这个路径,则用这个别名即可 url(r‘^home‘, views.home, name=‘home‘), url(r‘^index/(\d*)‘, views.index, name=‘index‘),
在模板中的引用:
{% url ‘home‘ %} #模板渲染的时候,被django解析成了这个名字对应的那个url,这个过程叫做反向解析
http请求中产生的核心对象:(所在位置:django.http)
1) path
2) method
if request.method=="GET": do_something() elif request.method=="POST": do_something_else()
3) GET
4) POST
5) session
6) COOKIES
7) FILES
8) user
方法:
HttpResponse对象由我们自己创建,且每个view请求处理方法必须返回一个HttpResponse对象。
HttpResponse类在django.http.HttpResponse,需要手动导入。
HttpResponse对象上扩展的常用方法:
return render(req,"my backend.html",locals())
render和redirect的区别:
模板渲染的两种特殊符号:
使用双大括号来引用变量:
{{ var_name }}
Views函数中的代码:
def current_time(req): now=datetime.datetime.now() return render(req, ‘current_datetime.html‘, {‘current_date‘:now}) # 在模板中,就可以使用{{current_date}}来引用这里的变量
利用点号来查找深度变量
点号可以访问列表索引,也可以通过字典的键来访问对应的值,同样也可以访问对象的属性以及方法
{{ items.2 }} # 通过列表的索引来获取对应的值 {{ person.name }} # 通过字典的key来获取对应的值 {{ date.month }} # 通过点号来访问对象的属性 {{ var.upper }} # 通过访问对应的方法来调用它
1)语法格式
2)常用的过滤器
# default:如果值是False,就替换成设置的默认值,否则就是用本来的值 {{ value|default:‘值是False‘}}
# length:返回值的长度,作用于字符串和列表 {{ name_list|length }}
# slice:切片,支持python中可用的所有数据类型 {{ name_list|slice:‘1:3‘ }} {{ s|slice:‘1::2‘ }} # add:给变量加上相应的值 {{ value|add:3 }} # capfirst:首字母大写 {{ value|capfirst }} # upper:字符转换成大写 {{ value|upper }} # cut:从字符串中移除指定的字符 {{ value|cut:‘ ‘}} # date:格式化日期字符串 {{ value|date:‘Y-m-d‘ }} # join:设定连接符将可迭代对象的元素连接在一起,与字符串的join方法相同 {{ name_list|join:‘_‘}} {{ tu|join:‘+‘}} # safe:告知Django这段代码为安全的,不必进行转义 {{ value|safe}}
{% if %}
{% if num >= 100 and 8 %} {% if num > 200 %} <p>num大于200</p> {% else %} <p>num大于100小于200</p> {% endif %} {% elif num < 100%} <p>num小于100</p> {% else %} <p>num等于100</p> {% endif %}
{% for %}
<ul> {% for obj in list %} <li>{{ obj.name }}</li> {% endfor %} </ul> # 在标签里可以用reversed来反序循环列表 {% for obj in list reversed %} ... {% endfor %}
{% for foo in name_list %} {% if forloop.first %} {{ foo }} {% else %} <p>只有第一次循环打印</p> {% endif %} {% endfor %}
{% csrf_token %}
<form action="{% url "xxoo" %}" > <input type="text"> <input type="submit"value="提交"> {% csrf_token %} </form>
{% url %}
{% with %}
{% with total=fhjsaldfhjsdfhlasdfhljsdal %} {{ total }} {% endwith %}
{% load %}
1)在app中创建templatetags模块(必须创建,且名字不能改)
2)创建 .py文件,如my_tags.py
from django import template from django.utils.safestring import mark_safe register = template.Library() #register的名字是固定的,不可改变 @register.filter def filter_multi(v1,v2): return v1 * v2 @register.simple_tag def simple_tag_multi(v1,v2): return v1 * v2 @register.simple_tag def my_input(id,arg): result = "<input type=‘text‘ id=‘%s‘ class=‘%s‘ />" %(id,arg,) return mark_safe(result)
3)在settings中的INSTALLED_APPS配置当前app
3)在使用自定义simple_tag和filter的html文件中导入之前创建的 my_tags.py :{% load my_tags %}
4)使用simple_tag和filter
{% load xxx %} #首行 # num=12 {{ num|filter_multi:2 }} # filter_multi只能传一个值,前面的num将作为它的第一个参数 # 而冒号后的值将作为第二个参数 {% simple_tag_multi 2 5 %} # 参数不限,但不能放在if for语句中 {% simple_tag_multi num 5 %} # filter_multi可以用在if等语句后,simple_tag不可以 {% if num|filter_multi:30 > 100 %} {{ num|filter_multi:30 }} {% endif %}
1)extends
{% extends ‘master.html‘ %}
2)block
{% block %}
标签越好在母版中定义:
<div class="menu"> {% block content %} {% endblock %} </div>
在其他页面对母版继承后,再进行对应内容的替换:
{% extends master.html %} # 继承母版 # 进行对应位置内容的替换 {% block content %} base页面首页 {% endblock %}
3)保留母版内容并添加新特性
母版html:
<div class="menu"> {% block content %} <div>这是母版测试页面</div> {% endblock %} </div>
base.html:
{% block content %} {{ block.super }} base页面首页 {% endblock %}
ORM是 “对象-关系-映射” 的简称。(Object Relational Mapping,简称ORM)
1)配置settings文件
django默认使用sqlite的数据库,并默认自带sqlite的数据库驱动
如果要更改数据库为MySQL,需要配置如下:
DATABASES = { ‘default‘: { ‘ENGINE‘: ‘django.db.backends.mysql‘, ‘NAME‘: ‘books‘, # 数据库名称,必须事先创建好 ‘USER‘: ‘root‘, # 数据库用户名 ‘PASSWORD‘: ‘‘, # 数据库密码 ‘HOST‘: ‘‘, # 数据库主机,留空默认为localhost ‘PORT‘: ‘3306‘, # 数据库端口 } }
2)更改MySQL驱动
django默认的MySQL驱动为MySQLdb,而MySQLdb在py3中有问题,所以还需要更改MySQL驱动为pymysql
# 找到项目名文件下的__init__,在里面写入: import pymysql pymysql.install_as_MySQLdb()
3)在models中通过类创建数据库表
在对应app的models文件中创建数据库表
from django.db import models # Create your models here. class UserInfo(models.Model): # 这里类就对应于一张表,且必须继承models.Model id = models.AutoField(primary_key=True) name = models.CharField(max_length=16) age = models.IntegerField() current_date = models.DateField() """ 上面的几个类的属性通过ORM映射就对应成了: create table userinfo( id int primary key auto_increment, name varchar(16), age int, current_date date) """
4)在数据库中生成表结构
将上面的类生成真生的数据库中的表结构
python manage.py makemigrations # Django 会在相应的 app 的migrations文件夹下面生成 一个python脚本文件 python manage.py migrate # 生成数据库表 # 此时,对应app下面的migrations目录中出现一个0001_initial.py的文件,这个文件就是执行了上述指令之后产生的脚本文件,这个文件就是一个记录
CharField # 字符串字段, 用于较短的字符串 # CharField 必须有一个参数 maxlength, 限制该字段所允许的最大字符数. IntegerField # 用于保存一个整数 DecimalField # 一个浮点数. 必须 提供两个参数: # max_digits 总位数(不包括小数点和符号) # decimal_places 小数位数 # 要保存最大值为 999 (小数点后保存2位): # models.DecimalField(..., max_digits=5, decimal_places=2) # 要保存最大值一百万(小数点后保存10位): # models.DecimalField(..., max_digits=17, decimal_places=10) # max_digits大于等于17就能存储百万以上的数了 # admin 用一个文本框(<input type="text">)表示该字段保存的数据 AutoField # 一个 IntegerField, 添加记录时它会自动增长,通常不需要直接使用这个字段 # 自定义一个主键:my_id=models.AutoField(primary_key=True) # 如果不指定主键,系统会自动添加一个主键字段到 model BooleanField # A true/false field # admin 用 checkbox 来表示此类字段 TextField # 一个容量很大的文本字段 # admin 用一个 <textarea> (文本区域)表示该字段数据.(一个多行编辑框) EmailField # 一个带有检查Email合法性的 CharField,不接受 maxlength 参数 DateField # 一个日期字段 # 有下列额外的可选参数: # auto_now # 当对象被保存时(更新或者添加),自动将该字段的值设置为当前时间. # 通常用于表示 "last-modified" 时间戳. # auto_now_add # 当对象首次被创建时,自动将该字段的值设置为当前时间. # 通常用于表示对象创建时间. # (仅仅在admin中有意义...) DateTimeField # 一个日期时间字段. 类似 DateField 支持同样的附加选项 ImageField # 类似 FileField, 不过要校验上传对象是否是一个合法图片 # 它有两个可选参数:height_field和width_field,如果提供这两个参数,则图片将按提供的高度和宽度规格保存 FileField # 一个文件上传字段. # 要求一个必须有的参数: upload_to, 一个用于保存上载文件的本地文件系统路径. # 这个路径必须包含 strftime #formatting, # 该格式将被上载文件的 date/time替换(so that uploaded files don‘t fill up the given directory). # admin 用一个<input type="file">部件表示该字段保存的数据(一个文件上传部件) . # # 在一个 model 中使用 FileField 或 ImageField 需要以下步骤: # 1) 在 settings 文件中, 定义一个完整路径给 MEDIA_ROOT 以便让 Django在此处保存上传文件 # 出于性能考虑,这些文件并不保存到数据库 # 定义MEDIA_URL 作为该目录的公共 URL. 要确保该目录对WEB服务器用户帐号是可写的. # 2) 在 model 中添加 FileField 或 ImageField, 并确保定义了 upload_to 选项, # 以告诉 Django使用 MEDIA_ROOT 的哪个子目录保存上传文件. # 数据库中要保存的只是文件的路径(相对于 MEDIA_ROOT). # 如果 ImageField 叫作 mug_shot, 就可以在模板中以 {{ object.#get_mug_shot_url }} 这样的方式得到图像的绝对路径 URLField # 用于保存 URL. # 若 verify_exists 参数为 True (默认), 给定的 URL 会预先检查是否存在( 即URL是否被有效装入且没有返回404响应). # admin 用一个 <input type="text"> 文本框表示该字段保存的数据(一个单行编辑框) NullBooleanField # 类似 BooleanField, 不过允许 NULL 作为其中一个选项. # 推荐使用这个字段而不要用 BooleanField 加 null=True 选项 # admin 用一个选择框 <select> (三个可选择的值: "Unknown", "Yes" 和 "No" ) 来表示这种字段数据 XMLField # 一个校验值是否为合法XML的 TextField # 必须提供参数: schema_path, 它是一个用来校验文本的 RelaxNG schema 的文件系统路径. FilePathField # 可选项目为某个特定目录下的文件名. # 支持三个特殊的参数, 其中第一个是必须提供的.这三个参数可以同时使用. # path # 必需参数. 一个目录的绝对文件系统路径. FilePathField 据此得到可选项目. # Example: "/home/images". # match # 可选参数. 一个正则表达式, 作为一个字符串, FilePathField 将使用它过滤文件名. # 注意这个正则表达式只会应用到 base filename 而不是路径全名. # Example: "foo.*\.txt^", 将匹配文件 foo23.txt 却不匹配 bar.txt 或 foo23.gif. # recursive # 可选参数.要么 True 要么 False. 默认值是 False. 是否包括 path 下面的全部子目录. # # match 仅应用于 base filename, 而不是路径全名 # FilePathField(path="/home/images", match="foo.*", recursive=True) # 会匹配 /home/images/foo.gif 而不匹配 /home/images/foo/bar.gif IPAddressField # 一个字符串形式的 IP 地址, (i.e. "24.124.1.30"). CommaSeparatedIntegerField # 用于存放逗号分隔的整数值. 类似 CharField, 必须要有maxlength参数.
null # 如果为True,Django 将用NULL 来在数据库中存储空值,默认值是 False. blank # 如果为True,该字段允许不填。默认为False。 # 这与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。 # 如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。 default # 字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用 # 如果字段没有设置可以为空,将来如果后添加一个字段,这个字段就要给一个default值 primary_key # 如果为True,那么这个字段就是模型的主键。 # 如果没有指定任何一个字段的primary_key=True,Django会自动添加一个IntegerField字段做为主键 # 所以除非想覆盖默认的主键行为,否则没必要设置任何一个字段的primary_key=True。 unique # 如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的 choices # 由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项 # 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框, # 而且这个选择框的选项就是choices 中的选项 db_index # 如果db_index=True 则代表着为此字段设置数据库索引 DatetimeField、DateField、TimeField 这个三个时间字段,都可以设置如下属性: auto_now_add # 配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。 # auto_now # 配置上auto_now=True,每次更新数据记录的时候会更新该字段,标识这条记录最后一次的修改时间
原文:https://www.cnblogs.com/hgzero/p/13211344.html