Django2开发必备技术点总结(一)

Django2开发必备技术点总结(一)

主要基于Django2.0.1为大家总结其中的核心技术,如果全部掌握则具备开发Web项目的能力。

为了更好的学习其知识点,我已在B站上传相关的视频:https://space.bilibili.com/485885102/channel/detail?cid=111581。如果在学习的过程中遇到问题,可以以QQ(610039018)方式沟通。

一、 Django入门

1.1 基本概念

1.2 创建环境与app项目

安装依赖包

pip install django==2.0.1 -i https://mirrors.aliyun.com/pypi/simple

【注意】如果Python版本(3.7.4+)很高时,SQLite3版本同样很高,则django版本建议使用django==2.1.5+;因为,admin.site 站点管理时,会报auth_user_old表不存在的错误。

进入"终端" CMD命令, 通过 django-admin 命令创建django项目。

django-admin startproject helloDjango

通过django-admin命令创建app应用

django-admin startapp  mainapp

在一个Django项目中,存在很多的app应用(模块), 创建好的app需要注册到主工程中(settings.py)

Django中常用的命令包括:

  • django-admin startproject 创建django项目
  • django-admin startapp 创建django的app模块
  • python manage.py makemigrations 基于settings中配置的DATABASE数据default方案生成迁移脚本
  • python manage.py migrate 开始迁移
  • python manage.py createsuperuser 创建admin站点的超级用户
  • python manage.py runserver 启动django服务,默认端口是8000, host为127.0.0.1

1.3 django项目结构

项目结构如下:

helloDjango
		|--- helloDjango   主工程目录
				 		|----  settings.py   # 设置文件, 数据库连接、app注册、中间件及模板配置
				 		|----  urls.py       # 总路由
				 		|----  wsgi.py       # Django实现wsgi的脚本
            |----  __init__.py
		|--- mainapp      应用模块(主)
						|----  __init__.py
						|---- admin.py      # 后台管理配置脚本
						|---- models.py     # 数据模型类声明所在脚本
						|---- views.py      # 声明当前应用的视图处理函数或类
						|---- urls.py       # 自已增加的当前应用模块的子路由
						|---- tests.py      # 当前应用模块的单元测试类
						|---- apps.py       # 声明当前应用的基本信息
		|--- manage.py     WEB应用的启动脚本, 项目工程的入口

1.4 Django请求流程

1. 到urls分发器 (总urls.py -> 子路由)
2. urls分发器根据路由规则(正则)分发到views
3. views去调用Model,交互数据
4. views将数据渲染到模板中
5. 模板呈现给用户

二、 数据库连接与ORM模型

2.1 数据库连接配置

默认是sqlite3数据库, 在使用ORM模型之前,需要先生成迁移文件,再执行迁移命令,在数据库中生成这些模型对应的表。

  • 先生成迁移文件
python manage.py  makemigrations
  • 开始迁移(生成表、 修改表、删除表)
python manage.py migrate

注意: 一旦生成了迁移文件并且迁移成功之后,不要删除迁移文件。

2.2 初步使用ORM模型

在app模块中的models.py 定义一个用户(客户)模型

from django.db import models

class UserEntity(models.Model):
     # 默认情况下会自动创建id主键
     name = models.CharField(max_length=20)
     age = models.IntegerField(default=0)
     phone = models.CharField(max_lengt=11)
     
     class Meta:
     		 # 指定当前模型类映射成哪一个表
     		 db_table = 'app_user'

模型创建完成后,先后执行生成迁移文件和迁移。

2.3 CURD操作

查询 READ

UserEntity.objects.all()  # 查询所有, list
UserEngtity.objects.get(pk=id)  # 根据主键值查询一个实体对象

增加 CREATE

u = UserEntity()
u.name = 'disen'
u.age = 20
u.phone = '177'

# 保存模型对象
u.save()

删除Delete

u = UserEntity.objects.get(1)
u.delete()  # 删除

更新Update

u = UserEntity.objects.get(3)
u.name = '李成'
u.save()

三、站点管理

注意:确定数据库已迁移

3.1 创建超级用户

python manager.py createsuperuser

