django框架

Django

01 初始化

1.1 安装Django

pip install django==2.1.0

# 查看第三方库
pip list

1.2 创建项目

django-admin startproject djangoStudy

1.3 启动项目

# 在manage.py 里打开
python manage.py runserver 0.0.0.0:8000
# 0.0.0.0 代表任意ip都可以访问

# 访问地址
127.0.0.1:8000

02 路由

2.1 创建视图

创建视图文件

# djangoStudy文件夹下创建视图文件
- djangoStudy
	- views.py

创建视图函数

from django.http import HttpResponse

# 请求视图
def index(request):
    # HttpResponse 响应路由
    return HttpResponse('这是Django的第一节课')
	
    # 里面可以直接放标签
    return HttpResponse('<h1>222</h1>')

2.2 创建路由匹配

# djangoStudy/urls.py

from django.contrib import admin
from django.urls import path
from . import views

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

2.3 动态路由

路由设置

# djangoStudy/urls.py
from . import views

urlpatterns = [
    path('getUrl/<urlParams>', views.getUrlParams),
]

视图设置

# djangoStudy/views.py
from django.http import HttpResponse

def getUrlParams(request,urlParams):
    return HttpResponse('获取到的动态路由参数:{urlParams}'.format(urlParams=urlParams))

多个参数传参

# 路由
urlpatterns = [
    # &分隔,可以多个
    path('getUrl/<urlParams>&<second>', views.getUrlParams),
]

# 视图
def getUrlParams(request,urlParams,second):
    return HttpResponse('获取参数:{urlParams},{second}'.format(urlParams=urlParams,second=second))

2.4 路径转换器

urlpatterns = [
    # 也可以设置参数类型
    # str 匹配除了(/)之外的非空字符串,默认
    # int 正整数,包括0
    # slug 字母、数字以及横杠、下划线组成的字符串
    # 任何非空字符串,包含路径分隔符(/)
    path('getUrl/<int:urlParams>', views.getUrlParams),
]

2.5 正则匹配路径

from django.urls import path,re_path
from . import views

urlpatterns = [
    re_path(r'^index/$', views.index),
]

2.6 分路由

创建app

python manage.py startapp book

# 一个项目下有多个app
在book项目下添加urls.py文件

注册app

每次新增一个app都需要去 djangoStudy/setting.py 注册app

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'book', # 注册book
]

分路由视图 book/views.py 配置

from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.
def appbook(request):
    return HttpResponse('分路由appbook')

分路由 book/urls.py 配置

from django.urls import path, re_path
from . import views

urlpatterns = [
    path('appbook/', views.appbook)
]

主路由 djangoStudy/urls.py 注册分路由

from django.urls import path, include

urlpatterns = [
    path('book/', include('book.urls'))
]

2.7 kwargs路由参数

路由传参

from django.contrib import admin
from django.urls import path
from . import views

urlpatterns = [
    path('index/', views.index,{'index':'2'}), # 字典格式
]

视图接收

from django.http import HttpResponse

def index(request,**kwargs):
    print('接收的kwargs参数:'+kwargs.get('index')) # 接收的kwargs参数:2
    return HttpResponse('这是Django的第一节课')

2.8 重定向

路由设置

from django.urls import path, include
from . import views

urlpatterns = [
    # 第一种 路由重定向
    path('direct/', views.direct),
    
    # 第二种 名称重定向
    path('test/', views.test,name='test'),
    path('directname/', views.directname),
]

视图设置

from django.shortcuts import render,redirect,reverse
from django.http import HttpResponse

# 第一种
def direct(request):
    # 重定向路由
    return redirect('/index')

def directname(request):
    # 重定向路由模版名称
    return redirect(reverse('test'))

03 模版引擎

3.1 配置模版引擎

在主目录下创建templates文件夹

在djangoStudy/setting.py下配置templates

# djangoStudy/setting.py

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR,'templates')], # 配置路径
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

在templates下创建book的app文件夹,里面存放html模版文件

在templates/book下创建book_index.html

3.2 渲染模版文件

from django.shortcuts import render
from django.http import HttpResponse
from django.template.loader import get_template

# 第一种渲染方法
def index1(request):
    # 前提book_index.html的存在
    getTemplate = get_template('book/book_index.html')
    rendHtml = getTemplate.render()
    return HttpResponse(rendHtml)

# 第二种渲染方法
def index2(request):
    return render(request, 'book/book_index.html')

3.3 模版变量

views.py 视图传参

def index2(request):
    return render(request, 'book/book_index.html', context={'name': '宁爸爸', 'age': 18})

book_index.html 模版接收

<body>
    <p>姓名:{{ name }}</p>
    <p>年龄:{{ age }}</p>
</body>
</html>

3.4 过滤器

# 路由模版传递参数
def filter(request):
    context = {
        'enStr': 'i am boy',
        'enBigStr': 'I AM BOY',
        'cnStr': '我是男孩',
        'intNum': 10,
        'floatNum': 1.234,
        'nowDate': datetime.now(),
        'list': [1, 2, 3, 4],
        'emptyValue': '',
        'noneValue': None
    }
    return render(request, 'book/book_index.html', context=context)

常用过滤器

  • add:字符串相加,数字相加,列表相加,如果失败返回一个空字符串
  • defalut:值为false时,提供默认值
  • default_if_none:值为None时使用默认值
  • first:返回列表中第一个值
  • last:返回列表中最后一个值
  • date:格式化时间和日期
  • time:格式化时间
  • join:与python中的join一样用法
  • length:返回字符串或者数组长度
  • length_is:字符串或者数组长度是否指定的值
  • upper:把英文变成大写
  • lower:把英文变成小写
  • truncatechars:字符超出规定长度…
  • truncatewords:单词超出规定长度…
  • capfirst:首字母大写
  • slice:切割列表
  • floatformat:浮点数格式化

例:

