警告
本文最后更新于 2020-09-11,文中内容可能已过时。
Django是一个开放源代码的Web应用框架,由Python写成。采用了MTV的框架模式,即模型M,视图V和模版T。它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是CMS(内容管理系统)软件。并于2005年7月在BSD许可证下发布。这套框架是以比利时的吉普赛爵士吉他手Django Reinhardt来命名的。2019年12月2日,Django3.0
发布。
说明
本文所包含的内容仅仅是用于自我学习,可能有些内容晦涩难懂,如碰到问题,可以留言问我
基础
下载与基本命令
仅介绍最简单的方式
安装
pip3 install django
创建项目
django-admin.py startproject mysite
创建应用
python manage.py startapp app01
注册应用
vim settings.py
1
2
3
INSTALLED_APPS = [
'app01.apps.App01Config'
]
启动项目
python manage.py runserver 8001
settings文件配置
静态文件
需要配置STATICFILES_DIRS
和STATIC_URL
两个变量
STATICFILES_DIRS
1
2
3
4
5
6
7
8
9
# 方式一
在每个app里面新建一个static文件夹 , 将静态文件放到里面 , 在加载静态文件时 , 比如要在模板中用到静态文件 , django会自动在每个app里面搜索static文件夹 ( 所以 , 不要把文件夹的名字写错哦 , 否则django就找不到你的文件夹了 )
# 方式二
在所有的app文件外面 , 建立一个公共的文件夹 , 因为有些静态文件不是某个app独有的 , 那么就可以把它放到一个公共文件夹里面 , 方便管理 ( 注意 , 建立一个公共的静态文件的文件夹只是一种易于管理的做法 , 但是不是必须的 , app是可以跨app应用静态文件的 , 因为最后所有的静态文件都会在STATIC_ROOT ( 项目上线使用 ) 里面存在 )
# 配置STATICFILES_DIRS让django知道你把一些静态文件放到app以外的公共文件夹中
STATICFILES_DIRS = [
os . path . join ( BASE_DIR , 'static' ),
]
STATIC_URL
通过配置STATIC_URL
后,可以通过http://127.0.0.1:8000/static/app/image/photo.png
进行访问
1
STATIC_URL = '/static/'
数据库配置
为了适应各种数据库,需要按需配置
mysql配置
1
2
3
4
5
6
7
8
9
10
11
12
13
DATABASES = {
'default' : {
'ENGINE' : 'django.db.backends.mysql' ,
'NAME' : 'mxonline' ,
'USER' : 'mxonline' ,
'PASSWORD' : 'Vefhaj-ryxpet-nivxe9' ,
'HOST' : 'rm-uf6b1jgns7ikmhl0ayo.mysql.rds.aliyuncs.com' ,
'PORT' : 3306 ,
'OPTIONS' : {
'init_command' : 'SET sql_mode=STRICT_TRANS_TABLES' ,
},
}
}
打印sql语句
如果想打印orm转换过程中的sql,需要在settings中进行如下配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
LOGGING = {
'version' : 1 ,
'disable_existing_loggers' : False ,
'handlers' : {
'console' :{
'level' : 'DEBUG' ,
'class' : 'logging.StreamHandler' ,
},
},
'loggers' : {
'django.db.backends' : {
'handlers' : [ 'console' ],
'propagate' : True ,
'level' : 'DEBUG' ,
},
}
}
CMD中调用Django环境
1
2
3
4
5
6
7
8
9
10
import os
if __name__ == '__main__' :
os . environ . setdefault ( "DJANGO_SETTINGS_MODULE" , "untitled15.settings" )
import django
django . setup ()
from app01 import models
books = models . Book . objects . all ()
print ( books )
视图层
Response对象
HttpResponse对象
响应对象主要有三种形式:
HttpResponse()
render()
redirect()
HttpResponse()
括号内直接跟一个具体的字符串作为响应体,比较直接很简单,所以这里主要介绍后面两种形式。
render()
结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的HttpResponse
对象。
render
方法就是将一个模板页面中的模板语法进行渲染,最终渲染成一个html
页面作为响应体。
1
render ( request , template_name [, dict ] )
redirect()
重定向
1
2
redirect ( '/some/url/' )
redirect ( 'http://www.baidu.com/' )
JsonResponse对象
向前端返回一个json格式字符串的两种方式
CBV和FBV
CBV
:基于类的视图(Class base view)
FBV
:基于函数的视图(Function base view)
简单文件上传
前端通过form表单上传文件后,可以通过request.FILES.get('file_value')
取出,file_value是imput标签的value值,后续通过wb模式写入文件即可
1
2
3
4
file_name = request . FILES . get ( 'file_value' ) . name
with open ( file_name , 'wb' ) as f :
for i in request . FILES . get ( 'file_value' ) . chunks ():
f . write ( i )
路由层
本质是URL与要为该URL调用的视图函数之间的映射表,对于客户端发来的某个URL调用哪一段逻辑代码对应执行
使用方式
1
2
3
4
5
6
7
8
9
#新的2.x版本导入path,导入简化
from django.urls import path
#原来的1.x版本url方式,conf子包
from django.conf.urls import url , include
urlpatterns = [
path ( 路由 , views视图函数 , 参数 , 别名 )
url ( 正则表达式 , views视图函数 , 参数 , 别名 ),
]
正则表达式:一个正则表达式字符串
views视图函数:一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
参数:可选的要传递给视图函数的默认参数(字典形式)
别名:一个可选的name参数
有名分组
1
2
3
4
5
from django.conf.urls import url , include
from app01.views import AppView
urlpatterns = [
# 捕获到的数据都是str类型
url ( r '^articles/(?P<year>[0-9] {4} )/(?P<month>[0-9] {2} )/(?P<day>[0-9] {2} )/$' , AppView . as_view ()),
在app/views.py
下
1
2
3
4
5
from django.views.generic.base import View
class AppView ( View ):
def get ( request , year = 1 , month , month , * args , ** kwargs ):
print ( year )
return HttpResponse ( 'ok' )
路由分发
1
2
3
4
5
6
from django.conf.urls import url , include
urlpatterns = [
# 路由分发
path ( 'app01/' , include ( 'app01.urls' )),
]
1
2
3
4
5
6
# 路由分发:在app01里创建一个urls
from django.conf.urls import url
from app01.views import AppView
urlpatterns = [
url ( r '^test/(?P<year>[0-9] {2} )/$' , AppView . as_view ()),
]
反向解析
在使用Django项目时,为了方便修改url而不影响代码,因此需要专门的URL生成机制
urls.py
1
2
3
4
5
from django.conf.urls import AppView
from app01 import views
urlpatterns = [
url ( r '^test/(?P<year>[0-9] {2} )/(?P<month>[0-9] {2} )/$' , AppView . as_view (), name = 'test' ),
]
html模版语法
1
< a href = "{% url 'test' 10 23 %}" > 哈哈</ a >
view.py
1
2
3
4
5
6
7
from django.shortcuts import render , HttpResponse , redirect , reverse
def get ( request , year = 1 , month , month , * args , ** kwargs ):
print ( year )
print ( month )
url = reverse ( 'test' , args = ( 10 , 20 ))
print ( url )
return HttpResponse ( 'ok' )
名称空间
由于项目可能会有多个app,在绑定url时,可能会出现多个反向解析相同的url的name,为了防止这个情况,需要名称空间,在每个名称空间中,可以定义相同name的名字
总url.py
1
2
3
4
5
from django.urls import path , re_path , include
urlpatterns = [
path ( 'app01/' , include ( 'app01.urls' , 'app01' )),
path ( 'app02/' , include ( 'app02.urls' , 'app02' ,))
]
app01
的urls.py
1
2
3
4
5
from django.conf.urls import url
from app01 import AppView
urlpatterns = [
url ( r 'index/' , AppView . as_view (), name = 'index' ),
]
app02
的urls.py
1
2
3
4
5
6
from app02 import AppView
urlpatterns = [
url ( r 'index/' , AppView . as_view (), name = 'index' ),
]
视图函数:url=reverse('app02:index')
模版:<a href="{% url 'app02:index'%}">哈哈</a>
Django2.0版的path
Django2.0的re_path
和1.0的url
一样,url中year参数是字符串类型的,为了让django自动转换为int类型,可以使用path
使用方法
1
2
3
4
5
6
7
8
9
10
from django.urls import path
from . import views
urlpatterns = [
path ( 'articles/2003/' , views . special_case_2003 ),
path ( 'articles/<int:year>/' , views . year_archive ),
path ( 'articles/<int:year>/<int:month>/' , views . month_archive ),
path ( 'articles/<int:year>/<int:month>/<slug>/' , views . article_detail ),
# path才支持,re_path不支持
path ( 'order/<int:year>' , views . order ),
]
模版层
一般而言,一个网页氛围前端和后端,后端主要是和数据库打交道,然后将数据传给前端,前端再进行处理,而有时候可能会出现一个人全栈,这时候,为了快速开发,需要Python来对前端来进行处理时最方便的,因此需要模版语言
python的模板:HTML代码+模板语法
变量
简单语法:{{ 变量名 }}
深度查询语法:{{ 变量名.变量名.变量名 }}
标签
for 循环
1
2
3
4
{% for foo in dic %}
{{ foo }}
<ul>foo</ul>
{% endfor %}
注:循环序号可以通过{{ forloop }}显示
forloop.counter
当前循环的索引值(从1开始)
forloop.counter0
当前循环的索引值(从0开始)
forloop.revcounter
当前循环的倒序索引值(从1开始)
forloop.revcounter0
当前循环的倒序索引值(从0开始)
forloop.first
当前循环是不是第一次循环(布尔值)
forloop.last
当前循环是不是最后一次循环(布尔值)
forloop.parentloop
本层循环的外层循环
for 标签带有一个可选的{% empty %}
从句,以便在给出的组是空的或者没有被找到时,可以有所操作。
1
2
3
4
5
6
{% for person in person_list %}
<p> {{ person.name }} </p>
{% empty %}
<p>sorry,no person here</p>
{% endfor %}
if 判断
1
2
3
4
5
6
7
{% if num > 100 or num < 0 %}
<p>无效</p>
{% elif num > 80 and num < 100 %}
<p>优秀</p>
{% else %}
<p>凑活吧</p>
{% endif %}
if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。
with
使用一个简单地名字缓存一个复杂的变量,当你需要使用一个“昂贵的”方法(比如访问数据库)很多次的时候是非常有用的
1
2
3
4
{% with total = business.employees.count %}
{{ total }} employee {{ total | pluralize }}
{% endwith %}
不要写成as
csrf_token
用于跨站请求伪造保护,会自动生成html,如果使用{{ csrf_token }}
,则只生成csrf_token
静态文件
加载方法{% load static %}
使用<img src="{% static "images/hi.jpg" %}" alt="Hi!" />
某个文件多处被用到可以存为一个变量
1
2
{% static "images/hi.jpg" as myphoto %}
<img src=" {{ myphoto }} "></img>
模版导入
{% include '模版名称' %}
模版继承
在HTML中我们总是可以看到多个页面中有许多相同的地方,例如头部,底部,左边栏等等,我们可以使用模版继承方式,将相同不变的写在基础页中,将变化的用变量包围起来,以便在各个页面中针对性的修改
定义基本模版base.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css"/>
<title> {% block title %} My amazing site {% endblock %} </title>
</head>
<body>
<div id="sidebar">
{% block sidebar %}
<ul>
<li><a href="/">Home</a></li>
<li><a href="/blog/">Blog</a></li>
</ul>
{% endblock %}
</div>
<div id="content">
{% block content %}{% endblock %}
</div>
</body>
</html>
在子模版中继承并修改不同的元素
1
2
3
4
5
6
7
8
9
10
{% extends "base.html" %}
{% block title %} My amazing blog {% endblock %}
{% block content %}
{% for entry in blog_entries %}
<h2> {{ entry.title }} </h2>
<p> {{ entry.body }} </p>
{% endfor %}
{% endblock %}
extends:告诉模版引擎,这个模版“继承”了另一个模版。
block:用子模版中的内容来替换这些block
使用建议:
如果你在模版中使用 {% extends %} 标签,它必须是模版中的第一个标签。其他的任何情况下,模版继承都将无法工作。
在base模版中设置越多的 {% block %} 标签越好。请记住,子模版不必定义全部父模版中的blocks,所以,你可以在大多数blocks中填充合理的默认内容,然后,只定义你需要的那一个。多一点钩子总比少一点好。
如果你发现你自己在大量的模版中复制内容,那可能意味着你应该把内容移动到父模版中的一个 {% block %} 中。
为了更好的可读性,你也可以给你的 {% endblock %} 标签一个 名字 。例如:
1
2
3
{% block content %}
...
{% endblock content %}
在大型模版中,这个方法帮你清楚的看到哪一个{% block %} 标签被关闭了。
不能在一个模版中定义多个相同名字的 block 标签。
过滤器
注意:冒号后面不能加空格
格式化年月:{{ now|date:"Y-m-d H:i:s" }}
如果变量为空,设置默认值,空数据,None,变量不存在,都适用:{{ name |default:'数据为空' }}
计算长度,只有一个参数:{{ person_list |length }}
计算文件大小:{{ 1024 |filesizeformat }}
字符串切片,前闭后开,前面取到,后面取不到:{{ 'hello world lqz' |slice:"2:-1" }}
截断字符,至少三个起步,因为会有三个省略号(传负数,1,2,3都是三个省略号):{{ 'the world mine' |truncatechars:"4" }}
截断文字,以空格做区分,这个不算省略号:{{ 'xxx 是 大帅比 谢谢' |truncatewords:"1" }}
不必转义:{{ link1|safe }}
♠
:{{ dot }}
加负数(传数字字符串都可以):{{ "10"|add:"-2" }}
转换大写:{{ name|upper }}
自定义标签和过滤器
在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag.
在app中创建templatetags模块(模块名只能是templatetags)
创建任意 .py 文件,如:my_tags.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 )
导入之前创建的my_tags.py
使用simple_tag和filter
1
2
3
4
5
6
7
# num=12
{{ num | filter_multi : 2 }} #24
{{ num | filter_multi :"[22,333,4444]" }}
{% simple_tag_multi 2 5 %} 参数不限,但不能放在if for语句中
{% simple_tag_multi num 5 %}
模型层
使用
在各app下的models.py中创建
1
2
3
4
5
6
7
8
9
10
11
12
13
14
from django.db import models
# Create your models here.
class Book ( models . Model ):
id = models . AutoField ( primary_key = True )
name = models . CharField ( max_length = 64 )
pub_data = models . DateField ()
price = models . DecimalField ( max_digits = 5 , decimal_places = 2 )
publish = models . CharField ( max_length = 12 )
class Meta :
verbose_name = '书'
verbose_name_plural = verbose_name
def __str__ ( self ):
return self . name
增
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 方式1
# 一对一
book_obj = Book . objects . create ( title = "python葵花宝典" , state = True , price = 100 , publish = "苹果出版社" , pub_date = "2012-12-12" )
# 一对多
publish_obj = Publish . objects . get ( nid = 1 )
book_obj = Book . objects . create ( title = "" , publishDate = "2012-12-12" , price = 100 , publish = publish_obj )
# 方式2
# 一对一
book_obj = Book ( title = "python葵花宝典" , state = True , price = 100 , publish = "苹果出版社" , pub_date = "2012-12-12" )
book_obj . save ()
# 一对多
book_obj = Book . objects . create ( title = "" , publishDate = "2012-12-12" , price = 100 , publish_id = 1 )
多对多
1
2
3
4
5
6
7
8
9
# 当前生成的书籍对象
book_obj = Book . objects . create ( title = "追风筝的人" , price = 200 , publishDate = "2012-11-12" , publish_id = 1 )
# 为书籍绑定的做作者对象
yuan = Author . objects . filter ( name = "yuan" ) . first () # 在Author表中主键为2的纪录
egon = Author . objects . filter ( name = "alex" ) . first () # 在Author表中主键为1的纪录
# 绑定多对多关系,即向关系表book_authors中添加纪录
book_obj . authors . add ( yuan , egon ) # 将某些特定的model对象添加到被关联对象集 == book_obj.authors.add(*[])
查
all()
:查询所有结果
filter(\*\*kwargs)
:它包含了与所给筛选条件相匹配的对象
get(\*\*kwargs)
:返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。
exclude(\*\*kwargs)
:它包含了与所给筛选条件不匹配的对象
order_by(\*field)
:对查询结果排序(’-id')
reverse()
:对查询结果反向排序
count()
:返回数据库中匹配查询(QuerySet)的对象数量。
first()
:返回第一条记录
last()
:返回最后一条记录
exists()
:如果QuerySet包含数据,就返回True,否则返回False
values(\*field)
:返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列
values_list(\*field)
:它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
distinct()
:从返回结果中剔除重复纪录
values的使用
1
2
Book . objects . all () . values ( 'name' )
Book . objects . all () . values_list ( 'price' , 'name' )
双下划线模糊查询
1
2
3
4
5
6
7
8
9
10
Book . objects . filter ( price__in = [ 100 , 200 , 300 ])
Book . objects . filter ( price__gt = 100 )
Book . objects . filter ( price__lt = 100 )
Book . objects . filter ( price__gte = 100 )
Book . objects . filter ( price__lte = 100 )
Book . objects . filter ( price__range = [ 100 , 200 ])
Book . objects . filter ( title__contains = "python" )
Book . objects . filter ( title__icontains = "python" )
Book . objects . filter ( title__startswith = "py" )
Book . objects . filter ( pub_date__year = 2012 )
删
1
2
3
# delete():立即删除对象而不返回任何值,在 Django 删除对象时,会模仿 SQL 约束 ON DELETE CASCADE 的行为,换句话说,删除一个对象时也会删除与它相关联的外键对象
b = Blog . objects . get ( pk = 1 )
b . delete ()
如果不想级联删除,可以设置为:
1
pubHouse = models . ForeignKey ( to = 'Publisher' , on_delete = models . SET_NULL , blank = True , null = True )
改
1
Book . objects . filter ( title__startswith = "py" ) . update ( price = 120 )
多对多关系其它常用API
1
2
3
book_obj . authors . remove () # 将某个特定的对象从被关联对象集合中去除。 ====== book_obj.authors.remove(*[])
book_obj . authors . clear () #清空被关联对象集合
book_obj . authors . set () #先清空再设置
基于对象的跨表查询
1
2
3
4
5
6
7
# 一对多,多对多查询查询
正向查询 ( 按字段 : publish )
反向查询 ( 按表名 : book_set )
# 一对一查询
正向查询 ( 按字段 : authorDetail )
反向查询 ( 按表名 : author )
基于双下划线的跨表查询
1
2
3
4
5
# 正向查询 按字段:publish
queryResult = Book . objects . filter ( publish__name = "苹果出版社" ) . values_list ( "title" , "price" )
# 反向查询 按表名:book
queryResult = Publish . objects . filter ( name = "苹果出版社" ) . values_list ( "book__title" , "book__price" )
字段参数
null
:用于表示某个字段可以为空。
unique
:如果设置为unique=True
则该字段在此表中必须是唯一的 。
db_index
:如果db_index=True
则代表着为此字段设置索引。
default
:为该字段设置默认值。
auto_now_add
:配置auto_now_add=True
,创建数据记录的时候会把当前时间添加到数据库。
auto_now
:配置上auto_now=True
,每次更新数据记录的时候会更新该字段。
常用字段和参数
AutoField(Field)
int自增列,必须填入参数 primary_key=True
BigAutoField(AutoField)
bigint自增列,必须填入参数 primary_key=True
注:当model中如果没有自增列,则自动会创建一个列名为id的列
SmallIntegerField(IntegerField)
PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
IntegerField(Field)
整数列(有符号的) -2147483648 ~ 2147483647
PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
BigIntegerField(IntegerField)
长整型(有符号的) -9223372036854775808 ~ 9223372036854775807
BooleanField(Field)
NullBooleanField(Field)
CharField(Field)
字符类型
必须提供max_length参数, max_length表示字符长度
TextField(Field)
EmailField(CharField)
字符串类型,Django Admin以及ModelForm中提供验证机制
IPAddressField(Field)
字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制
GenericIPAddressField(Field)
字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
参数:
protocol,用于指定Ipv4或Ipv6, ‘both’,“ipv4”,“ipv6”
unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol=“both”
URLField(CharField)
字符串类型,Django Admin以及ModelForm中提供验证 URL
SlugField(CharField)
字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)
CommaSeparatedIntegerField(CharField)
UUIDField(Field)
字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证
FilePathField(Field)
字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
参数:
path, 文件夹路径
match=None, 正则匹配
recursive=False, 递归下面的文件夹
allow_files=True, 允许文件
allow_folders=False, 允许文件夹
FileField(Field)
字符串,路径保存在数据库,文件上传到指定目录
参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
ImageField(FileField)
字符串,路径保存在数据库,文件上传到指定目录
参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
width_field=None, 上传图片的高度保存的数据库字段名(字符串)
height_field=None 上传图片的宽度保存的数据库字段名(字符串)
DateTimeField(DateField)
日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
DateField(DateTimeCheckMixin, Field)
TimeField(DateTimeCheckMixin, Field)
DurationField(Field)
长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型
FloatField(Field)
DecimalField(Field)
10进制小数
参数:
max_digits,小数总长度
decimal_places,小数位长度
BinaryField(Field)
F查询
Django 提供F()
来做两个字段的值做比较
1
2
3
4
5
# 查询评论数大于收藏数2倍的书籍
Book . objects . filter ( commnetNum__lt = F ( 'keepNum' ) * 2 )
# 将每一本书的价格提高30元
Book . objects . all () . update ( price = F ( "price" ) + 30 )
Q查询
如果你需要执行更复杂的查询(例如OR 语句),你可以使用Q对象。
Q对象可以使用&和|操作符组合起来。当一个操作符在两个Q对象上使用时,它产生一个新的Q对象。
1
bookList = Book . objects . filter ( Q ( authors__name = "yuan" ) | Q ( authors__name = "egon" ))
你可以组合&和|操作符以及使用括号进行分组来编写任意复杂的Q对象。同时,Q对象可以使用~操作符取反,这允许组合正常的查询和取反(NOT)查询
查询函数可以混合使用Q对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q对象)都将"AND”在一起。但是,如果出现Q对象,它必须位于所有关键字参数的前面
1
bookList = Book . objects . filter ( Q ( publishDate__year = 2016 ) | Q ( publishDate__year = 2017 ), title__icontains = "python" )
用户模型类
在项目中,我们首先需要的用户认证功能,而Django自带用户认证功能,不过有些功能,例如手机验证登录等等功能并没有,因此,我们需要在此基础上自定义用户模型类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from django.contrib.auth.models import AbstractUser
GENDER_CHOICES = (
( 'male' , '男' ),
( 'female' , '女' )
)
# 重写用户模型类, 继承自 AbstractUser
class UserProfile ( AbstractUser ):
# 以下为新增字段
name = models . CharField ( max_length = 30 , null = True , blank = True , verbose_name = '姓名' )
birthday = models . DateField ( null = True , blank = True , verbose_name = '出生年月' )
gender = models . CharField ( max_length = 6 , choices = GENDER_CHOICES , default = 'female' , verbose_name = '性别' )
mobile = models . CharField ( max_length = 11 , verbose_name = '电话' )
email = models . CharField ( max_length = 100 , null = True , blank = True , verbose_name = '邮箱' )
class Meta :
# 在后台管理系统中显示名称
verbose_name = '用户'
verbose_name_plural = verbose_name
# 在 str 魔法方法中, 返回用户名称
def __str__ ( self ):
return self . name
指定用户模型类
在默认情况下,Django会自动使用默认的用户模型类,由于我们自定义了用户模型类,因此,需要在settings.py中指明
1
2
# 修改指定默认用户表
AUTH_USER_MODEL = 'users.UserProfile'
其他
manage文件
python manage.py runserver ip:port
:利用ip可以访问不在同一个主机的数据库
python manage.py startapp app01
:开启一个app叫app01,创建如下文件:__init__.py
,models.py
,tests.py
,view.py
python manage.py createsuper
:交互式创建超级用户
python manage.py makemigrations
:创建迁移文件
python manage.py migrate
:重建数据库
DjangoUeditor
将djangoueditor源码拷贝到项目根目录下
INSTALLED_APPS 中配置 ‘DjangoUeditor’
配置相关的url:
re_path(r’^ueditor/’, include(’extra_apps.DjangoUeditor.urls’))
下载ueditor插件并放置到xadmin/plugins目录下
将editor文件名配置到xadmin/plugins/init .py文件的PLUGINS变量中'ueditor'
在对应的model的管理器中配置:
style_fields = {
“xxx”:“ueditor”
}
xxxx表示model中需要富文本的字段
xadmin的使用
settings文件中配置
1
2
3
4
5
6
INSTALLED_APPS = [
# 需开启默认admin
'django.contrib.admin' ,
'crispy_forms' ,
'extra_apps.xadmin'
]
安装依赖包
pip install django-crispy-forms django-import-export django-reversion django-formtools future httplib2 six xlwt xlsxwriter
生成数据库
python manage.py makemigrations
python manage.py migrate
配置url
1
2
3
4
5
6
7
from django.urls import path , re_path
from extra_apps import xadmin
urlpatterns = [
# path('admin/', admin.site.urls),
re_path ( '^xadmin/' , xadmin . site . urls )
]
drf