​ 根据提示输入用户名、邮箱和口令
​ 启动服务后,可以在/admin页面进行登录

3.2 定制admin管理

3.2.1 注册自己的模块

在自己模块的admin.py文件中

admin.site.register(Store)

3.2.2 自定义表单

在admin.py文件中,定义admin.ModelAdmin的子类
1) 效果: 添加Store的表单中只添加name

class StoreAdmin(admin.ModelAdmin):
	fields = ('name',)
	
admin.site.register(Store, StoreAdmin)

2) 效果: 分栏显示

class StoreAdmin(admin.ModelAdmin):
      fieldsets = (['Main', {'fields': ('name',)}],
                   ['Advance', {'fields': ('address',),
                                'classes': ('collapse',)}])

3) 效果: 内联显示

# 为外表创建内联类
class FruitInline(admin.TabularInline):
    model = Fruit
			
# 在主表设置内联
class StoreAdmin(admin.ModelAdmin):
    inlines = [FruitInline]

3.2.3 列表显示与搜索

# 在admin.ModelAdmin的子类中
class StoreAdmin(admin.ModelAdmin):
    list_display = ('id', 'name','address')  # 列表显示
    search_fields = ('name','address')  # 搜索关键字的字段

admin.site.register(Store, StoreAdmin)

四、 综合案例-水果管理

3.1 模型设计

# Fruit 水果模型类(name, price, source, cate_type_id)
# FruitImage 水果图片模型类(fruit_id, url, width, height, name)
# CateType 水果分类(name, order_num)

# Store 水果商店(name,name,boss_name, phone, address, city, lat, lon)
# StoreDetail 水果商店的详情

3.2 模板的基本使用

循环语句块

{% for item in items %}
	
{% endfor %}

分支循环

{% if 条件表达式 %}

{% endif %}

变量

{{ 变量名 }}

在views.py视图函数中,渲染模板

return render(request, 'fruit/list.html', locals() )

3.3 页面设计

{% block name %}

{% endblock %}
{% extends "base.html" %}

五、ORM快速应用

5.1 字段类型

  • CharField

    字符类型,必须指定max_length属性

  • IntegerField

    数值类型,可以指定chiose为元组,表示选择范围

  • BooleanField

    布尔类型, 数据表中表现是0 或 1

  • NullBooleanField

    可以为空的布尔值

  • AutoField

    自增列 int类型。必须填入参数 primary_key=True;可选auto_create自增

  • FloatField

    浮点类型

  • DecimalField

    同Python的Decimal类型,参数有

    • max_digits 最大总位数
    • decimal_places 小数点后的位数
  • TextField

    文本类型

  • UUIDField

    字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证

    class Order(models.Model):
        no = models.UUIDField(verbose_name='订单编号')
        price = models.DecimalField(verbose_name='订单金额',max_digits=6, decimal_places=2)
        pay_state = models.BooleanField(default=False)
    

    使用Order创建对象(数据库增加数据)方式如下:

    import uuid
    Order.objects.create(no=uuid.uuid4(),price=1819.567,pay_state=True)
    # price只保留两位小数,会自动四舍五入			
    
  • FileField

    字符串,路径保存在数据库,文件上传到指定目录
    参数有如下内容:

    upload_to = ""      上传文件的保存路径
    storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
    
  • ImageField
    字符串,路径保存在数据库,文件上传到指定目录
    参数有:

    upload_to = ""      上传文件的保存路径
    storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
    width_field=None,   上传图片的高度保存的数据库字段名(字符串)
    height_field=None   上传图片的宽度保存的数据库字段名(字符串)
    
  • DateField
    日期类型
    格式:YYYY-MM-DD
    参数
    auto_now
    每次保存时,自动设置当前字段为当前时间
    用于“最后一次修改时间”
    auto_now_add
    对象每一次保存时,自动设置为当前时间
    用于“创建时间”
    注意
    auto_now和auto_now_add及default只能设置一个,不能组合

  • DateTimeField
    日期时间类型
    datetime.datetime
    日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]

  • TimeField
    时间类型
    格式: HH:MM[:ss[.uuuuuu]]

