django基础语法

趁着一个项目学了学django框架,总的感觉是大而全,只接触到皮毛,慢慢学习吧。

django项目的创建

新建项目

新建一个django项目:

1
django-admin startproject django_project

运行成功后会有如下目录:

1
2
3
4
5
6
7
8
django_project
├── manage.py
├── django_project
├── __init__.py
├── asgi.py
├── settings.py
├── urls.py
└── wsgi.py

我们会发现执行命令后,新建了一个 django_project 目录,其中还有一个 django_project 目录

  • django_project: 项目的容器。
  • manage.py: 一个实用的命令行工具,可让你以各种方式与该 Django 项目进行交互。
  • __init__.py: 一个空文件,告诉 Python 该目录是一个 Python 包。
  • asgi.py: 一个 ASGI 兼容的 Web 服务器的入口,以便运行你的项目。
  • settings.py: 该 Django 项目的设置/配置。
  • urls.py: 该 Django 项目的 URL 声明; 一份由 Django 驱动的网站”目录”。
  • wsgi.py: 一个 WSGI 兼容的 Web 服务器的入口,以便运行你的项目。

启动开发服务器

可以运行python manage.py runserver 0.0.0.0:8000命令来启动django项目

创建app

在 Django 中,每一个应用(app)都是一个 Python 包,并且遵循着相同的约定。Django 自带一个工具,可以帮你生成应用的基础目录结构。

app应用与project项目的区别:

  • 一个app实现某个功能,比如博客、公共档案数据库或者简单的投票系统;
  • 一个project是配置文件和多个app的集合,这些app组合成整个站点;
  • 一个project可以包含多个app;
  • 一个app可以属于多个project!
  • app的存放位置可以是任何地点,但是通常都将它们放在与manage.py脚本同级的目录下,这样方便导入文件。

进入mysite项目根目录,输入下述命令:

1
$ python manage.py startapp app

系统会自动生成 app应用的目录,其结构如下:

1
2
3
4
5
6
7
8
9
app/
├── __init__.py
├── admin.py
├── apps.py
├── models.py
├── tests.py
├── views.py
├── migrations/
└── __init__.py

创建了之后还需要将app添加到setting.pyINSTALLED_APPS列表中,使得 django 能自动找到app中的模板文件(app-name/templates/下的文件)和静态文件(app-name/static/中的文件)

模型

基本设置

安装mysql驱动

1
pip install mysqlclient

修改setting.py配置

1
2
3
4
5
6
7
8
9
10
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 数据库引擎
'NAME': 'django_mysql', # 数据库名
'USER': 'root', # 账号
'PASSWORD': 'root', # 密码
'HOST': '127.0.0.1', # HOST
'POST': 3306, # 端口
}
}

模型的创建和迁移(激活)

模型类需要定义在app下的modules.py中,一个数据表对应一个模型类,表中的字段对应模型中的类属性。

创建模型

模型类需要继承自django.db.modules.Module

1
2
3
4
5
from django.db import modules

class Users(models.Model):
username = models.CharField(max_length=50)
password = models.CharField(max_length=50)

上面的代码相当于SQL语句:

1
2
3
4
5
CREATE TABLE app_users (
"id" serial NOT NULL PRIMARY KEY,
"username" varchar(50) NOT NULL,
"password" varchar(50) NOT NULL
);

其中,表名app_users由Django自动生成,默认格式为“项目名称+下划线+小写类名”,Django默认自动创建自增主键id,当然,你也可以自己指定主键。
可以通过在模型类中定义元数据类,自定义表名

1
2
3
4
5
6
7
8
from django.db import modules

class Users(models.Model):
username = models.CharField(max_length=50)
password = models.CharField(max_length=50)

class Meta:
db_table = 'users'

常用字段类型

  • AutoField 一个自动增加的整数类型字段
  • BooleanField 布尔值类型。默认值是None
  • CharField 字符串类型。必须接收一个max_length参数,表示字符串长度不能超过该值
  • DateField 日期类型。一个Python中的datetime.date的实例。
  • EmailField 邮箱类型,默认max_length最大长度254位。
  • FileField 上传文件类型
  • ImageField 图像类型,后面单独介绍
  • IntegerField 整数类型,最常用的字段之一。取值范围-2147483648到2147483647。
  • TextField 大量文本内容
  • UUIDField 用于保存通用唯一识别码的字段。使用Python的UUID类。

