准备工作:熟悉Django命令行工具

django-admin.py 是Django的一个用于管理任务的命令行工具,常用的命令整理如下:

<1> 创建一个django工程 : django-admin.py startproject mysite

  当前目录下会生成mysite的工程,目录结构如下:

  

  • manage.py ----- Django项目管理工具,通过它可以调用django shell和数据库等。
  • settings.py ---- 包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作的变量。
  • urls.py ----- 负责把URL模式映射到应用程序。

<2>在mysite目录下创建blog应用: python manage.py startapp blog

  目录结构如下:

  

<3>启动django项目:python manage.py runserver 8080

  这样我们的django就启动起来了!

<4>生成同步数据库的脚本:python manage.py makemigrations

                     同步数据库:  python manage.py migrate

  

   注意:在开发过程中,数据库同步误操作之后,难免会遇到后面不能同步成功的情况,解决这个问题的一个简单粗暴方法是把migrations目录下

的脚本(除__init__.py之外)全部删掉,再把数据库删掉之后创建一个新的数据库,数据库同步操作再重新做一遍。

<5>当我们访问http://127.0.0.1:8080/admin/时,会出现:

  所以我们需要为进入这个项目的后台创建超级管理员:python manage.py createsuperuser设置好用户名和密码后便可登录啦!

<6>清空数据库:python manage.py  flush

<7>查询某个命令的详细信息: django-admin.py  help  startapp

admin 是Django 自带的一个后台数据库管理系统。

<8>启动交互界面 :python manage.py  shell

     这个命令和直接运行 python 进入 shell 的区别是:你可以在这个 shell 里面调用当前项目的 models.py 中的 API,对于操作数据,还有一些小测试非常方便。

<9> 终端上输入python manage.py 可以看到详细的列表,在忘记子名称的时候特别有用

一、URL(路由系统)

  1. 浏览器会自动给url后加一个“/”
  2. django会自动给路由的正则表达式前面加一个“/”
  3. django会给任何不带“/”结尾的url语句添加“/”(可设置)
  4. 短路路由规则:匹配到第一条就忽略后面所有!
  5. 所以路由顺序很重要!

1.普通路由

  1. url(r'^index/',views.index),

2.正则路由

  1. url(r'^page/\d+', views.page),

3.正则加括号

提供参数传递,按顺序接收,接收到的都是字符串

  1. # urls.py
  2. url(r'^page/(\d+)', views.page),

 

  1. # views.py
  2. def page(request, index):
  3. page = index
  4. return HttpResponse("page: 第%s页" % page)

4.正则加括号加指定参数名

提供指定参数传递,按参数名字进行接收,顺序可变,但参数名必须相同,接收到的都是字符串

urls.py

  1. url(r'^page/(?P<page>\d+)/(?P<number>\d+)', views.page), 

views.py

  1. def page(request, page, number):
  2. p = page
  3. n = number
  4. return HttpResponse("page: 第%s页 第%s条" %(p, n))

5.分级路由include

在app01中新建urls文件

  1. from django.conf.urls import include
  2. url(r'index/', include(app01.urls)), 

二、Views(视图函数)

http请求中产生两个核心对象:

http请求:HttpRequest对象

http响应:HttpResponse对象

1. HttpRequest对象的属性和方法

  1. from django.shortcuts import render,HttpResponse
  2.  
  3. # Create your views here.
  4. def index(request):
  5. #request.POST
  6. #request.GET
  7. #return HttpResponse("hello world!")
  8. #1.path:请求页面的全路径,不包括域名
  9. print(request.path)
  10.  
  11. #2.get_full_path:请求页面的全路径,包括域名
  12. print(request.get_full_path())
  13.  
  14. #3.method:请求中使用的HTTP方法
  15. #if req.method == "GET":
  16. # do_something()
  17. #elseif req.method=="POST":
  18. # do_something_else()
  19. #GET: 包含所有HTTP GET参数的类字典对象
  20. # POST:包含所有HTTP POST参数的类字典对象
  21. # 服务器收到空的POST请求的情况也是可能发生的,也就是说,表单form通过
  22. # HTTP POST方法提交请求,但是表单中可能没有数据,因此不能使用
  23. #if req.POST来判断是否使用了HTTP POST方法;应该使用 if req.method=="POST"
  24.  
  25. #4.COOKIES:包含所有cookies的标准Python字典对象;keys和values都是字串。
  26.  
  27. #5.FILES:包含所有上传文件的类字典对象;
  28. # FILES中的每一个Key都是<input type = "file" name = "" / > 标签中name属性的值,
  29. # FILES中的每一个value同时也是一个标准的python字典对象,包含下面三个Keys:
  30. # filename:上传文件名,用字符串表示
  31. # content_type:上传文件的Content Type
  32. # content:上传文件的原始内容
  33.  
  34. #6.user:是一个django.contrib.auth.models.User对象,代表当前登陆的用户。如果访问用户当前
  35. # 没有登陆,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。你可以通
  36. # 过user的is_authenticated()方法来辨别用户是否登陆:
  37. # if req.user.is_authenticated();
  38. # 只有激活Django中的AuthenticationMiddleware时该属性才可用
  39.  
  40. # 7.session:唯一可读写的属性,代表当前会话的字典对象;自己有激活Django中的session支持时该属性才可用。

Http Request对象的属性和方法

2. HttpResponse对象的属性和方法

HttpRequest对象是由django自动创建的,HttpResponse对象需要我们自己创建,每个view请求处理方法必须返回一个HttpResponse对象。

HttpResponse类在django.http.HttpResponse

在HttpResponse对象上扩展的常用方法:

  1. 页面渲染:render()(推荐), render_to_response()
  2. 页面跳转:redirect("路径")
  3. locals():可以直接将函数中所有的变量传给模板
  1. /*--------------------register.html-------------------*/
  2. <body>
  3. <form action="{% url 'register' %}" method="post">
  4. <p>用户名<input type="text" name="username"></p>
  5. <p>密码<input type="password" name="password"></p>
  6. <p><input type="submit" value="提交注册"></p>
  7.  
  8. </form>
  9. <script src="/static/jquery-3.1.1.js"></script>
  10. </body>
  11. /*--------------------login.html---------------------*/
  12. <body>
  13. <form action="{% url 'login' %}" method="post">
  14. <p>姓名<input type="text" name="username"></p>
  15. <p>性别<input type="text" name="sex"></p>
  16. <p>邮箱<input type="text" name="email"></p>
  17. <p><input type="submit" value="submit"></p>
  18. </form>
  19. /*--------------------user_page.html--------------*/
  20. <body>
  21. <h1>用户{{ name }}你好</h1>
  22. </body>
  23. /*---------------------blog\urls.py------------------*/
  24. from django.contrib import admin
  25. from django.urls import path
  26. from django.conf.urls import url
  27.  
  28. from blog import views
  29.  
  30. urlpatterns = [
  31. # path('admin/', admin.site.urls),
  32.  
  33. url(r'register/',views.register,name="register"),
  34. url(r'^login',views.login,name="login"),
  35. url(r'^user_page',views.user_page,name="user_page")
  36. ]
  37. /*----------------------views.py-----------------------*/
  38. from django.shortcuts import render,HttpResponse,render_to_response,redirect
  39.  
  40. # Create your views here.
  41. user_list=[]
  42. def register(request):
  43. if request.method == "POST":
  44. username=request.POST.get("username",None)
  45. password=request.POST.get("password",None)
  46. print("username:",username)
  47. if username:
  48. user_list.append(username)
  49. return redirect("/blog/login/")
  50. #redirect方法进行页面跳转时,地址栏URL会跟改为跳转页面的,此处为http://127.0.0.1/blog/login
  51. #return render(request,"login.html")
  52. #在此处用render方法进入页面,地址栏URL不会改变,仍然为http;//127.0.0.1/blog/index
  53.  
  54. return HttpResponse("username is None")
  55. return render(request,"register.html")
  56. #或者render_to_response("register.html")
  57. def login(request):
  58. if request.method=="POST":
  59. user=request.POST.get("username",None)
  60. if user in user_list:
  61. name=user
  62. return redirect("/blog/user_page/")
  63. return HttpResponse("username does not exist")
  64.  
  65. return render(request, "login.html")
  66.  
  67. def user_page(request):
  68.  
  69. return render(request,"user_page.html",locals())

注册-登录-用户首页流程模拟

三、Template(模板系统)

在html文件中使用模板语言

1. 普通变量

  1. {{var}}

调用数组元素:(圆点加下标)

  1. list1 = [1,2,3]
  2. {{list.0}}
  3. {{list.1}}
  4. {{list.2}}