5.2 约束

  • max_length
    最大长度

  • default
    默认值

  • unique
    唯一

  • primary_key
    主键

  • null
    不为null
    False, 不能为null
    默认
    True , 可以为null

  • blank
    是否允许用户输入为空
    即空字符串

  • db_index
    索引

  • db_column
    指定字段名

  • verbose_name
    在admin显示的字段名称

  • choices
    一个包含双元素元组的可迭代的对象,用于给字段提供选项

    sex_l = (
          (1,'男'),
          (2,'女')
    )
    sex = color = models.IntegerField(choices=sex_l, defalut=1)
    

5.3 FileField和ImageField

文件字段和图片字段都属性MEDIA的多媒体类型的文件,需要在settings.py设置脚本文件中指定MEDIA_ROOT、MEDIA_URL、STATIC_URL, STATICFILES_DIRS

使用ImageField时,必须安装Pillow库

pip install pillow

扩展: github: https://github.com/disenQF/StoreOA.git

5.4 模型的Meta元信息

在模型类中,声明内部类 Meta, 类成员可以如下的变量:

  • db_table
  • ordering
  • verbose_name
  • verbose_name_plural
  • unique_together
  • abstract 布尔类型,表示当前的模型类是否为抽象类,如果抽象类,则不会创建表

六、CURD深度使用

6.1 模型类的objects

默认情况下,由创建模型类的元类在模型类中创建django.db.models.Manager类的对象,并赋给objects。Manager类实际是QuerySet类的子类。

我们可以在模型类中, 创建objects, 但是必须为Manager类对象。不能是普通的字段。

class CateTypeEntity(models.Model):
     name = models.CharField(max_length)
     # objects = models.IntegerField(default=0)  # 错误的写法
     objects = models.Manager()  # 正确的写法

6.2 filter和exclude查询

模型类.objects.filter(属性名__条件=条件值)
模型类.objects.filter(属性名=条件值)
模型类.objects.filter(属性名__时间属性__条件=条件值)

条件包含

  • 大于 gt、小于 lt、大于等于 gte、小于等于lte
  • 字符串相关: contains 包含(区分大小写), icontains, (i)startswith, (i)endswith
  • null相关: isnull(), isnotnull()
  • 范围: in

时间属性包含

  • year, month, day
  • hour, minute, second

6.3 QuerySet对象的方法

QuerySet对象的本身是可以被迭代的。

返回QuerySet对象的方法有

  • filter()
  • exclude()
  • all()
  • values()
  • values_list()
  • order_by(‘name’, ‘-city’)

统计方法和判断是否存在数据方法

  • count()
  • exists()

6.4 聚合函数类

django.db.models.Count/Avg/Max/Min/Sum与QuerySet的aggregate()组合使用。

七、F和Q的用法

7.1 F的选择字段值

django.db.models.F 用于获取字段的值并参于计算或作业更新条件。

# 中秋节: 全场水果打8.8折扣
FruitEntity.objects.update(price=F('price')*0.88)

7.2 Q的多条件

Q是用来指定多个查询条件的逻辑关系: 且 & , 或 | , 非 ~

 # 查询价格低于1的,或高于200的水果, 或源产地是西安且名字中包含"果"
 fruits2 = FruitEntity.objects.filter(
        Q(price__lte=1) | Q(price__gte=200) | Q(Q(source='西安') & Q(name__contains="果"))).values()

八、原生的SQL语句查询