模型迁移(激活)

完成模型创建后,执行命令

1
2
3
4
# 制作迁移
python manage.py makemigrations
# 生成迁移
python manage.py migrate

增加数据

新建一个模型对象的方法有如下几种:

1
User.objects.create(username='admin', password='pwd')
1
2
user = User(username='admin', password='pwd')
user.save()
1
2
3
4
user = User()
user.name = 'admin'
user.password = 'pwd'
user.save()
1
User.boject.get_or_create(username='admin', password='pwd')

查询数据

查询对象有以下方法

  • 获取所有数据

    1
    User.objects.all() 
  • 切片操作

    1
    2
    # 获取5个人,不支持负索引,切片可以节约内存
    User.objects.all()[:5]
  • 获取满足条件的一个对象,如果有多条会报错

    1
    User.objects.get(username='admin')
  • 使用filter进行条件查询

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    # 查询username字段严格等于'admin'的所有对象
    User.objects.filter(username='amdin')
    User.objects.filter(username__iexact='admin') #不区分大小写

    # 查询username中包含admin的所有对象
    User.objects.filter(username__contains='admin')
    User.objects.filter(username__icontains='admin') # 不区分大小写

    # 查询username中以'admin'开头的
    User.objects.filter(username__startwith='admin')
    User.objects.filter(username__istartwith='admin') # 不区分大小写

    # 查询username中以'admin'结尾的
    User.objects.filter(username__endwith='admin')
    User.objects.filter(username__iendwith='admin') # 不区分大小写

    # 正则表达式查询
    User.objects.filter(name__regex='^admin')
    User.objects.filter(name__iregex='^admin') # 不区分大小写

    除此之外,还有
    __gt 大于
    __gte 大于等于
    __lt 小于
    __lte 小于等于
    __in 存在于一个list范围内

  • 使用exclude排除符合条件的

    1
    2
    # 排除包含 admin 的User对象
    User.objects.exclude(username__contains="admin")
  • 链式过滤
    filterexclude的结果依然是个QuerySet,因此它可以继续被filterexclude,这就形成了链式过滤:

    1
    User.objects.filter(username='admin').filter(password='password')[0]

使用Q对象进行复杂查询

普通filter函数里的条件都是“and”逻辑,如果你想实现“or”逻辑就需要使用Q对象
Q来自django.db.models.Q,用于封装关键字参数的集合,可以作为关键字参数用于filterexcludeget等函数
可以使用&或者|~来组合Q对象,分别表示与或非逻辑。它将返回一个新的Q对象。

1
2
3
Q(question__startswith='Who')|Q(question__startswith='What')
# 这相当于:
WHERE question LIKE 'Who%' OR question LIKE 'What%'

默认情况下,以逗号分隔的都表示AND关系:

1
2
3
4
5
6
7
Poll.objects.get(
Q(question__startswith='Who'),
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)
# 它相当于
# SELECT * from polls WHERE question LIKE 'Who%'
AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')

当关键字参数和Q对象组合使用时,Q对象必须放在前面,如下例子:

1
2
Poll.objects.get(
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),question__startswith='Who',)

如果关键字参数放在Q对象的前面,则会报错

修改(更新)数据

使用update()方法可以批量为QuerySet中所有的对象进行更新操作。

1
2
# 更新所有用户名为admin的密码为new_pwd
User.objects.filter(username='admin').update(password='new_pwd')

update方法会被立刻执行,并返回操作匹配到的行的数目

删除数据

删除对象使用的是对象的delete()方法。该方法将返回被删除对象的总数量和一个字典,字典包含了每种被删除对象的类型和该类型的数量

1
2
# 删除所有用户名为admin的对象
User.objects.filter(username='admin').delete()

其他有用的QuerySets的API

order_by() 对查询集进行排序