调用字典元素: (圆点加键值)

  1. dict1 = {"k1":"v1","k2":"v2"}
  2. {{dict1.k1}}
  3. {{dict1.k2}}
  1. # 1.句点用于访问列表索引:
  2.  
  3. >>> from django.template import Template, Context
  4. >>> t = Template('Item 2 is {{ items.2 }}.')
  5. >>> c = Context({'items': ['apples', 'bananas', 'carrots']})
  6. >>> t.render(c)
  7. 'Item 2 is carrots.'
  8.  
  9. # 2.句点用于访问字典索引:
  10.  
  11. >>> from django.template import Template, Context
  12. >>> person = {'name': 'Sally', 'age': ''}
  13. >>> t = Template('{{ person.name }} is {{ person.age }} years old.')
  14. >>> c = Context({'person': person})
  15. >>> t.render(c)
  16. 'Sally is 43 years old.'
  17.  
  18. #3.句点访问对象属性,如 Python 的 datetime.date 对象有year,month 和 day 几个属性,可#以在模板中使用句点来访问这些属性:
  19.  
  20. >>> from django.template import Template, Context
  21. >>> import datetime
  22. >>> d = datetime.date(1993, 5, 2)
  23. >>> d.year
  24. 1993
  25. >>> d.month
  26. 5
  27. >>> d.day
  28. 2
  29. >>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.')
  30. >>> c = Context({'date': d})
  31. >>> t.render(c)
  32. 'The month is 5 and the year is 1993.'
  33.  
  34. # 4.句点通过实例变量访问自定义类属性,这个方法适用于任意的对象。
  35.  
  36. >>> from django.template import Template, Context
  37. >>> class Person(object):
  38. ... def __init__(self, first_name, last_name):
  39. ... self.first_name, self.last_name = first_name, last_name
  40. >>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.')
  41. >>> c = Context({'person': Person('John', 'Smith')})
  42. >>> t.render(c)
  43. 'Hello, John Smith.'
  44.  
  45. #5. 句点也可以用来引用对象的方法。例如,每个 Python 字符串都有 upper() 和 isdigit()方法,你在模板中可以使用同样的句点语法来调用它们:
  46. >>> from django.template import Template, Context
  47. >>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}')
  48. >>> t.render(Context({'var': 'hello'}))
  49. 'hello -- HELLO -- False'
  50. >>> t.render(Context({'var': ''}))
  51. '123 -- 123 -- True'
  1. 0# 语法格式:{{obj|filter:param}}
  2. #1. add :给变量加上相应的值
  3. #2. addslashes :给变量中的引号前加上斜线
  4. #3. capfirst:首字母大写
  5. #4. cut:从字符串中移除指定的字符
  6. #5. date:格式化日期字符串
  7. #6. default :如果值是False,就替换成设置的默认值,否则就是用本来的值
  8. #7. default_if_none: 如果值是None,就替换成设置的默认值,否则就使用本来的值
  9. #实例:
  10.  
  11. #value1="aBcDe"
  12. {{ value1|upper }}<br>
  13.  
  14. #value2=5
  15. {{ value2|add:3 }}<br>
  16.  
  17. #value3='he llo wo r ld'
  18. {{ value3|cut:' ' }}<br>
  19.  
  20. #import datetime
  21. #value4=datetime.datetime.now()
  22. {{ value4|date:'Y-m-d' }}<br>
  23.  
  24. #value5=[]
  25. {{ value5|default:'空的' }}<br>
  26.  
  27. #value6='<a href="#">跳转</a>'
  28.  
  29. {{ value6 }}
  30.  
  31. {% autoescape off %}
  32. {{ value6 }}
  33. {% endautoescape %}
  34.  
  35. {{ value6|safe }}<br>
  36.  
  37. {{ value6|striptags }}
  38.  
  39. #value7='1234'
  40. {{ value7|filesizeformat }}<br>
  41. {{ value7|first }}<br>
  42. {{ value7|length }}<br>
  43. {{ value7|slice:":-1" }}<br>
  44.  
  45. #value8='http://www.baidu.com/?a=1&b=3'
  46. {{ value8|urlencode }}<br>
  47. value9='hello I am yuan'

模板变量的filter使用

2. if语句

{% if %}标签判断一个条件表达式,如果是“true”,即它存在、不为空并且不是false的boolean值,系统则会显示{% if %}和{% endif %}间的所有内容

  1. {% if 判断 %}
  2. ......
  3. {% else %}
  4. ......
  5. {% endif %}

3. for循环

{% for %}标签按顺序遍历一个序列中的各个元素,每次循环模板系统都会渲染{% for %}和{% endfor %}之间的所有内容

  1. {% for i in data %}
  2. ......
  3. {% endfor %}

django内置特殊的用于for循环的变量:

  1. forloop.counter
  2. forloop.counter0
  3. forloop.first
  4. forloop.last
  1. forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1
  2.  
  3. {% for item in todo_list %}
  4. <p>{{ forloop.counter }}: {{ item }}</p>
  5. {% endfor %}
  6. forloop.counter0 类似于forloop.counter,但它是从0开始计数,第一次循环设为0
  7. forloop.revcounter
  8. forloop.revcounter0
  9. forloop.first当第一次循环时值为True,在特别情况下很有用:
  10. #{% empty %}判断列表是否为空
  11.  
  12. {{li }}
  13. {% for i in li %}
  14. <li>{{ forloop.counter0 }}----{{ i }}</li>
  15. {% empty %}
  16. <li>this is empty!</li>
  17. {% endfor %}
  18.  
  19. # [11, 22, 33, 44, 55]
  20. # 0----11
  21. # 1----22
  22. # 2----33
  23. # 3----44
  24. # 4----55

4.特殊标签

(1) {%csrf_token%}:csrf_token标签,用于防治跨站攻击验证。注意如果你在view的index里用的是render_to_response方法,该标签不会生效

其实,{%csrf_token%}是会生成一个input标签,和其他表单标签一起提交给后台。

(2) {% url  '路由别名' %}:  引用路由配置的地址

  1. <form action="{% url "bieming"%}" >
  2. <input type="text">
  3. <input type="submit"value="提交">
  4. {%csrf_token%}
  5. </form>

(3) {% with %}:用更简单的变量名替代复杂的变量名

  1. {% with total=fhjsaldfhjsdfhlasdfhljsdal %} {{ total }} {% endwith %}

(4) {% verbatim %}: 禁止render

  1. {% verbatim %}
  2. {{ hello }}
  3. {% endverbatim %}

(5) {% load %}: 加载标签库

5. 内置函数

  1. lower first last divisibleby 等等。例如:
  2. {{ AAA”|lower}}
  3. 使用管道符引用函数名,左边的‘AAA’自动当作参数传递给lower函数
  4. 又或:判断当前循环的次数是否能被2整除
  5. {% if forloop.counter0|divisibleby:"2" %}
  6. <tr class="success">
  7. {% else %}
  8. <tr>
  9. {% endif %}

6. 自定义filter和simple_tag

1.在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag.

2.在app中创建templatetags模块(必须的)

3.创建任意 .py 文件,如:my_tags.py

4.在使用自定义simple_tag和filter的html文件中导入之前创建的 my_tags.py :{% load my_tags %}

5.使用simple_tag和filter(如何调用)

  1. /*-------------------my_tag.py-----------------*/
  2. from django import template
  3. from django.utils.safestring import mark_safe
  4. register = template.Library() #register的名字是固定的,不可改变
  5. @register.filter #只能传递一个参数,能用在逻辑控制语句中
  6. def filter_multi(v1,v2):
  7. return v1 * v2
  8.  
  9. @register.simple_tag #参数不限,但不能用在逻辑控制语句中
  10. def simple_tag_multi(v1,v2):
  11. return v1 * v2
  12.  
  13. /*---------------使用my_tag的html------------*/
  14. {% load my_tag %}
  15. # num=12
  16. {{ num|filter_multi:2 }} #调用自定义filter24
  17. {% simple_tag_multi 2 5 %}#调用自定义simple_tag

自定义filter和simple_tag函数

7. 继承模板

  1. {% extends "xxxx.html" %}

8. 重写模板

  1. 在母版和子版式中使用同样的:
  2. {% block 取个名字 %}
  3. (每个子版专属的代码)
  4. {% endbloack %}

9.导入html代码

  1. {% include "xxx.html" %}

与继承模板不同的是,导入的是xxx.html的完全代码,因此xxx.html中最好没有头部,title等代码,只有实际的功能代码。

四、models

1.数据库配置

django默认支持sqlite,mysql, oracle,postgresql数据库。

1.sqlite: django默认使用sqlite数据库,默认自带sqlite的数据库驱动 , 引擎名称:django.db.backends.sqlite3

2.mysql:引擎名称:django.db.backends.mysql

3.常用的mysql驱动:MySQLdb(又名mysql_python,不支持python3.+,由pymysql替代),mysqlclient,mysql_connector_python(纯python的mysql驱动程序,由oracle官方维护)

4.在django的项目中会默认使用sqlite数据库,在settings里有如下设置

  1. DATABASES = {
  2. 'default': {
  3. 'ENGINE': 'django.db.backends.sqlite3',
  4. 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
  5. }
  6. }

如果我们想要更改数据库,需要修改如下

  1. DATABASES = {
  2. 'default': {
  3. 'ENGINE': 'django.db.backends.mysql',
  4. 'NAME': 'mydatabase',
  5. 'USER': 'mydatabaseuser',
  6. 'PASSWORD': 'mypassword',
  7. 'HOST': '127.0.0.1',
  8. 'PORT': '',
  9. }
  10. }

NAME即数据库的名字,在mysql连接前该数据库必须已经创建,而上面的sqlite数据库下的db.sqlite3则是项目自动创建 ;

USER和PASSWORD分别是数据库的用户名和密码。 设置完后,再启动我们的Django项目前,我们需要激活我们的mysql。

然后,启动项目会报错:no module named MySQLdb ,这是因为django默认你导入的驱动是MySQLdb,可是MySQLdb

对于py3有很大问题,所以我们需要的驱动是PyMySQL 所以,我们只需要找到项目名文件下的__init__,在里面写入:

import pymysql pymysql.install_as_MySQLdb() 问题解决!

如果使用的驱动是mysql官网驱动:mysql_connector_python,则database settings中需要将engine设置为

'ENGINE': 'mysql.connector.django',然后改驱动会自动适配Django

5.通过Django两条命令创建数据库和表

python3 manage.py makemigrations

python3 manage.py migrate

2. Django ORM语法

(1)基础类型

  1. from django.db import models
  2.  
  3. class userinfo(models.Model):
  4. name = models.CharField(max_length=30)
  5. email = models.EmailField()
  6. memo = models.TextField()

(2)连表类型

  1. 一对多:models.ForeignKey("其他表")
  2. 多对多:models.ManyToManyField("其他表")
  3. 一对一:models.OneToOneField("其他表")