针对复杂查询来说, 通过QuerySet查询不是特别方便,则使用原生的SQL查询。

  • QuerySet提供两种原生SQL查询:

    • QuerySet.raw()

      要求: 查询的字段必须是模型类中声明的字段,且必须存在主键列 。查询的结果是RawQuerySet类对象,可以迭代,元素类型是模型类对象。

      另外, 查询sql语句中可以使用 “%s” 占位符, 在其它可以使用元组参数传值

    raw_queryset = FruitEntity.objects.raw('select id, name,price from t_fruit where price < %s  order by price DESC LIMIT %s, 10', (10, 0))
    
    for fruit in raw_queryset:
        print(fruit)
    
    • QuerySet.extra()

      extra()扩展查询, 针对QuerySet查询结果集中,额外增加查询条件或排序等相关操作。返回结果还是QuerySet对象

    qs1 = FruitEntity.objects.extra(where=['price<%s'], params=['10'])
    qs2 = FruitEntity.objects.extra(where=['price<%s or name like %s'], params=['2', '果'])
    qs3 = FruitEntity.objects.extra(where=['price<%s or name like %s', 'source=%s'], params=['2', '果', '西安'])
    
  • 使用django.db.connection数据库连接对象进行原生SQL查询

    connection对象表示与数据库连接的对象, 可以通过connection连接对象获取游标cursor对象,再通过cursor的execute()/fetchall()/rowcount相关方法或函数来执行原生的SQL和执行的结果。

    cursor = connection.cursor()
    cursor.execute('select * from t_fruit')
    for row in cursor.fetchall():
        print(row)
    
    cursor.execute('update t_fruit set price=2 where id=1')
    print(cursor.rowcount)
    connection.commit()  # 提交更新
    

九、模型类之间的关系

9.1 显性创建objects

class OrderManager(models.Manager):
     def get_queryset(self):
     		 return super().get_queryset().filter(~models.Q(pay_status=5))
# 统计2018年全年销售总额
OrderModel.objects.filter(create_time__year=2018) \
          .aggregate(total_price=Sum('price'))

9.2 一对一关系

一对一的关系可以通过models.OneToOneField(关联模型类, on_delete=models.CASCADE)建立,

on_delete除了CASCADE级联删除之外,还有model.SET_NULL级联设置为null。

class RealProfile(models.Model):
    # 声明一对一的关联关系
    user = models.OneToOneField(UserEntity,
                                verbose_name='账号',
                                on_delete=models.CASCADE)

    real_name = models.CharField(max_length=20,
                                 verbose_name='真实姓名')
    number = models.CharField(max_length=30,
                              verbose_name='证件号')

    real_type = models.IntegerField(verbose_name='证件类型',
                                    choices=((0, '身份证'),
                                             (1, '护照'),
                                             (2, '驾驶证')))

    image1 = models.ImageField(verbose_name='正面照',
                               upload_to='user/real')
    image2 = models.ImageField(verbose_name='反面照',
                               upload_to='user/real')

主表: 用户表 , 从表: 实名认证表

从表对象获取 主表的数据

u1 = RealProfile.objects.filter(real_name='狄清').first()
u1.user.phone # 直接访问主表对象的数据

主表中获取从表的数据

login_u1 = UserEntity.objects.get(pk=1)
# 以隐性方式 读取从表的数据:  对象.关联模型类全小写名称.属性
login_u1.realprofile.number  # realprofile 一对一的关系模型类的名称(全小写)

9.3 一对多或多对一的关系

# 声明水果商品与购物车的关系表
class FruitCartEntity(models.Model):
    cart = models.ForeignKey(CartEntity,
                             on_delete=models.CASCADE,
                             verbose_name='购物车')

    fruit = models.ForeignKey(FruitEntity,
                              on_delete=models.CASCADE,
                              verbose_name='水果名')
    cnt = models.IntegerField(verbose_name='数量',
                              default=1)

    def __str__(self):
        return self.fruit.name +':'+self.cart.no

    @property
    def price1(self):
        # 属性方法在后台显示时没有verbose_name, 如何解决?
        return self.fruit.price  # 从获取主的对象属性

    @property
    def price(self):
        # 属性方法在后台显示时没有verbose_name, 如何解决?
        return round(self.cnt*self.fruit.price, 2)

    class Meta:
        db_table = 't_fruit_cart'
        verbose_name_plural = verbose_name = '购物车详情表'
# 主读取多个从对象的信息
login_u = UserEntity.objects.get(pk=1)
 # 查询当前用户的购物车中的所有商品及数量相关的信息
cart_fruits = login_u.cartentity.fruitcartentity_set.all() 
for fruit_cart in cart_fruits:
    print(fruit_cart.fruit.name, fruit_cart.fruit.price, fruit_cart.cnt)

9.4 多对多

django提供models.ManyToManyField 字段,来实现多对多的关系,需要第三方表的外键来实现。

如需求: 用户收藏商品, 需要建立第三方表,完成用户收藏多个商品, 或一个商品被多位用户收藏。