1
2
3
4
5
# 结果将按照id降序排序,然后再按照score升序排序。
# "-id"前面的负号表示降序顺序。 升序是默认的。 要随机排序,使用"?"
User.objects.filter(username='admin').order_by('-id', 'score')

User.objects.filter(username='admin').order_by('?')

reverse() 反向排序
distinct() 对查询集去重
values() 返回一个包含数据的字典的queryset,而不是模型实例
每个字典表示一个对象,键对应于模型对象的属性名称。

1
2
3
4
5
6
7
# 列表中包含的是Blog对象
User.objects.filter(name__startswith='Beatles')
# => <QuerySet [<Blog: Beatles Blog>]>

# 列表中包含的是数据字典
Blog.objects.filter(name__startswith='Beatles').values()
# => <QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>

视图

视图层是Django处理请求的核心代码层,我们大多数Python代码都集中在这一层面。

它对外接收用户请求,对内调度模型层和模版层,统合数据库和前端,最后根据业务逻辑,将处理好的数据,与前端结合,返回给用户。

URL路由

URL是Web服务的入口,用户通过浏览器发送过来的任何请求,都是发送到一个指定的URL地址,然后被响应。

在Django项目中编写路由,就是向外暴露我们接收哪些URL的请求,除此之外的任何URL都不被处理,也没有返回。通俗地理解,不恰当的形容,URL路由是你的Web服务对外暴露的API。

URL路由在Django项目中的体现就是urls.py文件,这个文件可以有很多个,但绝对不会在同一目录下。实际上Django提倡项目有个根urls.py,各app下分别有自己的一个urls.py,既集中又分治,是一种解耦的模式。

根 URL 就是在创建项目时自动创建的urls.py

1
2
3
4
5
6
from django.contrib import admin
from django.urls import path

urlpatterns = [
path('admin/', admin.site.urls),
]

默认导入了path方法和admin模块,然后有一条指向admin后台的url路径。

我们自己要编写的url路由,基本也是这个套路。

Django处理请求的流程

  1. 决定要使用的根URLconf模块。通常,这是ROOT_URLCONF设置的值,但是如果传入的HttpRequest对象具有urlconf属性(由中间件设置),则其值将被用于代替ROOT_URLCONF设置。通俗的讲,就是你可以自定义项目入口url是哪个文件!
  2. 加载该模块并寻找可用的urlpatterns。 它是django.urls.path()或者django.urls.re_path()实例的一个列表。
  3. 依次匹配每个URL模式,在与请求的URL相匹配的第一个模式停下来。也就是说,url匹配是从上往下的短路操作,所以url在列表中的位置非常关键。
  4. 导入并调用匹配行中给定的视图,该视图是一个简单的Python函数(被称为视图函数),或基于类的视图。 视图将获得如下参数:
    • 一个HttpRequest 实例。
    • 如果匹配的表达式返回了未命名的组,那么匹配的内容将作为位置参数提供给视图。
    • 关键字参数由表达式匹配的命名组组成,但是可以被django.urls.path()的可选参数kwargs覆盖。
  5. 如果没有匹配到任何表达式,或者过程中抛出异常,将调用一个适当的错误处理视图。

简单实例

1
2
3
4
5
6
7
8
9
from django.urls import path
from . import views

urlpatterns = [
path('', views.index),
path('articles/<int:year>/', views.year_archive),
path('articles/<int:year>/<int:month>/', views.month_archive),
path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
]
  • 要捕获一段url中的值,需要使用尖括号
  • 可以转换捕获到的值为指定类型,比如例子中的int
    默认情况下,捕获到的结果保存为字符串类型,不包含/这个特殊字符;
  • 匹配模式的最开头不需要添加/,因为默认情况下,每个url都带一个最前面的/,既然大家都有的部分,就不用浪费时间特别写一个了。

每当urls.py文件被第一次加载的时候,urlpatterns里的表达式们都将被预先编译,这会大大提高系统处理路由的速度。

path转换器