(3) 字段类型

  1. <1> CharField
  2. #字符串字段, 用于较短的字符串.
  3. #CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的最大字符数.
  4.  
  5. <2> IntegerField
  6. #用于保存一个整数.
  7.  
  8. <3> FloatField
  9. # 一个浮点数. 必须 提供两个参数:
  10. #
  11. # 参数 描述
  12. # max_digits 总位数(不包括小数点和符号)
  13. # decimal_places 小数位数
  14. # 举例来说, 要保存最大值为 999 (小数点后保存2位),你要这样定义字段:
  15. #
  16. # models.FloatField(..., max_digits=5, decimal_places=2)
  17. # 要保存最大值一百万(小数点后保存10位)的话,你要这样定义:
  18. #
  19. # models.FloatField(..., max_digits=19, decimal_places=10)
  20. # admin 用一个文本框(<input type="text">)表示该字段保存的数据.
  21.  
  22. <4> AutoField
  23. # 一个 IntegerField, 添加记录时它会自动增长. 你通常不需要直接使用这个字段;
  24. # 自定义一个主键:my_id=models.AutoField(primary_key=True)
  25. # 如果你不指定主键的话,系统会自动添加一个主键字段到你的 model.
  26.  
  27. <5> BooleanField
  28. # A true/false field. admin 用 checkbox 来表示此类字段.
  29.  
  30. <6> TextField
  31. # 一个容量很大的文本字段.
  32. # admin 用一个 <textarea> (文本区域)表示该字段数据.(一个多行编辑框).
  33.  
  34. <7> EmailField
  35. # 一个带有检查Email合法性的 CharField,不接受 maxlength 参数.
  36.  
  37. <8> DateField
  38. # 一个日期字段. 共有下列额外的可选参数:
  39. # Argument 描述
  40. # auto_now 当对象被保存时,自动将该字段的值设置为当前时间.通常用于表示 "last-modified" 时间戳.
  41. # auto_now_add 当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间.
  42. #(仅仅在admin中有意义...)
  43.  
  44. <9> DateTimeField
  45. # 一个日期时间字段. 类似 DateField 支持同样的附加选项.
  46.  
  47. <10> ImageField
  48. # 类似 FileField, 不过要校验上传对象是否是一个合法图片.#它有两个可选参数:height_field和width_field,
  49. # 如果提供这两个参数,则图片将按提供的高度和宽度规格保存.
  50. <11> FileField
  51. # 一个文件上传字段.
  52. #要求一个必须有的参数: upload_to, 一个用于保存上载文件的本地文件系统路径. 这个路径必须包含 strftime #formatting,
  53. #该格式将被上载文件的 date/time
  54. #替换(so that uploaded files don't fill up the given directory).
  55. # admin 用一个<input type="file">部件表示该字段保存的数据(一个文件上传部件) .
  56.  
  57. #注意:在一个 model 中使用 FileField 或 ImageField 需要以下步骤:
  58. #(1)在你的 settings 文件中, 定义一个完整路径给 MEDIA_ROOT 以便让 Django在此处保存上传文件.
  59. # (出于性能考虑,这些文件并不保存到数据库.) 定义MEDIA_URL 作为该目录的公共 URL. 要确保该目录对
  60. # WEB服务器用户帐号是可写的.
  61. #(2) 在你的 model 中添加 FileField 或 ImageField, 并确保定义了 upload_to 选项,以告诉 Django
  62. # 使用 MEDIA_ROOT 的哪个子目录保存上传文件.你的数据库中要保存的只是文件的路径(相对于 MEDIA_ROOT).
  63. # 出于习惯你一定很想使用 Django 提供的 get_<#fieldname>_url 函数.举例来说,如果你的 ImageField
  64. # 叫作 mug_shot, 你就可以在模板中以 {{ object.#get_mug_shot_url }} 这样的方式得到图像的绝对路径.
  65.  
  66. <12> URLField
  67. # 用于保存 URL. 若 verify_exists 参数为 True (默认), 给定的 URL 会预先检查是否存在( 即URL是否被有效装入且
  68. # 没有返回404响应).
  69. # admin 用一个 <input type="text"> 文本框表示该字段保存的数据(一个单行编辑框)
  70.  
  71. <13> NullBooleanField
  72. # 类似 BooleanField, 不过允许 NULL 作为其中一个选项. 推荐使用这个字段而不要用 BooleanField 加 null=True 选项
  73. # admin 用一个选择框 <select> (三个可选择的值: "Unknown", "Yes" 和 "No" ) 来表示这种字段数据.
  74.  
  75. <14> SlugField
  76. # "Slug" 是一个报纸术语. slug 是某个东西的小小标记(短签), 只包含字母,数字,下划线和连字符.#它们通常用于URLs
  77. # 若你使用 Django 开发版本,你可以指定 maxlength. 若 maxlength 未指定, Django 会使用默认长度: 50. #在
  78. # 以前的 Django 版本,没有任何办法改变50 这个长度.
  79. # 这暗示了 db_index=True.
  80. # 它接受一个额外的参数: prepopulate_from, which is a list of fields from which to auto-#populate
  81. # the slug, via JavaScript,in the object's admin form: models.SlugField
  82. # (prepopulate_from=("pre_name", "name"))prepopulate_from 不接受 DateTimeFields.
  83.  
  84. <13> XMLField
  85. #一个校验值是否为合法XML的 TextField,必须提供参数: schema_path, 它是一个用来校验文本的 RelaxNG schema #的文件系统路径.
  86.  
  87. <14> FilePathField
  88. # 可选项目为某个特定目录下的文件名. 支持三个特殊的参数, 其中第一个是必须提供的.
  89. # 参数 描述
  90. # path 必需参数. 一个目录的绝对文件系统路径. FilePathField 据此得到可选项目.
  91. # Example: "/home/images".
  92. # match 可选参数. 一个正则表达式, 作为一个字符串, FilePathField 将使用它过滤文件名.
  93. # 注意这个正则表达式只会应用到 base filename 而不是
  94. # 路径全名. Example: "foo.*\.txt^", 将匹配文件 foo23.txt 却不匹配 bar.txt 或 foo23.gif.
  95. # recursive可选参数.要么 True 要么 False. 默认值是 False. 是否包括 path 下面的全部子目录.
  96. # 这三个参数可以同时使用.
  97. # match 仅应用于 base filename, 而不是路径全名. 那么,这个例子:
  98. # FilePathField(path="/home/images", match="foo.*", recursive=True)
  99. # ...会匹配 /home/images/foo.gif 而不匹配 /home/images/foo/bar.gif
  100.  
  101. <15> IPAddressField
  102. # 一个字符串形式的 IP 地址, (i.e. "24.124.1.30").
  103. <16># CommaSeparatedIntegerField
  104. # 用于存放逗号分隔的整数值. 类似 CharField, 必须要有maxlength参数.

字段类型

  1. AutoField(Field)
  2. - int自增列,必须填入参数 primary_key=True
  3.  
  4. BigAutoField(AutoField)
  5. - bigint自增列,必须填入参数 primary_key=True
  6.  
  7. 注:当model中如果没有自增列,则自动会创建一个列名为id的列
  8. from django.db import models
  9.  
  10. class UserInfo(models.Model):
  11. # 自动创建一个列名为id的且为自增的整数列
  12. username = models.CharField(max_length=32)
  13.  
  14. class Group(models.Model):
  15. # 自定义自增列
  16. nid = models.AutoField(primary_key=True)
  17. name = models.CharField(max_length=32)
  18.  
  19. SmallIntegerField(IntegerField):
  20. - 小整数 -32768 32767
  21.  
  22. PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
  23. - 正小整数 0 32767
  24. IntegerField(Field)
  25. - 整数列(有符号的) -2147483648 2147483647
  26.  
  27. PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
  28. - 正整数 0 2147483647
  29.  
  30. BigIntegerField(IntegerField):
  31. - 长整型(有符号的) -9223372036854775808 9223372036854775807
  32.  
  33. BooleanField(Field)
  34. - 布尔值类型
  35.  
  36. NullBooleanField(Field):
  37. - 可以为空的布尔值
  38.  
  39. CharField(Field)
  40. - 字符类型
  41. - 必须提供max_length参数, max_length表示字符长度
  42.  
  43. TextField(Field)
  44. - 文本类型
  45.  
  46. EmailField(CharField):
  47. - 字符串类型,Django Admin以及ModelForm中提供验证机制
  48.  
  49. IPAddressField(Field)
  50. - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制
  51.  
  52. GenericIPAddressField(Field)
  53. - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4Ipv6
  54. - 参数:
  55. protocol,用于指定Ipv4Ipv6 'both',"ipv4","ipv6"
  56. unpack_ipv4 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启此功能,需要protocol="both"
  57.  
  58. URLField(CharField)
  59. - 字符串类型,Django Admin以及ModelForm中提供验证 URL
  60.  
  61. SlugField(CharField)
  62. - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)
  63.  
  64. CommaSeparatedIntegerField(CharField)
  65. - 字符串类型,格式必须为逗号分割的数字
  66.  
  67. UUIDField(Field)
  68. - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证
  69.  
  70. FilePathField(Field)
  71. - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
  72. - 参数:
  73. path, 文件夹路径
  74. match=None, 正则匹配
  75. recursive=False, 递归下面的文件夹
  76. allow_files=True, 允许文件
  77. allow_folders=False, 允许文件夹
  78.  
  79. FileField(Field)
  80. - 字符串,路径保存在数据库,文件上传到指定目录
  81. - 参数:
  82. upload_to = "" 上传文件的保存路径
  83. storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
  84.  
  85. ImageField(FileField)
  86. - 字符串,路径保存在数据库,文件上传到指定目录
  87. - 参数:
  88. upload_to = "" 上传文件的保存路径
  89. storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
  90. width_field=None, 上传图片的高度保存的数据库字段名(字符串)
  91. height_field=None 上传图片的宽度保存的数据库字段名(字符串)
  92.  
  93. DateTimeField(DateField)
  94. - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
  95.  
  96. DateField(DateTimeCheckMixin, Field)
  97. - 日期格式 YYYY-MM-DD
  98.  
  99. TimeField(DateTimeCheckMixin, Field)
  100. - 时间格式 HH:MM[:ss[.uuuuuu]]
  101.  
  102. DurationField(Field)
  103. - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型
  104.  
  105. FloatField(Field)
  106. - 浮点型
  107.  
  108. DecimalField(Field)
  109. - 10进制小数
  110. - 参数:
  111. max_digits,小数总长度
  112. decimal_places,小数位长度
  113.  
  114. BinaryField(Field)
  115. - 二进制类型