add相加:{{ intNum|add:10 }} <br/>  {# 值:30 #}
defalut默认值:{{ emptyValue|default:'输出的默认值' }} <br/> {# 值:输出的默认值 #}
default_if_none默认值:{{ noneValue|default:'只有为None时输出默认值' }} <br/> {# 值:只有为None时输出默认值 #}
列表首值:{{ list|first }} <br/> {# 值:1 #}
列表尾值:{{ list|last }} <br/> {# 值:4 #}
join拼接:{{ list|join:'+' }} <br/> {# 值:1+2+3+4 #}
数组或字符串长度:{{ list|length }} <br/> {# 值:4 #}
是否是3个长度:{{ list|length_is:3 }} <br/> {# 值:False #}
英文变大写:{{ enStr|upper }} <br/> {# 值:I AM BOY #}
英文变小写:{{ enBigStr|lower }} <br/> {# 值:i am boy #}
字符超出2个隐藏:{{ cnStr|truncatechars:2 }} <br/> {# 值:我… #}
单词超出2个隐藏:{{ enStr|truncatewords:2 }} <br/> {# 值:i am … #}
英文首单词大写:{{ enStr|capfirst }} <br/> {# 值:I am boy #}
列表切割:{{ list|slice:'0:3' }} <br/> {# 值:[1, 2, 3] #}
浮点数,默认保留一位:{{ floatNum|floatformat }} <br/> {# 值:1.2 #}
浮点数保留2位:{{ floatNum|floatformat:'2' }} <br/> {# 值:1.23 #}

date 和 time过滤器格式

  • Y:四位数年。例:1999
  • y:两位数年。例:99
  • m:两位数的月。例:01、09
  • n:一位数的月。例:1、9
  • d:两位数的日。例:01、09
  • j:一位数的日。例:1、9
  • g:12小时制的一位数的小时。例:1、9、12
  • G:24小时制的一位数的小时。例:1、9、24
  • h:12小时制的两位数的小时。例:01、09、12
  • H:24小时制的两位数的小时。例:01、09、24
  • i:分钟。从00-59
  • s:秒。从00-59

修改setting.py配置,时间转为上海东八区

TIME_ZONE = 'Asia/Shanghai'

例:

默认日期:{{ nowDate|date }} <br/> {# 值:Nov. 9, 2019 #}
默认时间:{{ nowDate|time }} <br/> {# 值:10:36 p.m #}
年月日时分秒:{{ nowDate|date:'Y/m/d G:i:s' }} <br/> {# 值:2019/11/09 22:40:09 p.m #}

3.5 配置静态文件夹

创建静态文件夹static在主目录,及其他文件

static
    ├─css
       ├─book.css
    ├─images
       ├─1.jpg
    └─js
       ├─book.js

setting.py配置静态文件夹

STATIC_URL = '/static/'

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static')
]

模版引入静态文件

<!-- 加载静态文件 -->
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- 引入静态文件 -->
    <link rel="stylesheet" href="{% static 'css/book.css' %}">
</head>
<body>
    <div class="box"></div>
     <!-- 获取图片 -->
    <img src="{% static 'images/1.jpg' %}" alt="" width="200" height="200">
</body>
</html>

3.6 模版标签

  • if / elif / else 判断语句
  • ifequal 判断是否相等
  • ifnotequal 判断值不相等
{# 判断语句 #}
{% if intNum == 123 %}
    if
{% elif intNum == 10 %}
    elif
{% else %}
    else
{% endif %}

{# 判断是否相等 #}
{% ifequal emptyValue '' %}
    判断值相等,不用==
{% endifequal %}

{# 判断值不相等 #}
{% ifnotequal noneValue None %}
    222
{% endifnotequal %}
    
{# 判断值不相等 #}
{% ifnotequal noneValue None %}
    222
{% endifnotequal %}
  • for…in… 遍历
  • forloop.counter 当前迭代的次数,下标从0开始。1,2,3,4
  • forloop.counter0 当前迭代的次数,下标从1开始。0,1,2,3
  • forloop.revcounter 当前迭代的次数,下标从0开始,且下标从大到小。4,3,2,1
  • forloop.revcounter0 当前迭代的次数,下标从1开始,且下标从大到小。3,2,1,0
  • forloop.first 判断是否是第一次迭代
  • forloop.last 判断是否是最后一次迭代
  • forloop.parentloop 嵌套循环返回的是上一层的for
{#列表遍历#}
{% for i in list %}
    {{ i }}
{% endfor %}
    
{% for i in list %}
{#    当前迭代的次数,下标从0开始。1,2,3,4 #}
    {{ forloop.counter }}

{#    当前迭代的次数,下标从1开始。0,1,2,3, #}
    {{ forloop.counter0 }}

{#    当前迭代的次数,下标从0开始,且下标从大到小。4,3,2,1 #}
    {{ forloop.revcounter }}

{#    当前迭代的次数,下标从1开始,且下标从大到小。3,2,1,0 #}
    {{ forloop.revcounter0 }}

{# 判断是否是第一次迭代 #}
    {{ forloop.first }}

{# 判断是否是最后一次迭代 #}
    {{ forloop.last }}
{% endfor %}    
    
{# 嵌套循环 #}
{% for i in list %}
    {% for j in list %}
        {# 嵌套循环返回的是上一层的for #}
        {% if forloop.parentloop.counter == 1 %}
            2222
        {% endif %}
    {% endfor %}
{% endfor %}
  • widthratio 自带运算(乘除)
{# 乘法 10*2/1 #}
{% widthratio 10 1 2 %}{# 结果:20 #}

{# 除法 10*2/2 #}
{% widthratio 10 2 2 %} {# 结果:10 #}
  • url 跳转传参
{# 第一个参数为模版名称,第二个参数是传递的参数 #}
<a href="{% url 'getUrl' 'aabb' %}">222</a>

with 变量重命名

{{ enStr }} {# i am boy #}

{#重命名变量使用的区域#}
{% with enStr as new_name %}
    {{ new_name }} {# i am boy #}
{% endwith %}

autoescape 关闭转义

{{ html }} {#  22 #}

{# 关闭转义区域 #}
{% autoescape off %}
    {{ html }} {#  <h1>22</h1> #}
{% endautoescape %}

3.7 模版继承

extends 继承模版

  • block 继承修改区块
└─book
 └─templates
    └─base.html
    └─book_test.html

基础模版base.html

<body>
    {#  content是块名称 #}
    {% block content %}
        2222222
    {% endblock %}
</body>

extends 继承模版

index.html 继承 base.html

{% extends 'base.html' %}

重新定义content块的内容

{% extends 'base.html' %}

{# 重新定义content内容 #}
{% block content %}
    新内容
{% endblock %}

继承并修改

{# 继承content并修改 #}
{% block content %}
    {# block.super 继承上一个内容 #}
    {{ block.super }}
    新内容
{% endblock %} 

include 引入模版

{# 引入模版,必须在block里 #}
{% block content %}
    {% include 'test.html' %}
{% endblock %}

3.8 配置自定义模版

主目录下创建common的文件夹

└─common

将common添加到settings文件配置

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'book',
    'common', # 添加配置
]

在common里面创建文件夹templatetags,存放自定义标签和过滤器

└─common
 └─templatetags

3.9 自定义过滤器

创建过滤器文件

└─common
 └─templatetags
  └─common_textras.py

定义自定义过滤器

from django import template

# 模版实例化对象
register = template.Library()


# isZore 为过滤器名字,不定义时,取ifZore函数名称
@register.filter('isZore')
def ifZore(num):
    return num == 0

# 定义过滤器
@register.filter
def my_sort(list): # my_sort 为过滤器名字
    return sorted(list)

# 接收参数的过滤器
@register.filter
def joinList(list,index):
    return list[index]

使用自定义过滤器

{# 加载自定义过滤器 #}
{% load common_textras %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {{ list | my_sort }}
    {{ 0 | isZore }}
    {{ list | joinList:0 }}
</body>
</html>

3.10 自定义简单标签

接着在上面common_textras.py文件里写

# 获取时间的标签
import datetime
@register.simple_tag
def get_time():
    for_string = '%Y-%m-%d %H:%M:%S'
    return datetime.datetime.now().strftime(for_string)

# 加法,传参的自定义标签
@register.simple_tag
def add_val(num1,num2):
    return num1+num2

使用自定义简单标签

<body>
    {% get_time %} {# 值:2019-11-10 17:03:02 #}
    {% add_val 1 2 %} {# 值:3 #}
</body>

开启上下文的自定义标签

视图中的参数

def filter(request):
    context = { 'enStr': 'i am boy' }
    return render(request, 'book/book_index.html', context=context)

开启接收上下文参数

@register.simple_tag(takes_context=True) # 允许使用上下文参数,默认关闭
def get_last_val(context):
    enStr = context.get('enStr') # 获取上下文中的enStr参数
    return enStr+' boy boy boy'

使用该自定义标签

<body>
    {% get_last_val %} {# 值:i am boyboy boy boy #}
</body>

3.11 自定义包含标签

包含文件,在book/template/test.html

{% for i in printList %}
    {{ i }}
{% endfor %}

注册自定义包含标签

# test.html为包含的模版
@register.inclusion_tag('test.html')
def show_list():
    list = ['我','的','天']
    # printList为包含模版里的参数
    return { 'printList':list }

在template/book/book_index.html里插入模版

{# 加载自定义过滤器 #}
{% load common_textras %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {% show_list %}
</body>
</html>

传参

@register.inclusion_tag('test.html')
def for_val(val):
    # printList为包含模版里的参数
    return { 'printList':val }
<body>
    {% show_list '123' %}
</body>

开启上下文

@register.inclusion_tag('test.html',takes_context=True)
def open_text(context):
    enStr = context.get('enStr')  # 获取上下文中的enStr参数
    return { 'printList':enStr }
<body>
    {% open_text %}
</body>

04 模型系统

4.1 连接数据库

在settings.py配置数据库

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',  # 数据库引擎
        'NAME': 'ucan',  # 使用的数据库
        'USER': 'root',  # 用户
        'PASSWORD': '123456',  # 密码
        'HOST': '127.0.0.1',  # mysql服务器的ip地址
        'PORT': '3306'  # 端口
    }
}

安装模块

pip install pymysql 

django用pymysql代替mysqldb连接数据库

# djangoStudy/djangoStudy/__init__.py
import pymysql
pymysql.install_as_MySQLdb() # 数据库连接器

启动服务器错误时:

使用python3.7+django2.2+pymysql时遇到这个错误

django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 0.9.2

解决 C:\Python37\Lib\site-packages\django\db\backends\mysql(python安装目录)打开base.py

# if version < (1, 3, 13):
#     raise ImproperlyConfigured('mysqlclient 1.3.13 or newer is required; you have %s.' % Database.__version__)

C:\Python37\lib\site-packages\django\db\backends\mysql\operations.py

# 打开此文件把146行的decode修改为encode
if query is not None:
    query = query.encode(errors='replace')
return query

4.2 字段类型映射关系

varchar - CharField # 字符
int - IntegerField # 数值
longtext - TextField # 长文本
date - DateField # 日期	
datetime - DateTieField # 日期时间

# 布尔值 
boolean - BooleanField # 传入True / 
False,值不可以为空
NullBooleanFild # 布尔值可以为空
EmailField #邮箱地址

例:模型类

class Article(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=20)
    age = models.IntegerField()
    offon = models.BooleanField(default=True)
    content = models.TextField()
    create_time = models.DateField(auto_now_add=True) # 第一次创建设置时间
    update_datetime = models.DateTimeField(auto_now=True) # 自动更新修改时间
    # 默认获取当前时间戳(毫秒)
    date_publish = models.IntegerField(verbose_name="更新时间戳" , default=datetime.datetime.now)

使用时间时,不根据数据库时间,修改settings.py,

USE_TZ = False

4.3 Field的常用参数

primary_key # 是否为主键
unique # 是否为唯一
null # 是否为空,默认为False
blank # 等于True时form表单验证时可以为空,默认为False
defalut: # 设置默认值
DateField.auto_now # 每次修改都会更新当前时间
DateField.auto_now_add # 第一次添加,将时间设置进去

4.4 创建模型类

表映射关系: 模型类 = 表 / 属性 = 字段

在创建mysql_test的app,并注册

在mysql_test/models.py

from django.db import models

class User(models.Model):
    id = models.AutoField(primary_key=True) # 主键 自增长
    name = models.CharField(max_length=20) # 字符字段,长度20

创建一个映射文件(迁移)

表结构任何修改都要重新执行映射文件

# appname 为app名称,appname存在只映射这个app的文件
python manage.py makemigrations [appname] 

将映射文件的映射数据真正提交到数据库(迁移)

python manage.py migrate [appname]

生产的表名称,app名称+模型类名称 = mysql_test_user

强制执行

python manage.py makemigrations --fake
python manage.py migrate --fake

规定打印:mysql_test/model.py

class User(models.Model):
    id = models.AutoField(primary_key=True)  # 主键 自增长
    name = models.CharField(max_length=20)  # 字符,max_length 长度20
    city = models.CharField(max_length=30, default='广州')  # default 默认值

    # 打印
    def __str__(self):
        return 'name:{},city:{}'.format(self.name, self.city)
# views.py

# <QuerySet [<User: name:zzw,city:江门>, <User: name:caj,city:广州>, <User: name:ch,city:潮州>, <User: name:zzw,city:开平>]>

def	select(request):	
    # 查询所有
    all_data = User.objects.all()
    
    print(all_data.__dict__) # 字典形式返回
    print(all_data) # 规定打印返回

4.5 添加数据

在mysql_test/views.py

# 导入用户表
from .models import User

def add(request):
    # 方法一
    user_data = User(name='zzw', city='江门')
    user_data.save() # 保存
    
    
    # 方法二
    user_data = User()
    user_data.name = 'caj'
    user_data.city = '广州'
    user_data.save() # 保存
    
	# 方法三,不需要保存
    User.objects.create(name='ch', city='潮州')
    
    # 方法四 
    # 重复值,不允许提交
    # 不重复就提交
    # 返回元祖
  user_obj = User.objects.get_or_create(name='zzw', city='江门')
	# instance 返回实例
	# created_bolean 创建结果 true成功 false失败
	instance,created_bolean = user_obj
    
    return HttpResponse('添加数据') 

4.6 查询数据

mysql_test/views.py

基础查询
from django.core import serializers

def select(request):	
    # 查询所有
    all_data = User.objects.all() 
    re_data = ''
    for item in all_data:
        re_data += ' 姓名:{},城市:{}'.format(item.name, item.city)
        
    # 单个查询
    data = User.objects.get(id=1) # 查询条件
    re_data = ' 姓名:{},城市:{}'.format(data.name, data.city)
    # 单个查询转json
    json_data = json.loads(serializers.serialize("json", [re_data])[1:-1])
    
    # 查询满足条件的对象
    filter_data = User.objects.filter(city='江门')
    
    # 是否存在
    User.objects.filter(city='江门').exists()
    
    re_data = ''
    for item in filter_data:
        re_data += ' 姓名:{},城市:{}'.format(item.name, item.city)

    return HttpResponse(re_data)
字段查询
# 返回values选项的字典
user = User.objects.values('id','city')

# 返回values选项的元祖
user = User.objects.values_list('id','city')
    
# 过滤字段,只返回id,city字段
user = User.objects.only('id','city').filter(city='江门')

# 非过滤字段
user = User.objects.defer('id','city').filter(city='江门')
条件筛选
User.objects.first() # 获取数据第一条
User.objects.last()  # 获取数据最后一条

# 查询不满足条件的,相当于not操作
User.objects.exclude(name='zzw') 

# 排序,传入需要排序的字段 
User.objects.order_by('age')  # 'age'为升序 '-age'为倒叙

# 查询结果转换为字典
User.objects.all().values()

# 获取查询结果数量
User.objects.all().count()

# 等于
User.objects.filter(name__exact='zzw') # 双下划线  [key]___exact

# 模糊查询
User.objects.filter(name__contains='z') # 双下划线  [key]___contains

# 以...开头
User.objects.filter(name__startswith='c')  # 双下划线  [key]___startswith

# 以...结尾
User.objects.filter(name__endswith='w')  # 双下划线  [key]___endswith

# 成员所属 包含[...]里面的
User.objects.filter(age__in=[1,18]) # 双下划线  [key]___in

# 比较符号
User.objects.filter(id__lt=3) # 小于
User.objects.filter(id__lte=4) # 小于等于
User.objects.filter(id__gt=4) # 大于
User.objects.filter(id__gte=4) # 大于等于

# 区间 [2,8]
User.objects.filter(id__range=(2,8)) 
外键关联
# 一个表里有两个外键
# 'tag','author' 两个外键关联表的字段
User.objects.select_related('tag','author').all()
排序
User.objects.all().order_by('id','time')
聚合查询
from django.db.models import Avg, Max, Min,Count
# 计算学生平均年龄, 返回字典。age和avg间是双下划线哦

Student.objects.all().aggregate(Avg('age'))

{ 'age__avg': 12 }

 

# 学生平均年龄,返回字典。all()不是必须的。

Student.objects.aggregate(Avg('age'))

{ 'age__avg: 12' }

 

# 计算学生总年龄, 返回字典。

Student.objects.aggregate(Sum('age'))

{ 'age__sum': 144 }

 

# 学生平均年龄, 设置字典的key

Student.objects.aggregate(average_age = Avg('age'))

{ 'average_age': 12 }

 

# 学生最大年龄,返回字典

Student.objects.aggregate(Max('age'))

{ 'age__max': 12 }

 

# 同时获取学生年龄均值, 最大值和最小值, 返回字典

Student.objects.aggregate(Avg('age‘), Max('age‘), Min('age‘))

{ 'age__avg': 12, 'age__max': 18, 'age__min': 6, }

 

# 根据Hobby反查学生最大年龄。查询字段student和age间有双下划线哦。

Hobby.objects.aggregate(Max('student__age'))

{ 'student__age__max': 12 }
分组查询
# 按学生分组,统计每个学生的爱好数量

Student.objects.annotate(Count('hobbies'))

 

返回的结果依然是Student查询集,只不过多了hobbies__count这个字段。如果你不喜欢这个默认名字,你当然可以对这个字段进行自定义从而使它变得更直观。

 

# 按学生分组,统计每个学生爱好数量,并自定义字段名

Student.objects.annotate(hobby_count_by_student=Count('hobbies'))

 

# 按爱好分组,再统计每组学生数量。

Hobby.objects.annotate(Count('student'))

 

# 按爱好分组,再统计每组学生最大年龄。

Hobby.objects.annotate(Max('student__age'))
Annotate与values()联用
# 按学生名字分组,统计每个学生的爱好数量。

Student.objects.values('name').annotate(Count('hobbies'))

 

你还可以使用values方法从annotate返回的数据集里提取你所需要的字段,如下所示:

# 按学生名字分组,统计每个学生的爱好数量。

Student.objects.annotate(hobby_count=Count('hobbies')).values('name', 'hobby_count')

————————————————
版权声明:本文为CSDN博主「大江狗」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42134789/article/details/84567365

4.7 修改数据

def update(request):
    # 方法一 单改
    data = User.objects.get(id=3)  # 查询条件,有时间时间也会跟着修改
    data.name = 'baba'
    data.save()
    
    # 方法二 可多个一起修改
    User.objects.filter(id=3).update(name='mama')

    return HttpResponse('修改成功')

4.8 删除数据

def delete(request):
    #方法一
    User.objects.get(id=1).delete()
    
    # 方法二 多个删除
    User.objects.filter(id=3).delete()
    
    return HttpResponse('删除成功')

4.9 表关系

多对一关系

例:一个学院多个学生

# 学院表
class Department(models.Model):
    d_id = models.AutoField(primary_key=True)
    d_name = models.CharField(max_length=30)


# 学生表
class Student(models.Model):
    s_id = models.AutoField(primary_key=True)
    s_name = models.CharField(max_length=30)
    # on_delete 级联删除
    department = models.ForeignKey('Department', on_delete=models.CASCADE)  # 外键关联学院表
    # 表会自动创建department_id字段,关联学院表的主键

一对一关系

例:一个学生对应一个学生详情

# 学生详情表
class Student_detail(models.Model):
    # OneToOneField 一对一关联
    student = models.OneToOneField('Student', on_delete=models.CASCADE)
    s_age = models.IntegerField()
    note = models.TextField()
    phone = models.IntegerField()

多对多关系

通过中间表,同时关联学院表与学生表

class Course(models.Model):
    c_id = models.AutoField(primary_key=True)
    c_name = models.CharField(max_length=30)
    # ManyToManyField 多对多关联
    student = models.ManyToManyField('Student')

级联删除

on_delete=models.CASCADE # 删除主键同时删除外键数据
on_delete=models.PROTECT, null=True # 如果有外键在引用主键,主键不允许删除
on_delete=models.SET_NULL,null=True # 删除主键同时把外键设为空
on_delete=models.SET_DEFAULT,default='默认值' # 删除主键同时把外键设为默认值

4.10 一对多

新增/修改

from .models import Department,Student
def test(request):
    d1 = Department.objects.get(d_id=3)
    s6 = Student.objects.get(s_id=4)
    # 方法一: 学生添加/修改课程,添加/修改
    d1.student_set.add(s6) 
    # 方法二:新增学生与外键
    d1.student_set.create(s_name='超人') 
    return HttpResponse('成功')

查询

from .models import Department,Student
def test(request):
    d1 = Department.objects.get(d_id=3)
    s6 = Student.objects.get(s_id=4)

    # 学生找课程
    d_name = s6.department.d_name

    # 课程找学生
    print(d1.student_set.all()) # 多个学生
    # 指定查询
    print(d1.student_set.get(s_id=1))
    return HttpResponse(d_name)

删除

def test(request):
    d1 = Department.objects.get(d_id=3)
    s6 = Student.objects.get(s_id=4)
    d1.student_set.remove(s6) # 指定删除
    d1.student_set.clear() # 全部删除

    return HttpResponse('ok')

4.11 一对一

from .models import Department,Student,Student_detail
def test(request):
    stu = Student_detail.objects.get(id=1)
    s6 = Student.objects.get(s_id=5)
    name = stu.student.s_name # 通过学生详情找学生
    print(s6.student_detail) # 学生找详情,单个
    return HttpResponse(name)

4.12 多对多

rom .models import Department,Student,Student_detail,Course
def test(request):
    # 课程
    c1 = Course.objects.get(c_id=1)
    c2 = Course.objects.get(c_id=2)
    c3 = Course.objects.get(c_id=3)

    # 学生
    s2 = Student.objects.get(s_id=2)
    s3 = Student.objects.get(s_id=3)
    s4 = Student.objects.get(s_id=4)

    # 增加 - 学生报名课程
    s2.course_set.add(c1,c3)
    s3.course_set.add(c2)
    s4.course_set.add(c3)

    # 查询
    print(s2.course_set.all()) # 查询学生报了的课程
    print(c1.student.all()) # 查询哪里学生报名了c1

    # 删除
    s2.course_set.remove(c1) # 学生删除课程
    c2.student.remove(s3) # 课程删除学生
    s2.course_set.clear() # 学生删除所有课程
    return HttpResponse('add')

4.13 聚合查询

from .models import Student_detail
from django.db.models import Count,Avg,Max,Min,Sum
def test(request):
    rs = Student_detail.objects.all().aggregate(Avg('s_age')) # 平均年龄
    rs = Student_detail.objects.all().aggregate(Max('s_age')) # 最大值
    rs = Student_detail.objects.all().aggregate(Min('s_age')) # 最小值
    rs = Student_detail.objects.all().aggregate(Sum('s_age')) # 求和
    rs = Student_detail.objects.all().aggregate(Count('s_age')) # 求数量
    
      # 学生按照学院分组
    # values 以键值对的形式展示
    res = Student.objects.values('department').annotate(Count('department'))
    # 获取结果的数量
    res = Student.objects.values('department').annotate(Count('department')).values('count')
    print(rs)
    return HttpResponse('add')

4.14 FQ查询

F查询:针对两个字段值的比较

Q查询:如果你需要执行更复杂的查询(例OR语句)

  • 可以使用&(and)、|(or)操作符组合
  • ~(not)操作符在Q对象前表示取反
from .models import Student_detail, Student
from django.db.models import F,Q

def test(request):
    # 给学生详情的每个学生年龄+1
    # 查询s_age值 + 1
    Student_detail.objects.all().update(s_age=F('s_age') + 1)
    
     # 或
    rs = Student.objects.filter(Q(s_name='毛不易')|Q(s_name='超人'))

    # 且
    rs = Student.objects.filter(Q(s_name='毛不易') & Q(s_id=2))

    # 取反
    rs = Student.objects.filter(~Q(s_name='毛不易'))
    return HttpResponse('add')

05 请求与相应

5.1 请求参数

def getparams(request):
    print(request.path) # 请求url
    print(request.method) # 请求方法
    print(request.encoding) # 编码格式
    
    return HttpResponse('分路由appbook')

5.2 表单防止跨域

<!-- action没写具体提交地址,用什么地址进来,就会到什么地址去 -->
<form action='' method='post'>
    {% csrf_token %} {# 防止跨域请求 #}
    <input type='text' name='a' />
    <input type='text' name='b' />
    <input type='submit' value='提交' />
</form>

5.3 获取参数

get()

  • 根据键获取值,只能获取一个值

getlist()

  • 根据键获取值,以列表的形式返回
def getParams(request):
    # 根据请求类型判断要做的事
    if request.method == 'GET':
        return HttpResponse('GET')
    elif request.method == 'POST':
        # 获取post参数值
        title = request.POST.get('title') # 获取post的title值
    
   return HttpResponse('分路由appbook')

post参数获取

 def post(self, request):
    postBody = json.loads(request.body)
    username = postBody.get("username") # 不存在返回默认值none,默认值可设置
    password = postBody.get("password")
    phone = postBody.get("phone")

获取表单值

cleaned_data # 就是读取表单返回的值,返回类型为字典dict型
email=cleaned_data['username']  # 读取name为username的表单值

5.4 类视图

from django.urls import path
from . import views

urlpatterns = [
    path('test/', views.Test.as_view()),
]
from django.views import View
class Test(View):
    def get(self,request):
        return HttpResponse('GET')
    def post(self, request):
        # 获取post参数值
        title = request.POST.get('title')  # 获取post的title值
        return HttpResponse(title)

5.5 文件上传

上传配置

settings.py

MEDIA_ROOT = os.path.join(BASE_DIR,'static/media')
# static/media 创建文件夹
# enctype 上传文件必须写的参数
<form method='post' action="" enctype='multipart/form-data'>
        {% csrf_token %}
        <input type='file'  name='file' />
        <input type='submit'  value='上传' />
</form>

视图

from django.views import View
import os
from djangoStudy.settings import MEDIA_ROOT

class Upload(View):
    def get(self, request):
        return render(request, 'djangoStudy/index.html')

    def post(self, request):
        print('进来了')
        f1 = request.FILES.get('file')  # 获取上传的文件
        print(f1.name)  # 上传文件名字
        f_name = os.path.join(MEDIA_ROOT, f1.name)  # 拼接路径,创建文件
        # 上传的文件是二进制
        with open(f_name, 'wb') as f:
            # 读取里面的文件,读一行写一行
            for i in f1.chunks():
                f.write(i)  # 写入文件
        return HttpResponse('ok')

5.6 session

设置session

  • 无指定两星期后过期
  • value是整数则会话将在value秒后过期
  • 若value是一个imedelta对象,则在当前时间加上这个指定时间/日期过期
  • 若value为9,关闭浏览器过期
def setsession(request):
    
    request.session['username'] = 'username'
    request.session.set_expiry(0)
    return HttpResponse('setsession')

获取session

def getsession(request):
    username = request.session.get('getsession','default') # 不存在去默认值default
    return HttpResponse(username)

删除session并删除会话 / 退出登陆

def deletesession(request):
    # 删除seccion并删除会话
    request.session.flush()
    return HttpResponse('deletesession')

5.7 表单验证

创建用户表

from django.db import models

# Create your models here.
class UserModel(models.Model):
    username = models.CharField(max_length=30,unique=True)
    password = models.CharField(max_length=100)
    email = models.EmailField()

在book里窗户form.py并配置表单检测

from django import forms

# 验证表单
class RegForm(forms.Form):
    username = forms.CharField(max_length=30,min_length=2)
    password = forms.CharField(
        max_length=30,
        min_length=1,
        widget=forms.PasswordInput(attrs={"placeholder":'请输入密码'}) # 密码为空
    )
    password_repaet = forms.CharField(max_length=30,min_length=1,widget=forms.PasswordInput(attrs={"placeholder":"请输入密码"}))
    email = forms.EmailField()

注册路由

from django.urls import path
from . import views

urlpatterns = [
    path('reg/', views.Register.as_view()),
]

添加模版

from django.views import View
from .models import UserModel
from .forms import RegForm

class Register(View):
    def get(self, request):
        form = RegForm()
        return render(request, 'book/reg.html', context={'form': form})

    def post(self, request):
        form = RegForm(request.POST) # 获取表单数据
        print(form.is_valid())
        # 验证表单数据是否正确
        if form.is_valid():
            # 那数据
            username = form.cleaned_data.get('username')
            password = form.cleaned_data.get('password')
            password_repaet = form.cleaned_data.get('password_repaet')
            email = form.cleaned_data.get('email')
            if password == password_repaet:
                UserModel.objects.create(
                    username=username,
                    password=password,
                    email=email,
                )
                return HttpResponse('注册成功')
            else:
                return HttpResponse('两次密码不一样')

提交标题

<body>
    <form action='' method="post">
        {% csrf_token %}
        
        <!-- 表单的实例 -->
        {{ form.as_p }}
        <input type="submit" value="注册"/>
    </form>
</body>

5.8 表单传递参数

# views.py
# 添加参数request
 form = forms.RegisterForm(data=dict_data, request=request)
    
# forms.py 添加继承
class LoginForm(forms.Form):
    #...
     def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request', None)
        super(LoginForm, self).__init__(*args, **kwargs)

5.9 ModelForm 继承模型表单

from django.core.validators import MinLengthValidator
from utils.models import ModelBase

class Articles(ModelBase):
    """
    文章
    """
    title = models.CharField(
        max_length=150,
        validators=[MinLengthValidator(1)],
        verbose_name="标题",
        help_text="标题"
    )
    digest = models.CharField(
        max_length=200,
        validators=[MinLengthValidator(1)],
        verbose_name="摘要",
        help_text="摘要"
    )
    content = models.TextField(
        verbose_name="内容",
        help_text="内容"
    )
    clicks = models.IntegerField(
        default=0,
        verbose_name="点击量",
        help_text="点击量"
    )
    image_url = models.URLField(
        default="",
        verbose_name="图片url",
        help_text="图片url"
    )
    tag = models.ForeignKey('Tags', on_delete=models.SET_NULL, null=True)
    author = models.ForeignKey('users.Users', on_delete=models.SET_NULL, null=True)

    class Meta:
        ordering = ['-update_time', '-id']  # 排序
        db_table = "tb_article"  # 表名
        verbose_name = "文章"
        verbose_name_plural = verbose_name  # 显示的复数名称

    def __str__(self):
        return self.title

forms.py

from django import forms
from articles.models import Articles, Tags


# ModelForm 继承模型表单
class ArticlesForm(forms.ModelForm):
    # 重写覆盖
    image_url = forms.URLField(
        label="文章图片url",
        error_messages={"required": "文章图片url不行为空"}
    )

    # ModelChoiceField 选项框
    tag = forms.ModelChoiceField(
        # 选择的范围
        queryset=Tags.objects.only('id').filter(is_delete=False),
        error_messages={
            "required": "文章标签id不能为空",
            "invalid_choice": "文章标签id不存在"
        }
    )

    class Meta:
        # 与数据库模型关联
        model = Articles
        # 需要关联的字段
        fields = ['title', 'digest', 'content', 'image_url', 'tag']
        error_messages = {
            'title': {
                'max_length': "文章标题长度不能超过150",
                'min_length': "文章标题长度大于1",
                'required': "文章标题不能为空"
            },
            'digest': {
                'max_length': "文章摘要长度不能超过150",
                'min_length': "文章摘要长度大于1",
                'required': "文章摘要不能为空"
            },
            'content': {
                'required': "文章内容不能为空"
            },
        }

获取表单数据save前添加数据,加入数据库

 def post(self, request):
        try:
            json_data = request.body.decode()
            # 参数为空判断
            if not json_data:
                return result_json(msg="参数为空")
            dict_data = json.loads(json_data)
        except Exception as e:
            logging.info("错误信息:\n{}".format(e))
            return result_json(msg="参数错误")

        # 表单验
        form = forms.ArticlesForm(data=dict_data)
        if form.is_valid():
            # 获取表单验证完成的数据集
            # commit不插入mysql数据库,当save时,为后续添加方便
            article_instance = form.save(commit=False)
            article_instance.author = request.user.id
            # article_instance.author = request.user 形式二
            article_instance.save()
            return result_json(code=0, msg="提交成功")
        else:
            err_str = regular.get_err(form)
            return result_json(msg=err_str)

06 中间键

6.1 生命周期

# 执行视图之前调用,在每个请求上调用,返回None或者HttpResponse对象
process_request(self,request)

# 调用视图之前被调用,在每个请求上调用,返回None或者HttpResponse对象
process_view(self,request,callback,callback_args,callback_kwargs)

# 在视图刚好执行完毕之后被调用,再每个请求上调用,返回实现了render方法的相应对象
process_template_response(self,request,response)

# 当视图抛出异常时调用,在每个请求上调用,返回一个HttpResponse对象
process_exception(self,request,exception)

# 所有相应返回浏览器之前被调用,在每个请求上调用,返回一个HttpResponse对象
process_response(self,request,response)

6.2 添加中间键

在主目录djangoStudy下创建mymiddleeware.py

from django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixin

class MyException(MiddlewareMixin):
    # 接收抛出的异常
    def process_exception(self, request, exception):
        return HttpResponse(exception)

setting.py 注册中间键

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
     'djangoStudy.mymiddleeware.MyException', # 注册:文件夹.文件.类名
]

6.3 中间键例

class UserMiddleware(object):
    def __init__(self,get_resp):
        self.get_resp = get_resp

    # 用户调用函数时响应
    def __call__(self, request):
        username = request.session.get('username','xxx')
        if username:
            # 给类设置属性与值
            setattr(request,'myuser',username)
            print('这是到达视图函数之前的代码')

        # 给视图返回请求的方法
        response = self.get_resp(request)
        print('这是响应之后的代码')
        
        return response

模版可以直接调用

<body>
	{{ request.myuser }} <!-- xxx -->
</body>

6.7 上下文管理器

所有页面都可以用此数据

在主目录djangoStudy下创建mycontext.py

def my_user(request):
    username = request.session.get('username','不存在')
    return {'myuser':username}

在settings.py模版中添加上下文管理器

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'djangoStudy.mycontext.my_user', # 注册
            ],
        },
    },
]

模版可以直接调用

<body>
	{{ myuser }}
</body>

07 admin后台

7.1 后台管理配置

在mysql_test/url.py注册

from django.contrib import admin

urlpatterns = [
    path('admin/', admin.site.urls), # 后台管理
]

7.2 创建管理员

python manage.py createsuperuser

7.3 切换中文模式

settings.py

LANGUAGE_CODE = 'en-us'
# 改为
LANGUAGE_CODE = 'zh-hans'

7.4 注册表到admin

把原来mysql_test里的model.py注册到admin.py

from django.contrib import admin
from .models import Course,Student_detail,Student,User

# Register your models here.
admin.site.register(Course)
admin.site.register(Student_detail)
admin.site.register(Student)
admin.site.register(User)

7.5 自定义管理页面

列表页属性

list_display #显示字段,可以点击列头进行排序
list_display_links # 可以点击修改
list_filter #过滤字段,过滤框会出现在右侧
search_fields #搜索字段,搜索框会出现在上册
list_per_page #分页,分页框会出现在下册

添加修改页属性,二选一

fields # 属性的先后顺序
fieldsets # 属性分组

例:admin.py

from django.contrib import admin
from .models import Course, Student_detail, Student, Department


class DepartmentAdmin(admin.ModelAdmin):
    list_display = ['d_id', 'd_name']  # 显示的字段
    list_display_links = ['d_id', 'd_name']  # 点击修改字段
    list_per_page = 2  # 分页数量


admin.site.register(Department, DepartmentAdmin)

08 auth系统

8.1 auth数据表

  • User

    User是auth模块中维护用户信息的关系模型(继承了models.Model),数据库中该表被命名为auth_user

  • Group

    User对象中有一个名为group的多对多字段,多对对关系由auth_user_groups数据表维护。Group对象可以通过user_set反向查询用户组中的用户

  • Permission

    Django的auth系统提供了模型级的权限控制,即可以检查用户是否对某个数据表拥有增(add),改(change),删(delete)权限

8.2 User模型常用属性与方法

  • 属性

    • user 用户名
    • email 邮箱
    • groups 多对多的组
    • user_permissions 多对多的用户权限
    • is_staff 是不是admin的管理员
    • is_active 是否激活,判断该用户是否可用
    • is_superuser 是否是超级用户
    • last_login 上次登录时间
    • date_joined 注册时间
    • is_authenticated 是否验证通过
    • is_anonymous 是否是匿名用户
  • 方法

    • set_password(now_password) 设置密码,传入原密码
    • check_password(now_password) 检查密码
    • has_perm(perm) 判断用户是否有某个权限
    • has_perms(perm_list) 判断用户是否有权限列表中的某个列表

8.3 认证系统功能

  • create_user 创建用户
  • authenticate 验证登录
  • login 保存用户登录状态
  • is_authenticated 判断用户是否登录
  • @login_required 判断用户是否登录的装饰器

创建用户

from django.contrib.auth.models import User,Group,Permission
User.objects.create_user(username=username,password=password)

验证登陆

from django.contrib.auth import login,logout,authenticate
user = authenticate(username=username,password=password) # 存在返回用户数据

保存登陆状态

login(request,user) 

退出登陆

logout(request)

8.4 登陆权限设置

判断用户是否登录的装饰器

from django.contrib.auth.decorators import login_required

@login_required
def blog_index(request):
    # 未登录报错 
    return render(request)


@login_required(name='dispatch')
class blog_index(Views):
    # ...

未登录时返回指定的路径,在settings.py配置

LOGIN_URL = '/login'

8.5 博客权限

有无添加博客权限,无权限则跳转到指定路径

视图函数方法

from django.contrib.auth.decorators import permission_required
# app标签.权限
@permission_required('blog.add_blogmodel')
def blog_add(request):
    if request.method == 'GET':
        return render(request,'blog/demo_add.html')

类视图方法

方法一:

from django.contrib.auth.decorators import method_decorator,login_required
@method_decorator(login_required,name='post')# post提交方式
class Blog_add(View)
	def get(self,request):

方法二:

from django.contrib.auth.decorators import method_decorator,permission_required
@method_decorator(permission_required('add_blogmodel'),name='post')# post提交方式
class Blog_add(View)
	def get(self,request):

有无删除博客权限,无权限则跳转到指定路径

@permission_required('blog.delete_blogmodel')
def blog_delete(request,blog_id):
    blog = BlogModel.objects.filter(id=blog_id)
   	if blog:
        blog.delete()
        # 删除完成返回列表
        return redirect(reverse('blog_list'))
    else:
        return HttpResponse('不存在这条博客')

添加权限

from django.contrib.auth.models import User,Permission
def test1(request):
    # 获取用户
    zw = User.objects.filter(username='zhuwei').first()
    # add_blogmodel 添加权限
    # delete_blogmodel 删除权限
    pems = Permission.objects.filter(codename='delete_blogmodel') # 获取权限
    zw.user_permission.add(pems) # 添加权限
    return HttpResponse('权限添加成功')

8.6 类与函数视图装饰器

from django.contrib.auth.decorators import method_decorator
def my_decorator(func):
    def wrapper(request,*args,**kwargs):
        print('这是定义装饰器')
        print('判断用户是否登陆,是否有相关权限')
        return func(request,*args,**kwargs)
    return wrapper

# 类装饰
@method_decorator(my_decorator,name='dispatch')
class IndexView(View):
    # ...
    # 函数装饰器
    @method_decorator(my_decorator)
    def get(self,request):

8.7 判断权限

from django.contrib.auth.mixins import  PermissionRequiredMixin

# 新闻标签
class NewsTagManage(PermissionRequiredMixin, View):
    # 需要的权限
    permission_required = ('news.view_tag', 'news.add_tag')
    raise_exception = True  # 是否规定报错

    # 无权限响应
    def handle_no_permission(self):
        if self.request.method.lower() == 'get':
            return super(NewsTagManage, self).handle_no_permission()
        else:
            return to_json_data(err_msg='没有权限')

09 分页

9.1 实例化

from django.core.paginator import Paginator,PageNotAnInteger,EmptyPage
def page_test(request):
    course = ['C++','python','java','php','C','C#','挖掘机','Go']
    # 2分页的数量
    p = Paginator(course,2) # 实例分页对象

    return HttpResponse('ok')

9.2 分页属性

print(p.count) # 对象总数量
print(p.num_pages) # 总页数
print(p.page_range) # 页码范围 [1,2) 
print(p.per_page) # 每一页显示的数量

# 获取第一页
page1 = p.page(1)
print(page1.object_list) # 页码里面的数据
print(page1.number) # 获取页码,第一页

9.3 分页方法

page1 = p.page(1)

print(page1.has_next()) # 查看当前页有没有下一页,返回布尔值
print(page1.has_previous()) # 查看当前页有没有上一页,返回布尔值
print(page1.has_other_pages()) # 查看当前页有没有上一页或下一页,返回布尔值
print(page1.next_page_number()) # 下一页的页码
print(page1.previous_page_number()) # 上一页的页码
print(page1.start_index()) # 当前页的第一个索引对象
print(page1.start_index()) # 当前页的最后一个个索引对象

9.4 实例

from django.core.paginator import Paginator,PageNotAnInteger,EmptyPage

def blog_list(request):
    blog_list = User.objects.all()
    p = Paginator(blog_list,3) # 分页实例化对象
    page = request.GET.get('page')
    try:
        pages = p.page(page)
    except PageNotAnInteger:
        pages = p.page(1) # 值不对,默认第一页
    except EmptyPage:
        pages = p.page(p.num_pages) # 页码出错

    return HttpResponse('title')

补充知识

Django 2.2.2.dev20190508124537 文档 ========================== Django 文档 你所需要知道的关于 Django 的一切。 获取帮助 遇到问题?我们可以帮你! 试试 FAQ —— 这里有很多常见问题的解答。 正在寻找特定的信息?试试 索引,模块索引 或者 详细内容目录。 在 django-users 邮件列表的档案库搜索,或者 post a question。 在 #django IRC channel 频道提问 在我们的 ticket tracker 报告关于 Django 的 Bug。 这份文档是如何组织的 Django 有丰富的文档。一份高度概述的文档会告诉你在哪里找到特定的东西: 教程 通过手把手地方式教你一步步的创建一个 Web 应用。如果你初学 Django 或编程,请从这里开始。也请看看下面的 "快速入门"。 专题指南 在相当高的层次上介绍关键主题和概念,并提供有用的背景信息和解释。 参考指南 包含 API 和 Django 各个工作机制方面的技术参考。它们介绍了 Django 是如何工作,如何被使用的。不过,你得先对关键字的概念有一定理解。 操作指南 是一份目录。它们以排列好的关键问题和用例的方式指导你。它们比教程更加深入,且需要你先了解一些关于 Django 是如何工作的知识。 快速入门 您是刚学 Django 或是初学编程? 这就是你开始学习的地方! 从零开始: 概要 | 安装 入门教程: 第1节: 请求和响应 | 第2节: 模型和 admin 站点 | 第3节: 视图和模板 | 第4节: 表单和通用视图 | 第5节: 测试 | 第6节: 静态文件 | 第7节: 自定义 admin 站点 进阶教程 : 如何编写可复用的应用 | 提交你的第一个 Django 补丁 模型层 Django 提供了一个抽象的模型 ("models") 层,为了构建和操纵你的Web应用的数据。阅读下面内容了解更多: 模型: 模型介绍 | 字段类型 | 索引 | Meta 选项 | Model 类 QuerySet: 执行查询 | QuerySet 方法参考 | 查询表达式 Model 实例: 实例方法 | 访问关联的对象 迁移: 迁移概述 | 操作参考 | SchemaEditor | 编写迁移 高级: 管理员 | 原始 SQL | 事务 | 聚合 | 搜索 | 自定义字段 | 多个数据库 | 自定义查询 | 查询表达式 | 条件表达式 | 数据库函数 其它: 支持的数据库 | 旧数据库 | 提供初始化数据 | 优化数据库访问 | PostgreSQL 的特定功能 视图层 Django 具有 “视图” 的概念,负责处理用户的请求并返回响应。通过以下链接查找所有你需要知道的有关视图的信息: 基础: URL配置 | 视图函数 | 便捷工具 | 装饰器 参考: 内置视图 | Request/response 对象 | TemplateResponse 对象 文件上传: 概览 | 文件对象 | 存储 API | 管理文件 | 自定义存储 基于类的视图: 概览 | 内置显示视图 | 内置编辑视图 | 使用混入 | API 参考 | 扁平化索引 高级: 生成 CSV | 生成 PDF 中间件: 概览 | 内建的中间件类 模板层 模板层提供了一个对设计者友好的语法用于渲染向用户呈现的信息。学习如何使用语法(面向设计者)以及如何扩展(面向程序员): 基础: 概述 对于设计者: 语法概述 | 内建标签及过滤器(filters) | 人性化 针对程序员: 模板 API | 自定义标签(tags)和过滤器(filters) 表单 Django 提供了一个丰富的框架来帮助创建表单和处理表单数据。 基础: 概览 | 表单 API | 内建字段 | 内建 widgets 进阶: 针对模型的表单 | 整合媒体 | 表单集 | 自定义验证 开发进程 学习众多的组件及工具,来帮助你开发和测试 Django 应用: 设置: 概览 | 完整的设置列表 应用程序: 概览 异常: 概览 django-admin.py 和 manage.py: 概览 | 添加自定义命令 测试: 介绍 | 书写并运行测试 | 包含的测试工具 | 高级主题 部署: 概览 | WSGI 服务器 | 部署静态文件 | 用 email 跟踪代码错误 管理 找到所有你想知道的,关于自动化管理界面的知识,Django 最受欢迎的特性之一: 管理站点 管理动作 管理文档生成器 安全 在 Web 应用的发展中,安全是最重要主题,Django 提供了多种保护手段和机制。 安全概览 在 Django 中披露的安全问题 点击劫持保护
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值