默认情况下,Django内置下面的路径转换器:

  • str:匹配任何非空字符串,但不含斜杠/,如果你没有专门指定转换器,那么这个是默认使用的
  • int:匹配0和正整数,返回一个int类型
  • slug:可理解为注释、后缀、附属等概念,是url拖在最后的一部分解释性字符。该转换器匹配任何ASCII字符以及连接符和下划线,比如building-your-1st-django-site
  • uuid:匹配一个uuid格式的对象。为了防止冲突,规定必须使用破折号,所有字母必须小写,例如075194d3-6885-417e-a8a8-6c931e272f00。返回一个UUID对象
  • path:匹配任何非空字符串,重点是可以包含路径分隔符/。这个转换器可以帮助你匹配整个url而不是一段一段的url字符串。

使用正则表达式

使用re_path()方法来进行基于正则的url匹配

1
2
3
4
5
6
7
8
9
10
from django.urls import path, re_path

from . import views

urlpatterns = [
path('articles/2003/', views.special_case_2003),
re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[\w-]+)/$', views.article_detail),
]

与path()方法不同的在于两点:

  • year中匹配不到10000等非四位数字,这是正则表达式决定的
  • 传递给视图的所有参数都是字符串类型。而不像path()方法中可以指定转换成某种类型。

指定视图参数的默认值

有一个小技巧,我们可以指定视图参数的默认值。 下面是一个URLconf和视图的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# URLconf
from django.urls import path

from . import views

urlpatterns = [
path('blog/', views.page),
path('blog/page<int:num>/', views.page),
]

# View (in app/views.py)
def page(request, num=1):
# Output the appropriate page of blog entries, according to num.
...

在上面的例子中,两个URL模式指向同一个视图views.page。但是第一个模式不会从URL中捕获任何值。 如果第一个模式匹配,page()函数将使用num参数的默认值”1”。 如果第二个模式匹配,page()将使用捕获的num值。

自定义错误页面

当Django找不到与请求匹配的URL时,或者当抛出一个异常时,将调用一个错误处理视图。Django默认的自带的错误视图包括400、403、404和500,分别表示请求错误、拒绝服务、页面不存在和服务器错误
它们分别位于:

  • handler400 —— django.conf.urls.handler400。
  • handler403 —— django.conf.urls.handler403。
  • handler404 —— django.conf.urls.handler404。
  • handler500 —— django.conf.urls.handler500。

这些值可以在根URLconf中设置。在其它app中的二级URLconf中设置这些变量无效。

我们可以自定义错误页面
首先,在根URLconf中额外增加下面的条目,并导入views模块:

1
2
3
4
5
6
7
8
9
10
11
12
13
from django.contrib import admin
from django.urls import path
from app import views

urlpatterns = [
path('admin/', admin.site.urls),
]

# 增加的条目
handler400 = views.bad_request
handler403 = views.permission_denied
handler404 = views.page_not_found
handler500 = views.error

然后在,app/views.py文件中增加四个处理视图:

1
2
3
4
5
6
7
8
9
10
11
def bad_request(request):
return render(request, '400.html')

def permission_denied(request):
return render(request, '403.html')

def page_not_found(request):
return render(request, '404.html')

def error(request):
return render(request, '500.html')

除了这些,还需要将setting.py中的DEUBG = True改为DEUBG = false

路由转发

通常,我们会在每个app里,各自创建一个urls.py路由模块,然后从根路由出发,将app所属的url请求,全部转发到相应的urls.py模块中。

路由转发使用的是include()方法,需要提前导入,它的参数是转发目的地路径的字符串,路径以圆点"."分割。

1
2
3
4
5
6
from django.urls import include, path

urlpatterns = [
path('community/', include('aggregator.urls')),
path('contact/', include('contact.urls')),
]

每当Django 遇到include()时,它会去掉URL中匹配的部分并将剩下的字符串发送给includeURLconf做进一步处理,也就是转发到二级路由去

反向解析

在URL中提供一个name参数,并赋值一个你自定义的、好记的、直观的字符串。
通过这个name参数,可以反向解析URL、反向URL匹配、反向URL查询或者简单的URL反查。