字段类型

(4)参数类型

  1. <1> null : 数据库中字段是否可以为空
  2.  
  3. <2> blank: django的 Admin 中添加数据时是否可允许空值
  4.  
  5. <3> default:设定缺省值
  6.  
  7. <4> editable:如果为假,admin模式下将不能改写。缺省为真
  8.  
  9. <5> primary_key:设置主键,如果没有设置django创建表时会自动加上:
  10. id = meta.AutoField('ID', primary_key=True)
  11. primary_key=True implies blank=False, null=False and unique=True. Only one
  12. primary key is allowed on an object.
  13.  
  14. <6> unique:数据唯一
  15.  
  16. <7> verbose_name: Admin中字段的显示名称
  17.  
  18. <8> help_text: Admin中该字段的提示信息
  19.  
  20. <9> validator_list: 有效性检查。非有效产生 django.core.validators.ValidationError 错误
  21.  
  22. <10> db_column: 数据库中字段的列名
  23.  
  24. <11>db_index : 数据库中字段是否可以建立索引,如果为真将为此字段创建索引
  25.  
  26. <12>choices:一个用来选择值的2维元组。第一个值是实际存储的值,第二个用来方便进行选择。
  27. 如SEX_CHOICES= (( ‘F’,'Female’),(‘M’,'Male’),)
  28. gender = models.CharField(max_length=2,choices = SEX_CHOICES)
  29.  
  30. <13>error_messages: 自定义错误信息(字典类型),从而定制想要显示的错误信息;
  31. 字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
  32. 如:{'null': "不能为空.", 'invalid': '格式错误'}

参数类型

(5)多表关系及参数

  1. ForeignKey(ForeignObject) # ForeignObject(RelatedField)
  2. to, # 要进行关联的表名
  3. to_field=None, # 要关联的表中的字段名称
  4. on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为
  5. - models.CASCADE,删除关联数据,与之关联也删除
  6. - models.DO_NOTHING,删除关联数据,引发错误IntegrityError
  7. - models.PROTECT,删除关联数据,引发错误ProtectedError
  8. - models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
  9. - models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
  10. - models.SET,删除关联数据,
  11. a. 与之关联的值设置为指定值,设置:models.SET(值)
  12. b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
  13.  
  14. def func():
  15. return 10
  16.  
  17. class MyModel(models.Model):
  18. user = models.ForeignKey(
  19. to="User",
  20. to_field="id"
  21. on_delete=models.SET(func),)
  22. related_name=None, # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
  23. related_query_name=None, # 反向操作时,使用的连接前缀,用于替换【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
  24. limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件:
  25. # 如:
  26. - limit_choices_to={'nid__gt': 5}
  27. - limit_choices_to=lambda : {'nid__gt': 5}
  28.  
  29. from django.db.models import Q
  30. - limit_choices_to=Q(nid__gt=10)
  31. - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
  32. - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
  33. db_constraint=True # 是否在数据库中创建外键约束
  34. parent_link=False # 在Admin中是否显示关联数据
  35.  
  36. OneToOneField(ForeignKey)
  37. to, # 要进行关联的表名
  38. to_field=None # 要关联的表中的字段名称
  39. on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为
  40.  
  41. ###### 对于一对一 ######
  42. # 1. 一对一其实就是 一对多 + 唯一索引
  43. # 2.当两个类之间有继承关系时,默认会创建一个一对一字段
  44. # 如下会在A表中额外增加一个c_ptr_id列且唯一:
  45. class C(models.Model):
  46. nid = models.AutoField(primary_key=True)
  47. part = models.CharField(max_length=12)
  48.  
  49. class A(C):
  50. id = models.AutoField(primary_key=True)
  51. code = models.CharField(max_length=1)
  52.  
  53. ManyToManyField(RelatedField)
  54. to, # 要进行关联的表名
  55. related_name=None, # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
  56. related_query_name=None, # 反向操作时,使用的连接前缀,用于替换【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
  57. limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件:
  58. # 如:
  59. - limit_choices_to={'nid__gt': 5}
  60. - limit_choices_to=lambda : {'nid__gt': 5}
  61.  
  62. from django.db.models import Q
  63. - limit_choices_to=Q(nid__gt=10)
  64. - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
  65. - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
  66. symmetrical=None, # 仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段
  67. # 做如下操作时,不同的symmetrical会有不同的可选字段
  68. models.BB.objects.filter(...)
  69.  
  70. # 可选字段有:code, id, m1
  71. class BB(models.Model):
  72.  
  73. code = models.CharField(max_length=12)
  74. m1 = models.ManyToManyField('self',symmetrical=True)
  75.  
  76. # 可选字段有: bb, code, id, m1
  77. class BB(models.Model):
  78.  
  79. code = models.CharField(max_length=12)
  80. m1 = models.ManyToManyField('self',symmetrical=False)
  81.  
  82. through=None, # 自定义第三张表时,使用字段用于指定关系表
  83. through_fields=None, # 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表
  84. from django.db import models
  85.  
  86. class Person(models.Model):
  87. name = models.CharField(max_length=50)
  88.  
  89. class Group(models.Model):
  90. name = models.CharField(max_length=128)
  91. members = models.ManyToManyField(
  92. Person,
  93. through='Membership',
  94. through_fields=('group', 'person'),
  95. )
  96.  
  97. class Membership(models.Model):
  98. group = models.ForeignKey(Group, on_delete=models.CASCADE)
  99. person = models.ForeignKey(Person, on_delete=models.CASCADE)
  100. inviter = models.ForeignKey(
  101. Person,
  102. on_delete=models.CASCADE,
  103. related_name="membership_invites",
  104. )
  105. invite_reason = models.CharField(max_length=64)
  106. db_constraint=True, # 是否在数据库中创建外键约束
  107. db_table=None, # 默认创建第三张表时,数据库中表的名称
  108.  
  109. unique_together #联合唯一,自己创建多对多第三章表时,加上此约束后,创建的表与默认创建的表相同
  110. #class UserToTag(models.Model):
  111. # # nid = models.AutoField(primary_key=True)
  112. # u = models.ForeignKey(to='User')
  113. # t = models.ForeignKey(to='Tag')
  114. # ctime = models.DateField()
  115. # class Meta:
  116. # unique_together=[
  117. # ('u','t'),
  118. # ]

3. Django ORM表操作

(1)单表的增,删,改,查

  1. /*--------------------------index.html-------------------------*/
  2.  
  3. <!DOCTYPE html>
  4. <html lang="en">
  5. <head>
  6. <meta charset="UTF-8">
  7. <title>Title</title>
  8. <style>
  9. * {
  10. margin: 0;
  11. padding: 0
  12. }
  13. .head{
  14. line-height: 40px;
  15. background-color: green;
  16. color: white;
  17. text-align: center;
  18.  
  19. }
  20.  
  21. </style>
  22. </head>
  23. <body>
  24. <div class="outer">
  25. <div class="head">标题</div>
  26. <div class="content">
  27. <a href="/addbook/">添加书籍</a>
  28. <a href="/update/">修改书籍</a>
  29. <a href="/delete/">删除书籍</a>
  30. <a href="/select/">查询书籍</a>
  31. </div>
  32. <hr>
  33. <div class="queryResult">
  34. {% for book in book_list %}
  35. <div>
  36. <p>{{ book.title }} {{ book.author }} {{ book.price }}</p>
  37. </div>
  38. {% endfor %}
  39. </div>
  40. </div>
  41.  
  42. <script src="/static/jquery-3.1.1.js"></script>
  43. </body>
  44. </html>
  45.  
  46. /*-----------------------models.py---------------------------*/
  47.  
  48. from django.db import models
  49.  
  50. # Create your models here.
  51. class UserInfo(models.Model):
  52. user=models.CharField(max_length=32)
  53. pwd=models.CharField(max_length=32)
  54. class book(models.Model):
  55. author=models.CharField(max_length=32)
  56. price=models.IntegerField()
  57. date=models.DateField()
  58. title=models.CharField(max_length=100)
  59. def __str__(self):
  60. return self.title
  61.  
  62. /*-----------------------view.py------------------------------*/
  63.  
  64. from django.shortcuts import render,HttpResponse
  65. from blog.models import *
  66.  
  67. # Create your views here.
  68. def index(request):
  69. return render(request,"index.html")
  70. #-----------------增-------------------
  71. def addbook(request):
  72. #法一
  73. book.objects.create(author="马尔克斯",price=88,date="2014-3-3",title="百年孤独")
  74. #法二
  75. b=book(author="狄更斯",price=66,date="2011-2-4",title="艰难时世")
  76. b.save()
  77. return HttpResponse("书籍信息添加成功")
  78. #-----------------删-------------------
  79. def delete(request):
  80. book.objects.filter(id=9).delete()
  81. return HttpResponse("书籍信息删除成功")
  82. #-----------------改---------------------
  83. def update(request):
  84. #法一
  85. book.objects.filter(author="高尔基").update(price=99)
  86. #法二
  87. b=book.objects.get(author="狄更斯")
  88. b.price=77
  89. b.save()
  90. return HttpResponse("书籍信息修改成功")
  91. #------------------------------------------
  92. #<1> 法一修改不能用get的原因是:update是QuerySet对象的方法,
  93. # get返回的是一个model对象,它没有update方法,而filter返回的是一个
  94. # QuerySet对象(filter里面的条件可能有多个条件符合,比如name='alvin',
  95. # 可能有两个name='alvin'的行数据)。
  96. #<2>update方法直接设定对应字段属性,save方法会将所有属性重新设定一遍,效率低,
  97. # 故推荐使用update方法
  98. #--------------------------------------------

