python【第十九篇】Django进阶

时间:2023-03-10 02:38:29
python【第十九篇】Django进阶

1.路由系统优化

1.1 路由分发

前面我们已经知道,在工程名下的urls.py中写我们的路由映射关系,那么问题来了,假设我们有10个app,如果把所有的url映射都写在urls.py文件中,那么每一个app的路由都得到这里写,岂不是很麻烦?而且url多了还不好找,是吧?

所以,我们其实可以这样:

(1)在urls.py中这样写:

 from django.conf.urls import url
 from django.contrib import admin
 from django.conf.urls import include   # 导入include

 urlpatterns = [
     url(r'^admin/', admin.site.urls),
     url(r'^user/', include('user.urls')),  # 格式就是 url(r'^app01/', include('app01.urls')),
 ]
 '''
 ----------------------------------------------------------------------------------------------
 # 如果有多个app,那么就写成:
 urlpatterns = [
     url(r'^admin/', admin.site.urls),
     url(r'^app01/', include('app01.urls')),
     url(r'^app02/', include('app02.urls')),
     url(r'^app03/', include('app03.urls')),
 ]
 ----------------------------------------------------------------------------------------------
 '''

(2)在到每个app目录下,新建一个同名的urls.py,在其中写到:

 #! /usr/bin/env python3
 # -*- coding:utf-8 -*-

 from django.conf.urls import url
 from user import views           # 从当前app导入view

 # 下面就可以写对应的映射关系了,不过访问时url就形如:127.0.0.1:8000/user/login/了,不再是127.0.0.1:8000/login/
 urlpatterns = [
     url(r'^login/', views.login),
     url(r'^init/', views.db_init),
     url(r'^index/', views.index),
     url(r'^useradd/', views.user_add),
     url(r'^userdel/', views.user_del),
     url(r'^detail-(?P<nid>\d+)/', views.user_detail),
     url(r'^edit-(?P<nid>\d+)/', views.user_edit),
     url(r'^update/', views.update),
     url(r'^group-add/', views.group_add),
     url(r'^group-del/', views.group_del),
 ]

也就是说每个app的路由映射关系,都到了自己目录下面,是不是方便了很多?这就是路由分发。

1.2 通过路由传值

urls.py中这样写:

url(r'^detail-(\d+)-(\d+).html', views.detail),

对应views.py中的函数:

# 假设\d+匹配到的分别是2,9

#法1
def detail(request, nid, uid):

    pass

#法2
def detail(request, *args):
    args = (2,9)

#法3
def detail(request, *args, **kwargs):
    args = (2,9)
    kwargs = {}            

urls.py中这样写:

url(r'^detail-(?P<nid>\d+)-(?P<uid>\d+).html', views.detail)

对应views.py中的函数:

def detail(request, nid, uid):
    pass

def detail(request, **kwargs):
    kwargs = {'nid': 1, 'uid': 3}

def detail(request, *args, **kwargs):
    args = (2,9)

2.Model

python涉及数据库操作时,我们一般都会这样处理:

(1)

  创建数据库,设计表结构和字段

  使用PyMysql来连接数据库,并且编写数据访问层代码

  业务逻辑层去调用数据访问层执行数据库操作

(2)另外就是用关系对象映射(Object Relational Mapping,简称ORM)来处理,前面我们已经学过sqlalchemy这个模块来操作数据库了,而我们强大的django也有自己的一套ORM

其他语言中:

 PHP:activerecord

 Java:Hibernate

C#:Entity Framework

django中遵循 Code Frist 的原则,即:根据代码中定义的类来自动生成数据库表。

2.1 创建表

(1)基本表结构:

 from django.db import models

 class UserGroup(models.Model):
     """用户组表"""
     group_name = models.CharField(max_length=32)   # 用户组名称

更多字段:

1、models.AutoField  自增列 = int(11)
  如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。
2、models.CharField  字符串字段
  必须 max_length 参数
3、models.BooleanField  布尔类型=tinyint(1)
  不能为空,Blank=True