在需要解析URL的地方,对于不同层级,Django提供了不同的工具用于URL反查:

  • 在模板语言中:使用url模板标签。(也就是写前端网页时)
  • 在Python代码中:使用reverse()函数。(也就是写视图函数等情况时)
  • 在更高层的与处理Django模型实例相关的代码中:使用get_absolute_url()方法。(也就是在模型model中)

例如:

URLconf:

1
2
3
4
5
6
7
from django.urls import path

from . import views

urlpatterns = [
path('articles/<int:year>/', views.year_archive, name='news-year-archive'),
]

2019年对应的归档URL是/articles/2019/。

模板的代码中:

1
2
3
4
5
6
7
<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
{# Or with the year in a template context variable: #}
<ul>
{% for yearvar in year_list %}
<li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li>
{% endfor %}
</ul>

Python代码中:

1
2
3
4
5
6
7
8
from django.http import HttpResponseRedirect
from django.urls import reverse

def redirect_to_year(request):
# ...
year = 2019
# ...
return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))

app中的urls.py中,需要声明此app的名称,使用app_name = 'app名字'

之后需要反向解析到此urls.py中的路由,需要使用app名字.路由的格式。

比如:

1
2
3
4
5
6
7
8
9
10
from django.urls import path
from student import views


app_name = 'student'
urlpatterns = [
path('', views.index, name='index'), # /student/
path('info', views.info, name='info'), # /student/info
path('export', views.export, name='export'), # /student/export
]

视图函数

一个简单的视图

1
2
3
4
5
6
7
from django.http import HttpResponse
import datetime

def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)

每个视图函数都接收一个HttpRequest对象作为第一位置参数,一般取名为request
该视图返回一个HttpResponse对象,其中包含生成的HTML页面。

Django内置的一些方法

Django在django.shortcuts模块中,为我们提供了很多快捷方便的类和方法,它们都很重要,使用频率很高

render()

1
render(request, template_name, context=None, content_type=None, status=None, using=None)[source]

结合一个给定的模板和一个给定的上下文字典,返回一个渲染后的HttpResponse对象。
必须参数:

  • request:视图函数处理的当前请求,封装了请求头的所有数据,其实就是视图参数request
  • template_name:要使用的模板的完整名称或者模板名称的列表。如果是一个列表,将使用其中能够查找到的第一个模板。

可选参数:

  • context:添加到模板上下文的一个数据字典。默认是一个空字典。可以将认可需要提供给模板的数据以字典的格式添加进去。
    这里有个小技巧,使用Python内置的locals()方法,可以方便的将函数作用于内的所有变量一次性添加。
  • content_type:用于生成的文档的MIME类型。 默认为DEFAULT_CONTENT_TYPE设置的值。
  • status:响应的状态代码。 默认为200。
  • using:用于加载模板使用的模板引擎的NAME。

一个例子:

1
2
3
4
5
6
from django.shortcuts import render

def my_view(request):
return render(request, 'index.html', {
'foo': 'bar',
}, content_type='application/xhtml+xml')

这个示例等同于:

1
2
3
4
5
6
7
from django.http import HttpResponse
from django.template import loader

def my_view(request):
t = loader.get_template('index.html')
c = {'foo': 'bar'}
return HttpResponse(t.render(c, request), content_type='application/xhtml+xml')

redirect()

1
redirect(to, permanent=False, args, *kwargs)[source]

根据传递进来的url参数,返回HttpResponseRedirect
参数to可以是:

  • 一个模型:将调用模型的get_absolute_url()函数,反向解析出目的url;
  • 视图名称:可能带有参数:reverse()将用于反向解析url;
  • 一个绝对的或相对的URL:将原封不动的作为重定向的目标位置。

默认情况下是临时重定向,如果设置permanent=True将永久重定向。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
传递视图名,使用reverse()方法反向解析url:

def my_view(request):
...
return redirect('some-view-name', foo='bar')

重定向到硬编码的URL:
def my_view(request):
...
return redirect('/some/url/')

重定向到一个完整的URL:
def my_view(request):
...
return redirect('https://example.com/')

get_object_or_404()

1
get_object_or_404(klass, args, *kwargs)[source]