练习所用book表单

每次对表的操作想看见对应的sql实现语句,可在settings.py里加入日志记录配置

  1. LOGGING = {
  2. 'version': 1,
  3. 'disable_existing_loggers': False,
  4. 'handlers': {
  5. 'console':{
  6. 'level':'DEBUG',
  7. 'class':'logging.StreamHandler',
  8. },
  9. },
  10. 'loggers': {
  11. 'django.db.backends': {
  12. 'handlers': ['console'],
  13. 'propagate': True,
  14. 'level':'DEBUG',
  15. },
  16. }
  17. }

查询API

  1. # 查询相关API:
  2.  
  3. # <1>filter(**kwargs): 它包含了与所给筛选条件相匹配的对象
  4.  
  5. # <2>all(): 查询所有结果
  6.  
  7. # <3>get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。
  8.  
  9. #-----------下面的方法都是对查询的结果再进行处理:比如 objects.filter.values()--------
  10.  
  11. # <4>values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列
  12.  
  13. # <5>exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象
  14.  
  15. # <6>order_by(*field): 对查询结果排序
  16.  
  17. # <7>reverse(): 对查询结果反向排序
  18.  
  19. # <8>distinct(): 从返回结果中剔除重复纪录
  20.  
  21. # <9>values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
  22.  
  23. # <10>count(): 返回数据库中匹配查询(QuerySet)的对象数量。
  24.  
  25. # <11>first(): 返回第一条记录
  26.  
  27. # <12>last(): 返回最后一条记录
  28.  
  29. # <13>exists(): 如果QuerySet包含数据,就返回True,否则返回False。
  30.  
  31. #扩展查询,有时候DJANGO的查询API不能方便的设置查询条件,提供了另外的扩展查询方法extra:
  32. #extra(select=None, where=None, params=None, tables=None,order_by=None, select_params=None
  33.  
  34. (1) Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
  35.  
  36. (2) Blog.objects.extra(
  37. select=SortedDict([('a', '%s'), ('b', '%s')]),
  38. select_params=('one', 'two'))
  39.  
  40. (3) q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
  41. q = q.extra(order_by = ['-is_recent'])
  42.  
  43. (4) Entry.objects.extra(where=['headline=%s'], params=['Lennon'])

查询API

  1. def select(request):
  2. # book_list=book.objects.all()
  3. # book.objects.all()支持切片操作
  4. # book_list = book.objects.all()[::2]#切片
  5. # book_list = book.objects.all()[::-1]#切片
  6. # book_list = book.objects.first()
  7. # book_list = book.objects.last()
  8. # book_list = book.objects.get(id=2) # 只能取出一条记录时才不报错,取出的是单个元素,不能进行循环
  9. # ret1=book.objects.filter(author="高尔基").values("title","price")
  10. # ret2=book.objects.filter(author="yuan").values_list("name","price")
  11. # book_list=book.objects.exclude(author="yuan").values("name","price")
  12. # book_list= book.objects.all().values("name").distinct()
  13. # book_count= book.objects.all().values("name").distinct().count()
  14. # print("ret1:",ret1)
  15. # 万能的 __
  16. book_list=book.objects.filter(price__gt=50).values("name","price")#price__gt=50代表价格大于50
  17. # book_list = book.objects.filter(name__contains="P").values_list("name", "price")
  18. return render(request,"index.html",{"book_list":book_list})

查询API的使用

(2)一对多表的增、删、改、查

练习所用表单

book表

author表

publish表

book_author表

  1. /*---------------------------models.py---------------------*/
  2. from django.db import models
  3.  
  4. # Create your models here.
  5. class book(models.Model):
  6. author=models.CharField(max_length=32)
  7. price=models.IntegerField()
  8. date=models.DateField()
  9. title=models.CharField(max_length=100)
  10. publish=models.ForeignKey("Publish",on_delete=models.CASCADE)
  11. def __str__(self):
  12. return self.title
  13. class Publish(models.Model):
  14. name=models.CharField(max_length=100)
  15. city=models.CharField(max_length=100)
  16.  
  17. /*--------------------------views.py---------------------------*/
  18.  
  19. def addbook(request):
  20. #一对多
  21. #法一由于绑定一对多的字段,比如publish,存到数据库中的字段名叫publish_id,所以我们可以直接给这个
  22. #字段设定对应值
  23. #book.objects.create(author="马尔克斯",price=88,date="2014-3-3",title="百年孤独",publish_id=2)
  24. #法二
  25. #<1>先获取要绑定的Publisher对象:
  26. #pub_obj = Publish.objects.get(id=2)
  27. #print("-------pub_obj:",pub_obj)
  28. #<2>将 publish_id=2 改为 publish=pub_obj
  29. #book.objects.create(author="马尔克斯",price=88,date="2014-1-3",title="霍乱时期的爱情",publish=pub_obj)
  30.  
  31. return HttpResponse("书籍信息添加成功")
  32.  
  33. def select(request):
  34. #法一 通过对象
  35. book_obj=book.objects.get(title="童年")
  36. #book_obj.publish是一个书籍对象对应的一个publish object ,数据类型是models下publish类的一条与name="童年"的publish_id相同的实例对象,
  37. #可以通过调用对象属性查看相应信息
  38. # print(book_obj.publish.name)
  39. # print(book_obj.publish.city)
  40. #需求查询吉林出版社出版的所有书籍
  41. # pub_obj=Publish.objects.filter(name="吉林出版社")[0]
  42. # print("pub_obj:",pub_obj)
  43. # print(pub_obj.book_set.all().values("title","price"))
  44. # 法二通过filter和values的双下滑线语法查询
  45. # 需求:查询所有安徽人民出版社出版的书籍
  46. # ret = book.objects.filter(publish__name="安徽人民出版社").values("title", "price")
  47. # print("ret:", ret)
  48. #需求:查询童年这本书出版社的名字
  49. #ret=Publish.objects.filter(book__title="童年").values('name')
  50. #ret=book.objects.filter(title="童年").values("publish__name")
  51. #需求:查询出版社在北京的出版社出版的书籍名字
  52. #ret=book.objects.filter(publish__city="北京").values("title")
  53. #需求:查询在2014年上半年出版的书对应的出版社名字
  54. ret=book.objects.filter(date__gt="2014-01-01",date__lt="2014-07-01").values("publish__name")
  55. print("ret:", ret)
  56. return render(request,"书籍修改成功")

一对多增,删,改,查

(3)多对多表的增、删、改、查

  1. /*-----------------------models.py---------------------------------*/
  2. from django.db import models
  3.  
  4. # Create your models here.
  5. class book(models.Model):
  6. #author=models.CharField(max_length=32)
  7. price=models.IntegerField()
  8. date=models.DateField()
  9. title=models.CharField(max_length=100)
  10. publish=models.ForeignKey("Publish",on_delete=models.CASCADE)
  11. #author= models.ManyToManyField("Author")#自己创建中间表,不用ManyToManyField字段参数类型
  12. def __str__(self):
  13. return self.title
  14. class Publish(models.Model):
  15. name=models.CharField(max_length=100)
  16. city=models.CharField(max_length=100)
  17. def __str__(self):
  18. return self.name
  19. class Author(models.Model):
  20. name=models.CharField(max_length=32)
  21. age=models.IntegerField(default=20)
  22. def __str__(self):
  23. return self.name
  24. class Book_Author(models.Model):
  25. book=models.ForeignKey("book",on_delete=models.CASCADE)
  26. author=models.ForeignKey("Author",on_delete=models.CASCADE)
  27.  
  28. /*---------------------------views.py---------------------------*/
  29. #创建多对多关系author= models.ManyToManyField("Author")(推荐)
  30.  
  31. /*-----------------------------增--------------------------------*/
  32. #多对多(ManyToManyField()):
  33.  
  34. author1=Author.objects.get(id=1)
  35. author2=Author.objects.filter(name='alvin')[0]
  36. book=book.objects.get(id=1)
  37. book.authors.add(author1,author2)
  38. #等同于:
  39. book.authors.add(*[author1,author2])
  40. book.authors.remove(*[author1,author2])
  41. #-------------------
  42. book=models.book.objects.filter(id__gt=1)
  43. authors=models.Author.objects.filter(id=1)[0]
  44. authors.book_set.add(*book)
  45. authors.book_set.remove(*book)
  46. #-------------------
  47. book.authors.add(1)
  48. book.authors.remove(1)
  49. authors.book_set.add(1)
  50. authors.book_set.remove(1)
  51.  
  52. #注意: 如果第三张表是通过models.ManyToManyField()自动创建的,那么绑定关系只有上面一种方式
  53. # 如果第三张表是自己创建的:
  54. class Book_Author(models.Model):
  55. author=models.ForeignKey("Author")
  56. book= models.ForeignKey("book")
  57. # 那么就还有一种方式:
  58. author_obj=models.Author.objects.filter(id=2)[0]
  59. book_obj =models.book.objects.filter(id=3)[0]
  60.  
  61. s=models.Book_Author.objects.create(author_id=1,book_id=2)
  62. s.save()
  63. s=models.book_Author(author=author_obj,book_id=1)
  64. s.save()
  65.  
  66. /*--------------------------------删--------------------------------*/
  67. #多对多:remove()和clear()方法
  68. #正向
  69. book_obj = models.book.objects.filter(id=1)
  70.  
  71. #删除第三张表中和id=1关联的所有关联信息
  72. book_obj.author.clear() #清空与book中id=1 关联的所有数据
  73. book.author.remove(2) #可以为id
  74. book.author.remove(*[1,2,3,4]) #可以为列表,前面加*
  75.  
  76. #反向
  77. author = models.Author.objects.filter(id=1)
  78. author.book_set.clear() #清空id=1 关联的所有数据
  79.  
  80. /*-------------------------------查--------------------------------*/
  81.  
  82. #多对多查询(ManyToManyField()):
  83. #ret=models.Book.objects.filter(title='Python').values('author__name')
  84. #print(ret)
  85. #ret=models.Book.objects.filter(author__name="alex").values('title')
  86. #print(ret)
  87. #ret=models.Author.objects.filter(book__title='Python').values('name','price')