在FruitEntity模型类中,增加users属性,内容如下:

# 默认情况下,反向引用的名称是当前类的名称(小写)_set
# 可以通过related_name 来指定
# db_table='t_collect' 使用第三张表建立fruit和user的多对多关系
users = models.ManyToManyField(UserEntity,
                               db_table='t_collect',
                               related_name='fruits',
                               verbose_name='收藏用户列表')

当迁移完成后,模拟用户收藏商品:

u1 = UserEntity.objects.get(pk=1)
u1.fruits.add(FruitEntity.objects.get(pk=1))
u1.fruits.add(FruitEntity.objects.get(pk=2))

u2 = UserEntity.objects.get(pk=2)
u2.fruits.add(FruitEntity.objects.get(pk=2))

查询某一件商品,被哪些用户收藏

fruit1 = FruitEntity.objects.get(pk=2)
fruit1.users.all()

用户取消收藏商品

u1.fruits.remove(FruitEntity.objects.get(pk=1))

练习任务: 增加标签模型类TagEntity(id, name, order_num)并且和商品建立多对多的关系

十、模板语法

10.1 MTV设计中TV的关系

  • V 视图理函数可以渲染(使用)多个模板
  • 一个模板 T 可被任意的V 视图函数使用

10.2 模板的加载过程

模板加载对象: django.template.loader

  • 加载
template = loader.get_template('index.html')
  • 渲染
html = template.render(context)  # context是一个dict类型对象
  • 加载+渲染
html = loader.render_to_string("index.html", context)

10.3 模板中使用 “.” 点语法

使用 “.” 访问变量Variable的属性, 系统尝试以下顺序查询:

  • 字典
  • 属性或方法
  • 列表的数值索引
<h3>{{ msg }}</h3>
<p style="color: green">
    第三个用户名: {{ users.2.name }}
</p>
<p style="color: red;">
    请客的人: {{ error_index }}
</p>
<p style="color: white;background-color:blue;">
    <span>VIP:</span>
    <span>{{ vip.name.upper }}-{{ vip.money }}</span>
</p>
<ul>
    {% for key, value in vip.items %}
       <li>{{ key }} = {{ value }}</li>
    {% endfor %}

</ul>
<ul>
    {% for user in users %}
        <li>{{ user.id }} {{ user.name }}</li>

        {% if forloop.counter0 == error_index %}
            <p style="color: red;">
                请客的人: {{ user.name }}
            </p>
        {% endif %}
    {% endfor %}
</ul>
users = UserEntity.objects.all()
    msg = '最优秀的学员'

    error_index = random.randint(0, users.count()-1)

    vip = {
        'name': 'disen',
        'money': 20000
    }

    # # 加载模板
    # template = loader.get_template('user/list.html')
    #
    # # 渲染模板
    # html = template.render(context={
    #     'msg': msg,
    #     'users': users
    # })

    html = loader.render_to_string('user/list.html',
                                   locals())

    return HttpResponse(html,
                        status=200)  # 增加响应头??