常用于查询某个对象,找到了则进行下一步处理,如果未找到则给用户返回404页面。

在后台,Django其实是调用了模型管理器的get()方法,只会返回一个对象。不同的是,如果get()发生异常,会引发Http404异常,从而返回404页面,而不是模型的DoesNotExist异常。

必需参数:

  • klass:要获取的对象的Model类名或者Queryset等;
  • **kwargs:查询的参数,格式应该可以被get()接受。

HttpRequest对象

每当一个用户请求发送过来,Django将HTTP数据包中的相关内容,打包成为一个HttpRequest对象,并传递给每个视图函数作为第一位置参数,也就是request,供我们调用。

常用属性

  1. HttpRequest.scheme
    字符串类型,表示请求的协议种类,’http‘或’https‘。

  2. HttpRequest.body
    bytes类型,表示原始HTTP请求的正文。它对于处理非HTML形式的数据非常有用:二进制图像、XML等。
    如果要处理常规的表单数据,应该使用HttpRequest.POST

  3. HttpRequest.path
    字符串类型,表示当前请求页面的完整路径,但是不包括协议名和域名。
    例如:”/music/bands/the_beatles/“。
    这个属性,常被用于我们进行某项操作时,如果不通过,返回用户先前浏览的页面。非常有用!

  4. HttpRequest.path_info
    在某些Web服务器配置下,主机名后的URL部分被分成脚本前缀部分和路径信息部分。path_info 属性将始终包含路径信息部分,不论使用的Web服务器是什么。
    使用它代替path可以让代码在测试和开发环境中更容易地切换。

    例如,如果应用的WSGIScriptAlias设置为/minfo,那么HttpRequest.path等于/music/bands/the_beatles/ ,而HttpRequest.path_info/minfo/music/bands/the_beatles/

  5. HttpRequest.method
    字符串类型,表示请求使用的HTTP方法。默认为大写。 像这样:

  6. HttpRequest.encoding
    字符串类型,表示提交的数据的编码方式(如果为None 则表示使用DEFAULT_CHARSET设置)。
    这个属性是可写的,可以通过修改它来改变表单数据的编码。任何随后的属性访问(例如GET或POST)将使用新的编码方式。

  7. HttpRequest.content_type
    表示从CONTENT_TYPE头解析的请求的MIME类型。

  8. HttpRequest.content_params
    包含在CONTENT_TYPE标题中的键/值参数字典。

  9. HttpRequest.GET
    一个类似于字典的对象,包含GET请求中的所有参数。

  10. HttpRequest.POST
    一个包含所有POST请求的参数,以及包含表单数据的字典。
    如果需要访问请求中的原始或非表单数据,可以使用HttpRequest.body属性。
    POST中不包含上传文件的数据。

  11. HttpRequest.COOKIES
    包含所有Cookie信息的字典。键和值都为字符串。
    可以类似字典类型的方式,在cookie中读写数据

  12. HttpRequest.FILES
    一个类似于字典的对象,包含所有上传的文件数据。
    FILES中的每个键为<input type="file" name="" />中的name属性值。
    FILES中的每个值是一个UploadedFile要在Django中实现文件上传,就要靠这个属性!
    如果请求方法是POST且请求的<form>中带有enctype="multipart/form-data"属性,那么FILES将包含上传的文件的数据。 否则,FILES将为一个空的类似于字典的对象,属于被忽略、无用的情形。

  13. HttpRequest.META
    包含所有HTTP头部信息的字典。 可用的头部信息取决于客户端和服务器,下面是一些示例:
    CONTENT_LENGTH —— 请求正文的长度(以字符串计)。
    CONTENT_TYPE —— 请求正文的MIME类型。
    HTTP_ACCEPT —— 可接收的响应Content-Type。
    HTTP_ACCEPT_ENCODING —— 可接收的响应编码类型。
    HTTP_ACCEPT_LANGUAGE —— 可接收的响应语言种类。
    HTTP_HOST —— 客服端发送的Host头部。
    HTTP_REFERER —— Referring页面。
    HTTP_USER_AGENT —— 客户端的user-agent字符串。
    QUERY_STRING —— 查询字符串。
    REMOTE_ADDR —— 客户端的IP地址。想要获取客户端的ip信息,就在这里!
    REMOTE_HOST —— 客户端的主机名。
    REMOTE_USER —— 服务器认证后的用户,如果可用。
    REQUEST_METHOD —— 表示请求方法的字符串,例如”GET” 或”POST”。
    SERVER_NAME —— 服务器的主机名。
    SERVER_PORT —— 服务器的端口(字符串)。

    CONTENT_LENGTHCONTENT_TYPE之外,请求中的任何HTTP头部键转换为META键时,都会将所有字母大写并将连接符替换为下划线最后加上HTTP_前缀