(4)表操作总结

  1. 0.一对多,外键一定是建在'多'的那张表
  2. 1. 类代表数据库表
  3. 2. 类的对象代指数据库的一行记录
  4. 3. FK字段代指关联表中的一行数据(类的对象)
  5. 4. 自动生成的第三章表中命名为FK_id的字段代表的是对应关联表的id
  6. 5. ManyToMany字段,自动生成第三张表:依赖关联表对第三张表进行操作
  7. 6.一对多: 正向查询用"FK字段",反向查询用"小写类名_set",跨表用双下划线
  8. 7.多对多:正向查询用"M2M字段",其他同一对多,如果未自己创建第三章多对多关系表,无法直接用对象
  9. 8.数据库获取数据
  10. .all .filter 输出为[obj,obj],即一个个对象组成的列表
  11. .values 输出为[{},{}],即一个个字典组成的列表,字典中为所选字段的键值对
  12. .values_list 输出为[(),()],即一个个元组组成的列表,元组中为所选字段和对应的值
  1. """book包含字段: id price date title publish_id(ForeignKey) authors(ManyToManyField)"""
  2. #1. 类代表数据库表
  3. #2. 类的对象代指数据库的一行记录
  4. #3. FK字段代指关联表中的一行数据(类的对象)
  5. #4. 自动生成的第三章表中命名为FK_id的字段代表的是对应关联表的id
  6. #5. ManyToMany字段,自动生成第三张表:依赖关联表对第三张表进行操作
  7. #6. 正向查询用"FK字段",反向查询用"小写类名_set"
  8. #<1> ret = book.objects.all()
  9. #返回为QuerySet对象,对象由一个个book类的对象(即一条条记录)组成QuerySet列表
  10. #< QuerySet[ < book: bookobject(1) >, < book: bookobject(2) >, < book: bookobject(3) >, < book: book object(4) >, < book: bookobject(5) >,
  11. #< book: bookobject(6) >, < book: bookobject(7) >, < book: bookobject(8) >, < book: bookobject(9) >, < book: bookobject(10) >, < book: bookobject(11) >] >
  12. #在models book 加入下面两句,返回为:
  13. #def __str__(self):
  14. # return self.title
  15. #<QuerySet [<book: 战争与和平>, <book: 百年孤独>, <book: 巴黎圣母院>, <book: 童年>, <book: 霍乱时期的爱情>,
  16. # <book: 我们家的猫>, <book: 在人间>, <book: 我的大学>, <book: 艰难时世>, <book: 红与黑>, <book: python程序设计教程>]>
  17. #<2> 对通过ret = book.objects.all()拿到的QuerySet进行循环遍历
  18. # ret=book.objects.all()
  19. # for item in ret:
  20. # print(item.id,item.price,item.date,item.title,item.publish_id,item.publish.id)
  21. # #跨表
  22. # print(item.publish.id,item.publish.name,item.publish.city)
  23. #<3> 删除
  24. #pid=input("请输入出版社ID")
  25. #book.objects.filter(publish_id=pid).delete()#删除publish_id为对应输入id的book记录
  26. #pname=input("请输入出版社名字")
  27. #book.objects.filter(publish__name=pname).delete()#删除出版社为输入出版社名发布的所有book记录
  28. #<4> ret=book.objects.all().values("id","title")
  29. #返回QuerySet对象,对象由一个个所选字段组成的字典构成QuerySet列表
  30. #ret: < QuerySet[{'id': 1, 'title': '战争与和平'}, {'id': 2, 'title': '百年孤独'}, {'id': 3, 'title': '巴黎圣母院'},
  31. # {'id': 4,'title': '童年'}, {'id': 5, 'title': '霍乱时期的爱情'}, {'id': 6, 'title': '我们家的猫'}, {'id': 7, 'title': '在人间'},
  32. # {'id': 8,'title': '我的大学'}, {'id': 9, 'title': '艰难时世'}, {'id': 10, 'title': '红与黑'}, {'id': 11, 'title': 'python程序设计教程'}] >
  33. #<5> ret=book.objects.all().values_list("id","title")
  34. #返回QuerySet对象,对象由一个个所选字段值组成的元祖构成QuerySet列表
  35. #ret: <QuerySet [(1, '战争与和平'), (2, '百年孤独'), (3, '巴黎圣母院'), (4, '童年'), (5, '霍乱时期的爱情'),
  36. # (6, '我们家的猫'), (7, '在人间'), (8, '我的大学'), (9, '艰难时世'), (10, '红与黑'), (11, 'python程序设计教程')]>

(5)聚合查询

  1. from django.db.models import Avg,Min,Sum,Max
  2.  
  3. 从整个查询集生成统计值。比如,你想要计算所有在售书的平均价钱。Django的查询语法提供了一种方式描述所有
  4. 图书的集合。
  5.  
  6. >>> Book.objects.all().aggregate(Avg('price'))
  7. {'price__avg': 34.35}
  8.  
  9. aggregate()子句的参数描述了我们想要计算的聚合值,在这个例子中,是Book模型中price字段的平均值
  10.  
  11. aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的
  12. 标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。如果你想要为聚合值指定
  13. 一个名称,可以向聚合子句提供它:
  14. >>> Book.objects.aggregate(average_price=Avg('price'))
  15. {'average_price': 34.35}
  16.  
  17. 如果你也想知道所有图书价格的最大值和最小值,可以这样查询:
  18. >>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))
  19. {'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}

aggregate(*args,**kwargs)

(6)分组查询

  1. from django.db.models import Avg,Min,Sum,Max
  2. #必须导入上面聚类函数,否则会报错
  3. ret=book.objects.values("publish__name").annotate(Min('price'))
  4. #<QuerySet [{'publish__name': '北京出版社', 'price__min': 44},
  5. # {'publish__name': '安徽人民出版社', 'price__min': 36},
  6. # {'publish__name': '长春出版社', 'price__min': 33},
  7. # {'publish__name': '重庆出版社', 'price__min': 99},
  8. # {'publish__name': '吉林出版社', 'price__min': 46},
  9. # {'publish__name': '江苏人民出版社', 'price__min': 77},
  10. # {'publish__name': '清华大学出版社', 'price__min': 48}]>

annotate

(7)F查询和Q查询

  1. # F 使用查询条件的值,专门取对象中某列值的操作
  2.  
  3. # from django.db.models import F
  4. #让所有书的价格加10
  5. # book.objects.values(price=F(price)+10)
  6.  
  7. # Q 构建搜索条件
  8. from django.db.models import Q
  9.  
  10. #1 Q对象(django.db.models.Q)可以对关键字参数进行封装,从而更好地应用多个查询
  11. q1=models.Book.objects.filter(Q(title__startswith='P')).all()
  12. print(q1)#[<Book: Python>, <Book: Perl>]
  13.  
  14. # 2、可以组合使用&,|操作符,当一个操作符是用于两个Q的对象,它产生一个新的Q对象。
  15. Q(title__startswith='P') | Q(title__startswith='J')
  16.  
  17. # 3、Q对象可以用~操作符放在前面表示否定,也可允许否定与不否定形式的组合
  18. Q(title__startswith='P') | ~Q(pub_date__year=2005)
  19.  
  20. # 4、应用范围:
  21.  
  22. # Each lookup function that takes keyword-arguments (e.g. filter(),
  23. # exclude(), get()) can also be passed one or more Q objects as
  24. # positional (not-named) arguments. If you provide multiple Q object
  25. # arguments to a lookup function, the arguments will be “AND”ed
  26. # together. For example:
  27.  
  28. Book.objects.get(
  29. Q(title__startswith='P'),
  30. Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
  31. )
  32.  
  33. #sql:
  34. # SELECT * from polls WHERE question LIKE 'P%'
  35. # AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')
  36.  
  37. # import datetime
  38. # e=datetime.date(2005,5,6) #2005-05-06
  39.  
  40. # 5、Q对象可以与关键字参数查询一起使用,不过一定要把Q对象放在关键字参数查询的前面。
  41. # 正确:
  42. Book.objects.get(
  43. Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
  44. title__startswith='P')
  45. # 错误:
  46. Book.objects.get(
  47. question__startswith='P',
  48. Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))

F查询和Q查询