4、models.ComaSeparatedIntegerField  用逗号分割的数字=varchar
  继承CharField,所以必须 max_lenght 参数
5、models.DateField  日期类型 date
  对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。
6、models.DateTimeField  日期类型 datetime
  同DateField的参数
7、models.Decimal  十进制小数类型 = decimal
  必须指定整数位max_digits和小数位decimal_places
8、models.EmailField  字符串类型(正则表达式邮箱) =varchar
  对字符串进行正则表达式
9、models.FloatField  浮点类型 = double
10、models.IntegerField  整形
11、models.BigIntegerField  长整形
  integer_field_ranges = {
    'SmallIntegerField': (-32768, 32767),
    'IntegerField': (-2147483648, 2147483647),
    'BigIntegerField': (-9223372036854775808, 9223372036854775807),
    'PositiveSmallIntegerField': (0, 32767),
    'PositiveIntegerField': (0, 2147483647),
  }
12、models.IPAddressField  字符串类型(ip4正则表达式)
13、models.GenericIPAddressField  字符串类型(ip4和ip6是可选的)
  参数protocol可以是:both、ipv4、ipv6
  验证时,会根据设置报错
14、models.NullBooleanField  允许为空的布尔类型
15、models.PositiveIntegerFiel  正Integer
16、models.PositiveSmallIntegerField  正smallInteger
17、models.SlugField  减号、下划线、字母、数字
18、models.SmallIntegerField  数字
  数据库中的字段有:tinyint、smallint、int、bigint
19、models.TextField  字符串=longtext
20、models.TimeField  时间 HH:MM[:ss[.uuuuuu]]
21、models.URLField  字符串,地址正则表达式
22、models.BinaryField  二进制
23、models.ImageField   图片
24、models.FilePathField 文件

(2)连表结构:

(1)一对多:models.ForeignKey(其他表)

  应用场景:

  • 一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择)
    例如:创建用户信息时候,需要选择一个用户类型【普通用户】【金牌用户】【铂金用户】等。

示例:

 from django.db import models

 class UserGroup(models.Model):
     """用户组表"""
     group_name = models.CharField(max_length=32)   # 用户组名称

 class UserInfo(models.Model):
     """用户信息表"""
     name = models.CharField(max_length=32)         # 用户的姓名
     username = models.CharField(max_length=32)     # 用户名
     password = models.CharField(max_length=64)     # 用户密码
     user_type_choice = (
         (0, u'普通用户'),
         (1, u'管理员用户'),
     )
     user_type = models.IntegerField(choices=user_type_choice, default=0)    # 用户类型
     date = models.DateField(auto_now=True)                                  # 创建日期
     remark = models.CharField(max_length=64)                                # 备注
     user_group = models.ForeignKey(UserGroup)                               # 关联的用户组

2.2 操作表:

(1)创建表结构:

我们在modes中已经写好表的类了,那么我们可以通过命令行:

python manage.py makemigrations

python manage.py migrate

这样表结构就创建好了,如下所示:

python【第十九篇】Django进阶

(2)增删改查:

# 示例表结构类
class GroupInfo(models.Model):
    group_name = models.CharField(max_length=32)

class UserInfo(models.Model):

    username = models.CharField(max_length=32)
    password = models.CharField(max_length=64)

# 创建
# 法1
# models.UserInfo.objects.create(username="zingp", password="123")
# 法2
# user_dic = {"username": "alex", "password": "123"}
# models.UserInfo.objects.create(**user_dic)
# 法3
# obj = models.UserInfo(username="root", password="123")
# obj.save()

# 查
# result = models.UserInfo.objects.all()              # 查询所有
# result = models.UserInfo.objects.filter(username="root", password="123")    # 根据条件过滤
# for row in result:
#     print(row.id, row.username)
# models.UserInfo.objects.get(id=1)         # 获取单条数据,不存在则报错(不建议)

# 删除
#models.UserInfo.objects.filter(username="alex").delete()

# 更新
#models.UserInfo.objects.filter(id=3).update(password="8888")