QueryDict对象

HttpRequest对象中,GETPOST属性都是一个django.http.QueryDict的实例

request.POSTrequest.GETQueryDict都是不可变,只读的。如果要修改它,需要使用QueryDict.copy()方法,获取它的一个拷贝,然后在这个拷贝上进行修改操作。

方法

django sessioin

启用session

编辑settings.py中的一些配置

MIDDLEWARE 确保其中包含以下内容
'django.contrib.sessions.middleware.SessionMiddleware'

INSTALLED_APPS 是包含'django.contrib.sessions'
这些是默认启用的。如果你不用的话,也可以关掉这个以节省一点服务器的开销。

sessioin的配置

使用数据库+缓存的session
配置settings.py

1
2
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎
SESSION_COOKIE_NAME = 'sessionid' # sesion的cookie保存在浏览器时的key

session的基本操作

以键值对的格式写session

1
request.session['键']=值

根据键读取值

1
2
3
request.session.get('键',默认值)
# 或者
request.session['键']

清除所有session,在存储中删除值的部分

1
request.session.clear()

清除session数据,在存储中删除session的整条数据

1
request.session.flush()

删除session中的指定键及值,在存储中只删除某个键及对应的值

1
del request.session['键']

设置session数据有效时间; 如果不设置,默认过期时间为两周

1
request.session.set_expiry(value)

如果过期时间的value是一个整数,则 session 数据 将在value秒没有活动后过期。
如果过期时间的valueNone,那么会话永不过期。
如果过期时间的value为0,那么用户会话的Cookie将在用户的浏览器关闭时过期。

静态文件

Django中提供了一种解析的方式配置静态文件路径。静态文件可以放在项目根目录下,也可以放在应用的目录下,由于有些静态文件在项目中是通用的,所以推荐放在项目的根目录下,方便管理。

setting.py中定义静态文件存放的物理目录

1
2
3
4
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]

这样,就设置了静态文件的存储路径为/static

在模板中,我们首先需要使用{% load static %}加载 Django 的 STATICFILES_STORAGE,之后使用{% static "images/a.jpg" %}来动态的获取静态文件,而不是写死的路径。

模板

默认配置下,Django 的模板系统会自动找到app下面的templates文件夹中的模板文件。
变量:{{ }}
功能类的:{% %}

获取字典内容:

1
2
3
user = {'name':'admin'}

{{dict_user.name}}

在模板中取字典的键是用点user.name,而不是Python中的 user['name']

循环for,条件判断if

1
2
3
{% for i in list %}
{{ i }}
{% endfor %}

for循环有一些属性:
forloop.counter 索引从 1 开始算
forloop.counter0 索引从 0 开始算
forloop.revcounter 索引从最大长度到 1
forloop.revcounter0 索引从最大长度到 0
forloop.first 当遍历的元素为第一项时为真
forloop.last 当遍历的元素为最后一项时为真
forloop.parentloop 用在嵌套的 for 循环中,获取上一层 for 循环的 forloop

1
2
3
{% for item in List %}
{{ item }}{% if not forloop.last %},{% endif %}
{% endfor %}

列表中可能为空时,用for empty

1
2
3
4
5
6
7
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% empty %}
<li>抱歉,列表为空</li>
{% endfor %}
</ul>
文章作者: Dar1in9
文章链接: http://dar1in9s.github.io/2020/06/12/django/django/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Dar1in9's Blog