(8)QuerySet

  1. #惰性机制:
  2. #所谓惰性机制:Publisher.objects.all()或者.filter()等都只是返回了一个QuerySet(查询结#果集对象),它并不会马上执行sql,而是当调用QuerySet的时候才执行。
  3. #QuerySet特点:可迭代,可切片
  4.  
  5. <1>Djangoqueryset是惰性的
  6.  
  7. Djangoqueryset对应于数据库的若干记录(row),通过可选的查询来过滤。例如,下面的代码会得到数据库中名字为‘Dave’的所有的人:
  8. person_set = Person.objects.filter(first_name="Dave")
  9. 上面的代码并没有运行任何的数据库查询。你可以使用person_set,给它加上一些过滤条件,或者将它传给某个函数,这些操作都不会发送给数据库。这是对的,因为数据库查询是显著影响web应用性能的因素之一。
  10.  
  11. <2>要真正从数据库获得数据,你可以遍历queryset或者使用if queryset,总之你用到数据时就会执行sql.
  12. 为了验证这些,需要在settings里加入 LOGGING(验证方式)
  13. obj=models.Book.objects.filter(id=3)
  14. # for i in obj:
  15. # print(i)
  16.  
  17. # if obj:
  18. # print("ok")
  19.  
  20. <3>queryset是具有cache
  21. 当你遍历queryset时,所有匹配的记录会从数据库获取,然后转换成Djangomodel。这被称为执行(evaluation).这些model会保存在queryset内置的cache中,这样如果你再次遍历这个queryset
  22. 你不需要重复运行通用的查询。
  23. obj=models.Book.objects.filter(id=3)
  24.  
  25. # for i in obj:
  26. # print(i)
  27. ## models.Book.objects.filter(id=3).update(title="GO")
  28. ## obj_new=models.Book.objects.filter(id=3)
  29. # for i in obj:
  30. # print(i) #LOGGING只会打印一次
  31.  
  32. <4> 简单的使用if语句进行判断也会完全执行整个queryset并且把数据放入cache,虽然你并不需要这些数据!为了避免这个,可以用exists()方法来检查是否有数据:
  33.  
  34. obj = Book.objects.filter(id=4)
  35. # exists()的检查可以避免数据放入queryset的cache。
  36. if obj.exists():
  37. print("hello world!")
  38.  
  39. <5>当queryset非常巨大时,cache会成为问题
  40.  
  41. 处理成千上万的记录时,将它们一次装入内存是很浪费的。更糟糕的是,巨大的queryset可能会锁住系统进程,让你的程序濒临崩溃。要避免在遍历数据的同时产生queryset cache,可以使用iterator()方法来获取数据,处理完数据就将其丢弃。
  42. objs = Book.objects.all().iterator()
  43. # iterator()可以一次只从数据库获取少量数据,这样可以节省内存
  44. for obj in objs:
  45. print(obj.name)
  46. #BUT,再次遍历没有打印,因为迭代器已经在上一次遍历(next)到最后一次了,没得遍历了
  47. for obj in objs:
  48. print(obj.name)
  49.  
  50. #当然,使用iterator()方法来防止生成cache,意味着遍历同一个queryset时会重复执行查询。所以使用iterator()的时候要当心,确保你的代码在操作一个大的queryset时没有重复执行查询
  51.  
  52. 总结:
  53. querysetcache是用于减少程序对数据库的查询,在通常的使用下会保证只有在需要的时候才会查询数据库。
  54. 使用exists()和iterator()方法可以优化程序对内存的使用。不过,由于它们并不会生成queryset cache,可能
  55. 会造成额外的数据库查询。

(9)QuerySet对象的源码里的方法总结

  1. def all(self)
  2. # 获取所有的数据对象
  3.  
  4. def filter(self, *args, **kwargs)
  5. # 条件查询
  6. # 条件可以是:参数,字典,Q
  7.  
  8. def exclude(self, *args, **kwargs)
  9. # 条件查询
  10. # 条件可以是:参数,字典,Q
  11.  
  12. def select_related(self, *fields)
  13. 性能相关:表之间进行join连表操作,一次性获取关联的数据。
  14. model.tb.objects.all().select_related()
  15. model.tb.objects.all().select_related('外键字段')
  16. model.tb.objects.all().select_related('外键字段__外键字段')
  17.  
  18. def prefetch_related(self, *lookups)
  19. 性能相关:多表连表操作时速度会慢,使用其执行多次SQL查询在Python代码中实现连表操作。
  20. # 获取所有用户表
  21. # 获取用户类型表where id in (用户表中的查到的所有用户ID)
  22. models.UserInfo.objects.prefetch_related('外键字段')
  23.  
  24. from django.db.models import Count, Case, When, IntegerField
  25. Article.objects.annotate(
  26. numviews=Count(Case(
  27. When(readership__what_time__lt=treshold, then=1),
  28. output_field=CharField(),
  29. ))
  30. )
  31.  
  32. students = Student.objects.all().annotate(num_excused_absences=models.Sum(
  33. models.Case(
  34. models.When(absence__type='Excused', then=1),
  35. default=0,
  36. output_field=models.IntegerField()
  37. )))
  38.  
  39. def annotate(self, *args, **kwargs)
  40. # 用于实现聚合group by查询
  41.  
  42. from django.db.models import Count, Avg, Max, Min, Sum
  43.  
  44. v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id'))
  45. # SELECT u_id, COUNT(ui) AS `uid` FROM UserInfo GROUP BY u_id
  46.  
  47. v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id')).filter(uid__gt=1)
  48. # SELECT u_id, COUNT(ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1
  49.  
  50. v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id',distinct=True)).filter(uid__gt=1)
  51. # SELECT u_id, COUNT( DISTINCT ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1
  52.  
  53. def distinct(self, *field_names)
  54. # 用于distinct去重
  55. models.UserInfo.objects.values('nid').distinct()
  56. # select distinct nid from userinfo
  57.  
  58. 注:只有在PostgreSQL中才能使用distinct进行去重
  59.  
  60. def order_by(self, *field_names)
  61. # 用于排序
  62. models.UserInfo.objects.all().order_by('-id','age')
  63.  
  64. def extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
  65. # 构造额外的查询条件或者映射,如:子查询
  66.  
  67. Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))
  68. Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
  69. Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
  70. Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])
  71.  
  72. def reverse(self):
  73. # 倒序
  74. models.UserInfo.objects.all().order_by('-nid').reverse()
  75. # 注:如果存在order_by,reverse则是倒序,如果多个排序则一一倒序
  76.  
  77. def defer(self, *fields):
  78. models.UserInfo.objects.defer('username','id')

  79. models.UserInfo.objects.filter(...).defer('username','id')
  80. #映射中排除某列数据
  81.  
  82. def only(self, *fields):
  83. #仅取某个表中的数据
  84. models.UserInfo.objects.only('username','id')

  85. models.UserInfo.objects.filter(...).only('username','id')
  86.  
  87. def using(self, alias):
  88. 指定使用的数据库,参数为别名(setting中的设置)
  89.  
  90. ##################################################
  91. # PUBLIC METHODS THAT RETURN A QUERYSET SUBCLASS #
  92. ##################################################
  93.  
  94. def raw(self, raw_query, params=None, translations=None, using=None):
  95. # 执行原生SQL
  96. models.UserInfo.objects.raw('select * from userinfo')
  97.  
  98. # 如果SQL是其他表时,必须将名字设置为当前UserInfo对象的主键列名
  99. models.UserInfo.objects.raw('select id as nid from 其他表')
  100.  
  101. # 为原生SQL设置参数
  102. models.UserInfo.objects.raw('select id as nid from userinfo where nid>%s', params=[12,])
  103.  
  104. # 将获取的到列名转换为指定列名
  105. name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'}
  106. Person.objects.raw('SELECT * FROM some_other_table', translations=name_map)
  107.  
  108. # 指定数据库
  109. models.UserInfo.objects.raw('select * from userinfo', using="default")
  110.  
  111. ################### 原生SQL ###################
  112. from django.db import connection, connections
  113. cursor = connection.cursor() # cursor = connections['default'].cursor()
  114. cursor.execute("""SELECT * from auth_user where id = %s""", [1])
  115. row = cursor.fetchone() # fetchall()/fetchmany(..)
  116.  
  117. def values(self, *fields):
  118. # 获取每行数据为字典格式
  119.  
  120. def values_list(self, *fields, **kwargs):
  121. # 获取每行数据为元祖
  122.  
  123. def dates(self, field_name, kind, order='ASC'):
  124. # 根据时间进行某一部分进行去重查找并截取指定内容
  125. # kind只能是:"year"(年), "month"(年-月), "day"(年-月-日)
  126. # order只能是:"ASC" "DESC"
  127. # 并获取转换后的时间
  128. - year : 年-01-01
  129. - month: 年-月-01
  130. - day : 年-月-日
  131.  
  132. models.DatePlus.objects.dates('ctime','day','DESC')
  133.  
  134. def datetimes(self, field_name, kind, order='ASC', tzinfo=None):
  135. # 根据时间进行某一部分进行去重查找并截取指定内容,将时间转换为指定时区时间
  136. # kind只能是 "year", "month", "day", "hour", "minute", "second"
  137. # order只能是:"ASC" "DESC"
  138. # tzinfo时区对象
  139. models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.UTC)
  140. models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.timezone('Asia/Shanghai'))
  141.  
  142. """
  143. pip3 install pytz
  144. import pytz
  145. pytz.all_timezones
  146. pytz.timezone(‘Asia/Shanghai’)
  147. """
  148.  
  149. def none(self):
  150. # 空QuerySet对象
  151.  
  152. ####################################
  153. # METHODS THAT DO DATABASE QUERIES #
  154. ####################################
  155.  
  156. def aggregate(self, *args, **kwargs):
  157. # 聚合函数,获取字典类型聚合结果
  158. from django.db.models import Count, Avg, Max, Min, Sum
  159. result = models.UserInfo.objects.aggregate(k=Count('u_id', distinct=True), n=Count('nid'))
  160. ===> {'k': 3, 'n': 4}
  161.  
  162. def count(self):
  163. # 获取个数
  164.  
  165. def get(self, *args, **kwargs):
  166. # 获取单个对象
  167.  
  168. def create(self, **kwargs):
  169. # 创建对象
  170.  
  171. def bulk_create(self, objs, batch_size=None):
  172. # 批量插入
  173. # batch_size表示一次插入的个数
  174. objs = [
  175. models.DDD(name='r11'),
  176. models.DDD(name='r22')
  177. ]
  178. models.DDD.objects.bulk_create(objs, 10)
  179.  
  180. def get_or_create(self, defaults=None, **kwargs):
  181. # 如果存在,则获取,否则,创建
  182. # defaults 指定创建时,其他字段的值
  183. obj, created = models.UserInfo.objects.get_or_create(username='root1', defaults={'email': '','u_id': 2, 't_id': 2})
  184.  
  185. def update_or_create(self, defaults=None, **kwargs):
  186. # 如果存在,则更新,否则,创建
  187. # defaults 指定创建时或更新时的其他字段
  188. obj, created = models.UserInfo.objects.update_or_create(username='root1', defaults={'email': '','u_id': 2, 't_id': 1})
  189.  
  190. def first(self):
  191. # 获取第一个
  192.  
  193. def last(self):
  194. # 获取最后一个
  195.  
  196. def in_bulk(self, id_list=None):
  197. # 根据主键ID进行查找
  198. id_list = [11,21,31]
  199. models.DDD.objects.in_bulk(id_list)
  200.  
  201. def delete(self):
  202. # 删除
  203.  
  204. def update(self, **kwargs):
  205. # 更新
  206.  
  207. def exists(self):
  208. # 是否有结果