10.4 表达式标签

  • {% if 条件 %} {% endif %}
    • 条件表达式支持关系运算符
      • or
      • and
      • not
      • in
      • == 、 !=、 > 、< 、>=、<=
  • {% ifeqaul 值1 值2 %} {% endifequal %}
  • {% ifnoteqaul 值1 值2 %} {% endifnotequal %}
  • {% for 变量 in 可迭代对象 %} {% endfor %}
    • {% empty %} 当可迭代对象为空(非None), 显示empty标签下面的内容
    • {% cycle 值1 值2 值3 值4 %}
    • {{ forloop.counter }} 循环记数器, 从1开始
  • 注释: 渲染模板之后不会存在的
    • {# 单行注释 #}
    • {% comment %} 多行注释的文本 {% endcomment %}
  • escape 安全标签
    • {% autoescape on|off %} 开启escape时, 会将变量的 大于号、小于号、单引号、双引号及&等转成escape的表示,如大于号为 &gt;
    • {{ info|escape }} escape也可以换成safe 表示不转换escape

10.5 模板的过滤器

  • 数值运算

    • |add:5
    • |add:-5
    • |divisibleby:2
    • {% widthratio 变量 分母 分子 %}
  • 字符串

  • 格式化

    • 日期格式化

      now|date:“Y-m-d H:i:s”

    • 文件大小格式化

      file_size|filesizeformat

    • 小数值格式化

      v|floatformat:n 默认n 是1位小数

  • 列表

  • HTML转义

    {{ html|safe }}   不转义
    
    {{ html|escape }}  转义, 显示html源码标签
    
  • 默认值

10.6 自定义过滤器

在app的__init__.py脚本编写

from django.template.defaultfilters import register
import os

@register.filter('ellipse')
def ellipse(value):
    return os.path.split(value)[-1]

10.7 扩展: os.stat()获取文件大小

file_dir = os.path.join(settings.BASE_DIR, 'mainapp/')
files = {file_name: os.stat(file_dir+file_name)
         for file_name in os.listdir(file_dir)
         if os.path.isfile(file_dir+file_name)}

十一、csrf (防止跨站请求伪造)

11.1 {% csrf_token %} 标签

在 模板的<form>内部使用即可,会生成隐藏字段, 名称为csrfmiddlewaretoken, 它的值是在渲染板块是产生的,并存储在session, 当表单提交到后端时,通过csrfMiddleWare中间件验证。

 <form class="form" method="post">
		{% csrf_token %}
</form>

注意: 只针对post请求

扩展1: make_password和check_password

django.contrib.auth.hashers.make_password
django.contrib.auth.hashers.check_password

扩展2: request.session

session是字典类型

11.2 取消csrf

  • 在settings.py的中间件的配置中,将CsrfViewMiddleware删除
  • @csrf_exempt装饰view处理函数
django.views.decorators.csrf.csrf_exempt

十二、模板布局标签

12.1 block/extends/include

12.2 显示父模板的内容

{{ block.super }}

十三、app模块内部模板

  • 每个app下都可以增加templates目录,存放它自己的模板文件
  • 内部的模板templates目录,不需要在settings.py中设置
  • 如果app模块之外存在templates目录,且在settings.py中已设置,则加载模板时,则优先从此目录中加载模板文件。

十四、URL路由配置

14.1 URL分级

URL分级即是总路由和子路由(app模块的路由)

  • 主工程目录下urls.py
urlpatterns = [
		path('url',  视图函数, name=None),
		path('url/', include('app_label.urls',  namespace=None))  # 包含子路由
]
  • app目录下的urls.py
urlpatterns = [
		path('url',  视图函数, name=None),
]

include的namespace和path的name都在反向解析中使用, 即反向获取url路径: ‘namespace.name’

14.2 url和path两种路由的配置

url()配置兼容Django1.x 的老版本

path() 是Django2之后的路由函数。

from django.urls import path
from django.conf.urls import url

from orderapp import views

urlpatterns = [
    path('list', views.order_list),
    url(r'^list2$', views.order_list)
]

url()支持正则, 通过正则在url路径中向处理函数传参:

url(r'^list2/(?P<city_code>\w+)/(?P<order_num>\d+)$', views.order_list)

以上是按关键传参方式。也可以按位置传参(从左到右),如下所示

url(r'^list2/(\w+)/(\d+)$', views.order_list)
def order_list(request, order_num, city_code):
    print(order_num, city_code)
    return render(request,
                  'list_order.html',
                  locals())

以上的url路由传参可以使用path()的<name>实现, 如:

 path('list/<city_code>/<order_num>', views.order_list),

如果路由中的参数是uuid类型,则使用参数转换器进行匹配, 如

path('cancel/<uuid:order_num>', views.cancle_order),

除了uuid转换器之外, 还有str, int, slug。如果路由中参数的规则较复杂时,建议使用re_path()配置路由中的参数

 re_path(r'^search/(?P<phone>1[3-57-9][\d]{9})$', views.search)
def search(request, phone):
    return HttpResponse('hi, phone: %s' % phone)

十五、反向解析

15.1 命名空间

使用include的namespace和path的name属性。

主路由

path('order/', include('orderapp.urls', namespace='order')),

子路由内容如下:

app_name = 'orderapp'

urlpatterns = [
    path('list/<city_code>/<order_num>', views.order_list, name='list'),
    path('cancel/<uuid:order_num>', views.cancle_order, name='cancel'),
    re_path(r'^search/(?P<phone>1[3-57-9][\d]{9})$', views.search, name='search')
    # url(r'^list2/(?P<city_code>\w+)/(?P<order_num>\d+)$', views.order_list)
]

【注意】如果子路由指定了namespace命名空间, 则子路由的脚本中必须声明"app_name"属性,属性一般是app模块名称。

15.2 在网页中获取路径

在网页中使用 {% url ‘namespace或app_name:name’ 参数 %}

<p>
  <a href="{% url 'orderapp:list' 'xa' 1001 %}">订单</a>
</p>

参数可以是多个,每个参数之间使用空格分隔。

参数默认使用位置传参, 也可以使用关键参数传参。

<p>
  <a href="{% url 'orderapp:list' order_num=1002 city_code='xa' %}">订单</a>
</p>

15.3 在视图函数中获取路径

在视图函数中,使用reverse()函数来反向获取url请求路径。 再通过redirect或HttpResponseRedirect()来重定向。

url = reverse('order:search',
              args=('17791692077',))
return redirect(url)
url = reverse('order:list',
              kwargs=dict(city_code='ShangXiXiaan', order_num=11009))
return HttpResponseRedirect(url)
  • reverse()可以使用kwargs字典类型传参, 也可以使用args以位置方式传参。

  • HttpResponseRedirect()和redirect()是一样的, 即redirect()返回就是HttpResponseRedirect类对象。

十六、error视图模板

常见的错误的响应状态码: 403, 400, 404, 405 请求方法不允许, 500 (服务器异常)

在templates模板中定义404.html或500.html, 要求将settings.py的DEBUG设置为False。

404.html

{% extends 'base.html' %}
{% block content %}

    <h3 style="color:red">

        Sorry, 您请求的资源{{ request_path }}
        <script>
            document.write(window.location.href)
        </script> 不存在

    </h3>
    <p>
        3秒之后自动跳转到<a href="/">主页</a>
    </p>

{% endblock %}

十七、模型类扩展知识点

17.1 validators验证

如果验证不通过,可以抛出ValidationError信息

from django.core.exceptions import ValidationError

自定义验证器类(用于模型类字段的):

class UserValidator:
    @classmethod
    def valid_phone(cls, value):
        if not re.match(r'1[1-57-9]\d{9}', value):
            raise ValidationError('手机格式不正确')
        return True
class UserEntity(models.Model):
    name = models.CharField(max_length=20,
                            verbose_name='账号')
    age = models.IntegerField(default=0,
                              verbose_name='年龄')

    phone = models.CharField(max_length=11,
                             verbose_name='手机号',
                             validators=[UserValidator.valid_phone],
                             blank=True,  # 站点的表单字段值可以为空
                             null=True)  # 数据表的字段可以是null值

在model.CharField(validators=[]) 指定哪些验证方法。

17.2 QuerySet的bulk_create([]) 批量创建

c1 = CateTypeEntity()
c1.name='水果1'
c1.order_num = 10

c2 = CateTypeEntity()
c2.name = '水果2'
c2.order_num = 11

CateTypeEntity.objects.bulk_create([c1, c2])

17.3 QuerySet.values()或values_list()返回指定字段

UserEntity.objects.values('id', 'name')  # 只查看id和name两个字段
<QuerySet [{'id': 1, 'name': 'disen'}, {'id': 2, 'name': 'jack'}, {'id': 3, 'name': '王栋平'}, {'id': 7, 'name': '罗鹏'}, {'id': 8, 'name': '李晨西'}, {'id': 10, 'name': '疾风剑豪亚索'}, {'id': 11, 'name': 'lucy'}]>

17.4 request请求对象的属性

GET/POST/COOKIES/FILES 都是QueryDict类,QueryDict自动进行url的中文编码处理。

method, path, content_type, encoding, session

发布了8 篇原创文章 · 获赞 29 · 访问量 7460

猜你喜欢

转载自blog.csdn.net/ahhqdyh/article/details/104925396