(10)常用双下划线

  1. models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值
  2.  
  3. models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据
  4. models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in
  5.  
  6. models.Tb1.objects.filter(name__contains="ven")
  7. models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
  8.  
  9. models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and
  10.  
  11. startswithistartswith, endswith, iendswith 

(11)表的正反向查询

  1. 1.一对多跨表查询:
  2. (1)正向跨表查询
  3. 1:查询书名为《巴黎圣母院》的出版社名
  4. <法1:>通过对象进行正向跨表查询(obj.FK.跨表要查询的字段),注意book_obj.publish是指书籍对象对应的关联表中的publish对象,是Publish表中的一条记录
  5. book_obj= book.objects.filter(title="巴黎圣母院").first()
  6. ret=book_obj.publish.name
  7. 注意.filter输出为[obj,obj...],即一个个对象组成的列表,后面不加.first(),直接取值会出错,可以遍历里面的对象取值
  8. book_obj = book.objects.filter(title="巴黎圣母院")
  9. for item in book_obj:
  10. print(item.publish.name,item.publish.city)
  11. <法2:>通过PK加双下滑线进行正向跨表查询
  12. ret=book.objects.filter(title="巴黎圣母院").values('publish__name','publish__city')#values里面用双下划线
  13. 补充ret=Publish.objects.filter(book__title='巴黎圣母院').values('name','city')#filter里面用双下滑线,这个是反向查询,及类名加双下滑线实现例子中的需求
  14. print(ret)
  15.  
  16. print(ret)
  17. (2)反向跨表查询
  18. 1:查询北京出版社出版的所有书籍书名和价格
  19. <法1:>通过对象进行反向跨表查询
  20. publish_obj=Publish.objects.filter(name='北京出版社')[0]#先拿到一个publish对象
  21. ret=book.objects.filter(publish=publish_obj).values('title','price')#通过FK=publish对象进行筛选
  22. print(ret)
  23. <法2:>:通过 小写表名_set进行反向查询
  24. publish_obj = Publish.objects.filter(name='北京出版社')[0]#先拿到一个publish对象
  25. print(publish_obj.book_set.all().values('title','price'))#通过book_set反向关联要查询的表
  26. <法3:>通过类名加双下滑线进行反向查询
  27. ret=Publish.objects.filter(name='北京出版社').values('book__title','book__price')
  28. ret=book.objects.filter(publish__name='北京出版社').values('title','price')#补充,这个是通过正向查询,及PK加双下划线实现的例子中的需求
  29. print(ret)
  30.  
  31. 2.一对多查询练习
  32. 1:查询在北京的所有出版社出过的书籍名称和价格
  33. ret=Publish.objects.filter(city='北京').values('book__title','book__price')
  34. print(ret)
  1. 3.多对多跨表查询
  2. 类型1,通过many_to_many字段自动创建第3张表
  3. (1)正向多对多跨表查询
  4. 1:查询书籍《python程序设计教程》的所有作者姓名和年龄
  5. <法1:>通过对象进行正向跨表查询
  6. book_obj = book.objects.filter(title='python程序设计教程')[0]
  7. print(book_obj.author.all())#通过book_obj.MTM字段.all()拿到的是book对应的author对象组成的QuerySet集合<QuerySet[obj,obj]>
  8. author_set=book_obj.author.all()
  9. for item in author_set:
  10. print(item.name,item.age)
  11. <法2:> 通过MTM字段加双下滑线进行正向跨表查询
  12. author_ret_set=book.objects.filter(title='python程序设计教程').values('author__name','author__age')
  13. print(author_ret_set)
  14. (2)反向多对多跨表查询
  15. 1:查询高尔基出过的所有书籍名称和价格
  16. <法1:> 通过对象进行反向跨表查询
  17. author_obj=Author.objects.filter(name='高尔基')[0]
  18. book_ret_set=book.objects.filter(author=author_obj).values('title','price')
  19. print(book_ret_set)
  20. <法2:> 通过小写表名_set进行反向查询
  21. author_obj = Author.objects.filter(name='高尔基')[0]
  22. book_set=author_obj.book_set.all()
  23. for item in book_set:
  24. print(item.title,item.price)
  25. <法3:>通过类名加双下滑线进行反向查询
  26. book_ret_set=Author.objects.filter(name='高尔基').values('book__price','book__title')
  27. print(book_ret_set)
  28. 类型2,自己手动创建第3张表

>>>>>>>待续

Django:URL,Views,Template,Models的更多相关文章

  1. 第三百零四节,Django框架,urls.py模块,views.py模块,路由映射与路由分发以及逻辑处理——url控制器

    Django框架,urls.py模块,views.py模块,路由映射与路由分发以及逻辑处理——url控制器 这一节主讲url控制器 一.urls.py模块 这个模块是配置路由映射的模块,当用户访问一个 ...

  2. 二 Django框架,urls.py模块,views.py模块,路由映射与路由分发以及逻辑处理——url控制器

    Django框架,urls.py模块,views.py模块,路由映射与路由分发以及逻辑处理——url控制器 这一节主讲url控制器 一.urls.py模块 这个模块是配置路由映射的模块,当用户访问一个 ...

  3. python :Django url /views /Template 文件介绍

    1,Django URL 路由系统 URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表:你就是以这种方式告诉Django ...

  4. Django框架_URLconf、Views、template、ORM

    目录: 一.Django-MTV MTV模型 Django基本命令 视图层之路由配置系统(views) 视图层之视图函数(views) 模板层(template) 二.Django-model基础 O ...

  5. Django基础(一)_URLconf、Views、template、ORM

    一 什么是web框架? 框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演. 对于所有 ...

  6. Django 路由系统URL 视图views

    一.Django URL (路由系统) URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表:你就是以这种方式告诉Djan ...

  7. Django url配置 正则表达式详解 分组命名匹配 命名URL 别名 和URL反向解析 命名空间模式

    Django基础二之URL路由系统 本节目录 一 URL配置 二 正则表达式详解 三 分组命名匹配 四 命名URL(别名)和URL反向解析 五 命名空间模式 一 URL配置 Django 1.11版本 ...

  8. Django URL (路由系统)

    URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表:你就是以这种方式告诉Django,对于这个URL调用这段代码,对于那 ...

  9. Django url

    urlpatterns = [ url(正则表达式, views视图函数,参数,别名),]     参数说明:   一个正则表达式字符串 一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符 ...

  10. Django URL(路由系统)

    Django URL Django 1.11版本 URLconf官方文档 URL配置(URLconf)就像 Django 所支撑网站的目录.它的本质是URL模式以及要为该URL模式调用的视图函数之间的 ...

随机推荐

  1. POJ 2373

    原本一道挺简单的DP题,思路有了,运用单调队列,但在写单调队列时写挫了... 这道题只需要计算偶数位置的即可,这是显而易见的,我有注意过这情况,写的时候却没在意...--! 加入队列的元素应该当前no ...

  2. 開始搭建第一个zookeeper

    首先须要下载zookeeper的tar包.地址为http://zookeeper.apache.org,然后再linux中解压并编译tar包. # tar-xvzf zookeeper-3.4.5.t ...

  3. jQuery高性能自己定义滚动栏美化插件

    malihu是一款高性能的滚动栏美化jQuery插件. 该滚动栏美化插件支持水平和垂直滚动栏,支持鼠标滚动,支持键盘滚动和支持移动触摸屏. 而且它能够和jQuery UI和Bootatrap完美的结合 ...

  4. Android 怎样实现 焦点图的 无线循环滑动的状态?

    參考网址:http://my.oschina.net/xsk/blog/119167 总体的架构:ViewPgaer 中直接嵌套  IamgeView 方案一:  重写Viewpager 这样有局限性 ...

  5. 《Head First 设计模式》学习笔记——复合模式

    模型-视图-控制器(MVC模式)是一种很经典的软件架构模式.在UI框架和UI设计思路中扮演着很重要的角色.从设计模式的角度来看,MVC模式是一种复合模式.它将多个设计模式在一种解决方式中结合起来,用来 ...

  6. hdoj--1083--Courses(最大匹配)

    Courses Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total ...

  7. 表格td内容过多时,td显示省略号,鼠标移入显示全部内容。

    转自:https://blog.csdn.net/weixin_42193908/article/details/80405014 两种方式显示: 1.title方式显示: <!DOCTYPE ...

  8. struts的工作流程

    - 一个请求过来,走前端控制器StrutsPrepareAndExecuteFilter        -前端控制器是一个过滤器,过滤器中的核心方法是doFilter(),doFilter方法中首先处 ...

  9. 使用filezella服务器安装ftp

    使用FileZilla配置FTP站点,可参考以下步骤: 1.打开Filezilla Server服务端: 点击[Edit]->[Users],或者点击如下图标新增用户. 2.添加FTP帐号后,设 ...

  10. if,elif,else的关系 input print int的用法

    qian=input("找劳保网是什么网站?:")if qian=="zhaolaobaowang.com": print("正确")els ...