• Django Model 基础


    程序涉及到数据库相关操作时,一般都会这样:

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

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

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

    import pymysql
      
    def get_list(sql):
        db = pymysql.connect(user='root', db='db1', passwd='123456', host='localhost')
        cursor = db.cursor()
        cursor.execute(sql)
        data = cursor.fetchall()
        db.close()
        return data 

    Django为使用一种新的方式,即:关系对象映射(Object Relational Mapping,简称ORM)。

      PHP:activerecord

      Java:Hibernate 

        C#:Entity Framework

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

    一  创建表

    1.  基本结构 

    from django.db import models
    
    class UserInfo(models.Model):
        name = models.CharField(max_length=32)
        email = models.EmailField()
        memo = models.TextField()
        num = models.IntegerField(null=True, blank=True, default=0)
        ctime = models.DateTimeField(auto_now=True)
    
        def __str__(self):
            return self.name
        # modes字段类型
        AutoField                 int自增列,必须填入参数 primary_key=True
        BigAutoField              bigint自增列,必须填入参数 primary_key=True
        注:当model中如果没有自增列,则自动会创建一个列名为id的列
    
        SmallIntegerField         小整数 -32768 ~ 32767
        PositiveSmallIntegerField 正小整数 0 ~ 32767
        IntegerField              整数列(有符号的) -2147483648 ~ 2147483647
        PositiveIntegerField      正整数 0 ~ 2147483647
        BigIntegerField           长整型(有符号的) -9223372036854775808 ~ 9223372036854775807
        自定义无符号整数字段
                class UnsignedIntegerField(models.IntegerField):
                    def db_type(self, connection):
                        return 'integer UNSIGNED'
    
                PS: 返回值为字段在数据库中的属性,Django字段默认的值为:
                    'AutoField': 'integer AUTO_INCREMENT',
                    'BigAutoField': 'bigint AUTO_INCREMENT',
                    'BinaryField': 'longblob',
                    'BooleanField': 'bool',
                    'CharField': 'varchar(%(max_length)s)',
                    'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
                    'DateField': 'date',
                    'DateTimeField': 'datetime',
                    'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
                    'DurationField': 'bigint',
                    'FileField': 'varchar(%(max_length)s)',
                    'FilePathField': 'varchar(%(max_length)s)',
                    'FloatField': 'double precision',
                    'IntegerField': 'integer',
                    'BigIntegerField': 'bigint',
                    'IPAddressField': 'char(15)',
                    'GenericIPAddressField': 'char(39)',
                    'NullBooleanField': 'bool',
                    'OneToOneField': 'integer',
                    'PositiveIntegerField': 'integer UNSIGNED',
                    'PositiveSmallIntegerField': 'smallint UNSIGNED',
                    'SlugField': 'varchar(%(max_length)s)',
                    'SmallIntegerField': 'smallint',
                    'TextField': 'longtext',
                    'TimeField': 'time',
                    'UUIDField': 'char(32)',
    
        BooleanField          布尔值类型
        NullBooleanField      可以为空的布尔值
    
    
        CharField             字符类型,必须提供max_length参数, max_length表示字符长度
        TextField             文本类型
        EmailField            字符串类型,Django Admin以及ModelForm中提供验证机制
        IPAddressField        字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制
        GenericIPAddressField 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
            - protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
            - unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both"
        URLField               字符串类型,Django Admin以及ModelForm中提供验证 URL
        SlugField  字          符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)
        UUIDField              字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证
    
        FilePathField
            - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
            - 参数:
                path,                      文件夹路径
                match=None,                正则匹配
                recursive=False,           递归下面的文件夹
                allow_files=True,          允许文件
                allow_folders=False,       允许文件夹
    
        FileField
            - 字符串,路径保存在数据库,文件上传到指定目录
            - 参数:
                upload_to = ""      上传文件的保存路径
                storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
    
        ImageField(FileField)
            - 字符串,路径保存在数据库,文件上传到指定目录
            - 参数:
                upload_to = ""      上传文件的保存路径
                storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
                width_field=None,   上传图片的高度保存的数据库字段名(字符串)
                height_field=None   上传图片的宽度保存的数据库字段名(字符串)
    
        DateTimeField  日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
        DateField      日期格式      YYYY-MM-DD
        TimeField      时间格式      HH:MM[:ss[.uuuuuu]]
    
        DurationField  长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型
        FloatField     浮点型
        DecimalField
            -10进制小数
            - 参数:
                max_digits,小数总长度
                decimal_places,小数位长度
        BinaryField  二进制类型
        
        # 更多信息参考 https://docs.djangoproject.com/en/1.11/ref/models/fields/
    字段
        # 参数
        null                数据库中字段是否可以为空
        db_colmun           数据库中字段的列名
        db_tablespace
        default             数据库中字段的默认值
        primary_key         数据库中字段是否为主键
        db_index            数据库中字段是否可以建立索引
        unique              数据库中字段是否可以建立唯一索引
        unique_for_date     数据库中字段【日期】部分是否可以建立唯一索引
        unique_for_month    数据库中字段【月】部分是否可以建立唯一索引
        unique_for_year     数据库中字段【年】部分是否可以建立唯一索引
    
        verbose_name        Admin中显示的字段名称
        blank               Admin中是否允许用户输入为空
        editable            Admin中是否可以编辑
        help_text           Admin中该字段的提示信息
        choices             dmin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
                            如:friend = models.IntegerField(choices=[(0, '小李子'),(1, '大表姐'),],default=1)
    
        error_messages      自定义错误信息(字典类型),从而定制想要显示的错误信息;
                            字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
                            如:{'null': "不能为空.", 'invalid': '格式错误'}
    
        validators          自定义错误验证(列表类型),从而定制想要的验证规则
                            from django.core.validators import RegexValidator
                            from django.core.validators import EmailValidator,URLValidator,DecimalValidator,
                            MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
                            如:
                                test = models.CharField(
                                    max_length=32,
                                    error_messages={
                                        'c1': '优先错信息1',
                                        'c2': '优先错信息2',
                                        'c3': '优先错信息3',
                                    },
                                    validators=[
                                        RegexValidator(regex='root_d+', message='错误了', code='c1'),
                                        RegexValidator(regex='root_112233d+', message='又错误了', code='c2'),
                                        EmailValidator(message='又又错误了', code='c3'), ]
                                )
    参数
    class UserInfo(models.Model):
        name = models.CharField(max_length=30)
        email = models.EmailField()
        memo = models.TextField()
    
        class Meta:
            # 抽象基类,不会生成对应库表
            abstract = True
    
            # app名称
            app_label = 'myapp'
    
            # latest()方法默认排序字段
            get_latest_by = 'order_date'
    
            # 默认排序规则
            ordering = ['-order_date']
    
            # 代理继承
            proxy = True
    
            # 数据库中生成的表名称 默认 app名称_类名小写
            db_table = "table_name"
    
            # 联合索引
            index_together = [
                ("pub_date", "deadline"),
            ]
    
            # 联合唯一索引
            unique_together = (("driver", "restaurant"),)
    
            # admin中显示的表名称
            verbose_name = 'name'
    
            # verbose_name复数形式
            verbose_name_plural = 'names'
    
            # 只读属性
            # label,=app_label.object_name,如'polls.Question'
            # label_lower,=app_label.object_name,如'polls.question'
    
            # 更多参考 https://docs.djangoproject.com/en/1.11/ref/models/options/
    元类

    2.  连表结构

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

    • 多对多:models.ManyToManyField(其他表)

    • 一对一:models.OneToOneField(其他表)

    应用场景:

    • 一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择)

      例如:创建用户信息时候,需要选择一个用户类型【普通用户】【金牌用户】【铂金用户】等。

    • 多对多:在某表中创建一行数据是,有一个可以多选的下拉框

      例如:创建用户信息,需要为用户指定多个爱好

    • 一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了)

      例如:用户基本表存储用户名、密码,用户详情表存储基本信息

    二  操作表

    1.  基本操作

     1     #
     2     #
     3     # models.userinfo.objects.create(name='Linda', email='linda@gmail.com', memo='xxxx') # 增加一条数据,可以接受字典类型数据 **kwargs
     4     # obj = models.userinfo(name='Green', email='Green@gmail.com', memo='xxxx')
     5     # obj.save()
     6 
     7     #
     8     #
     9     # models.userinfo.objects.get(id=1)     # 获取单条数据,不存在则报错(不建议)
    10     # models.userinfo.objects.all()         # 获取所有对象,QuerySet列表,元素为对象
    11     # models.userinfo.objects.filter(name="Curry")  # 过滤指定条件数据 <QuerySet [<userinfo: Curry>]>
    12 
    13     #
    14     #
    15     # models.userinfo.objects.filter(name='Bill').delete() # 删除指定条件的数据
    16 
    17     #
    18     #
    19     # models.userinfo.objects.filter(name='Green').update(num=10) # 将指定条件的数据更新,均支持 **kwargs
    20     # obj = models.userinfo.objects.get(id=1)
    21     # obj.num = 100
    22     # obj.save()    # # 修改单条数据
    View Code 

    2.  进阶操作(了不起的双下划线)

     1     # 获取个数
     2     # models.userinfo.objects.filter(name='Green').count()
     3 
     4     # 大于,小于
     5     # models.userinfo.objects.filter(id__gt=1)            # 获取id大于1的值
     6     # models.userinfo.objects.filter(id__gte=1)           # 获取id大于等于1的值
     7     # models.userinfo.objects.filter(id__lt=8)            # 获取id小于8的值
     8     # models.userinfo.objects.filter(id__lte=8)           # 获取id小于8的值
     9     # models.userinfo.objects.filter(id__lt=8, id__gt=1)  # 获取id大于1 且 小于8的值
    10 
    11     # in
    12     # models.userinfo.objects.filter(id__in=[1, 2, 3])
    13     # models.userinfo.objects.exclude(id__in=[1, 2, 3])
    14 
    15     # isnull
    16     # models.userinfo.objects.filter(ctime__isnull=True)
    17 
    18     # contains
    19     # models.userinfo.objects.filter(name__contains='Lin')
    20     # models.userinfo.objects.filter(name__icontains='lin')  # icontains大小写不敏感
    21     # models.userinfo.objects.exclude(name__icontains='lin')
    22 
    23     # range
    24     # models.userinfo.objects.filter(id__range=[1, 2])
    25 
    26     # 其他类似
    27     # startswith, istartswith, endswith, iendswith
    28 
    29     # order_by
    30     # models.userinfo.objects.all().order_by('id')  # asc
    31     # models.userinfo.objects.all().order_by('-id') # desc
    32 
    33     # group by
    34 
    35     # limit, offset
    36     # models.userinfo.objects.all()[10:12]
    37 
    38     # regex正则匹配,iregex 不区分大小写
    39     # models.userinfo.objects.get(name__regex=r'^(An?|The)+')
    40     # models.userinfo.objects.get(name__iregex=r'^(An?|The)+')
    View Code

    3.  extra、F、Q及原生SQL

     1     # extra
     2     #
     3     # models.userinfo.objects.extra(select={'new_id': 'select name from app_userinfo where id > %s'}, select_params=(1,))
     4     # models.userinfo.objects.extra(where=['name=%s'],params=["Linda"])
     5     # models.userinfo.objects.extra(where=["name='Linda' OR name='Green' OR name='Logan'"])
     6     # models.userinfo.objects.extra(select={'new_id': 'select name from app_userinfo where id > %s'}, select_params=(1,),order_by=['-id'])
     7 
     8     # F
     9     #
    10     # from django.db.models import F
    11     # models.userinfo.objects.filter(name='Linda').update(num=F('num')+1)
    12 
    13     # Q
    14     #
    15     # 方式一:
    16     # Q(nid__gt=10)
    17     # Q(nid=8) | Q(nid__gt=10)
    18     # Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
    19     # 方式二:
    20     # con = Q()
    21     # q1 = Q()
    22     # q1.connector = 'OR'
    23     # q1.children.append(('id', 1))
    24     # q1.children.append(('id', 10))
    25     # q1.children.append(('id', 9))
    26     # q2 = Q()
    27     # q2.connector = 'OR'
    28     # q2.children.append(('name', 'Linda'))
    29     # q2.children.append(('name', 'Logan'))
    30     # q2.children.append(('nmae', 'Green'))
    31     # con.add(q1, 'AND')
    32     # con.add(q2, 'AND')
    33     #
    34     # models.userinfo.objects.filter(con)
    35 
    36     # from django.db import connection, connections
    37     # cursor = connection.cursor()  # # cursor = connections['default'].cursor()
    38     # cursor.execute("""SELECT * from app_userinfo where id = %s""", [1])
    39     # row = cursor.fetchone()  # (1, 'Linda', 'linda@gmail.com', 'xxxx', 102, datetime.datetime(2017, 8, 3, 3, 50, 28, 145647))
    View Code

    4.  连表操作(了不起的双下划线)

    利用双下划线和_set将表之间的操作连接起来

     1 class UserProfile(models.Model):
     2     user_info = models.OneToOneField('UserInfo1')
     3     username = models.CharField(max_length=64)
     4     password = models.CharField(max_length=64)
     5 
     6     def __str__(self):
     7         return self.username
     8 
     9 
    10 class UserInfo1(models.Model):
    11     user_type_choice = (
    12         (0, u'普通用户'),
    13         (1, u'高级用户')
    14     )
    15     user_type = models.IntegerField(choices=user_type_choice,default=0)
    16     name = models.CharField(max_length=32)
    17     email = models.CharField(max_length=32)
    18     address = models.CharField(max_length=128)
    19 
    20     def __str__(self):
    21         return self.name
    22 
    23 
    24 class UserGroup(models.Model):
    25     caption = models.CharField(max_length=64)
    26     user_info = models.ManyToManyField('UserInfo1')
    27 
    28     def __str__(self):
    29         return self.caption
    30 
    31 
    32 class Host(models.Model):
    33     hostname = models.CharField(max_length=64)
    34     ip = models.GenericIPAddressField()
    35     user_group = models.ForeignKey('UserGroup')
    36 
    37     def __str__(self):
    38         return self.hostname
    表结构实例
     1     user_info_obj = models.UserInfo1.objects.filter(id=1).first()
     2     print(user_info_obj.user_type)
     3     print(user_info_obj.get_user_type_display())
     4     print(user_info_obj.userprofile.password)   # 默认userprofile属性对象
     5 
     6     user_profile_obj = models.UserProfile.objects.filter(id=1).first()
     7     print(user_profile_obj.user_info.address)   # user_info 当做对象来处理
     8 
     9     user_info_obj = models.UserInfo1.objects.filter(id=1).values('email','userprofile__username').first()
    10     print(user_info_obj)          # <QuerySet [{'email': 'tom@gmail.com', 'userprofile__username': 'tommm'}]>
    11     print(user_info_obj.keys())
    12     print(user_info_obj.values())
    一对一操作
     1     """
     2     1. 搜索条件使用 __ 连接
     3     2. 获取值时使用 . 连接
     4     3. 从主键表到外键表,即方向操作时,主键对象.外键表名_set.all()
     5     """
     6     host_obj = models.Host.objects.filter(id=1).first()
     7     print(host_obj.user_group.caption)
     8 
     9     user_group_obj = models.UserGroup.objects.filter(id=1).first()
    10     print(user_group_obj.host_set.all())  # <QuerySet [<Host: host1>, <Host: host2>]>
    一对多操作
     1     user_info_obj = models.UserInfo1.objects.filter(name='Tim').first()
     2     user_info_objs = models.UserInfo1.objects.all()
     3 
     4     group_obj = models.UserGroup.objects.filter(caption='GroupB').first()
     5     group_objs = models.UserGroup.objects.all()
     6 
     7     # 添加数据
     8     # group_obj.user_info.add(user_info_obj)    # 组对象GroupB 添加单个对象 Tim
     9     # group_obj.user_info.add(*user_info_objs)  # 组对象GroupB 批量添加对象
    10 
    11     # 删除数据
    12     # group_obj.user_info.remove(user_info_obj)   # 组对象GroupB 删除单个对象 Tim
    13     # group_obj.user_info.remove(*user_info_objs) # 组对象GroupB 批量删除对象
    14 
    15     # 添加数据
    16     # user_info_obj.usergroup_set.add(group_obj)   # 对象Tim 添加到组对象GroupB中
    17     # user_info_obj.usergroup_set.add(*group_objs) # 对象Tim 批量添加到各个组对象中
    18 
    19     # 删除数据
    20     # user_info_obj.usergroup_set.remove(group_obj)   # 对象Tim 从组对象GroupB中删除
    21     # user_info_obj.usergroup_set.remove(*group_objs) # 对象Tim 从各个组对象中删除
    22 
    23     # 获取数据
    24     # class UserGroup中定义 user_info = models.ManyToManyField('UserInfo1')
    25     print(group_obj.user_info.all())               # <QuerySet [<UserInfo1: tom>, <UserInfo1: Tim>, <UserInfo1: linda>]>
    26     print(group_obj.user_info.all().filter(id=1))  # <QuerySet [<UserInfo1: tom>]>
    27 
    28     # 获取数据
    29     # 获取user_info_obj所在哪些组
    30     print(user_info_obj.usergroup_set.all())      # <QuerySet [<UserGroup: GroupB>, <UserGroup: GroupA>]>
    31     print(user_info_obj.usergroup_set.all().filter(caption='GroupB'))  # <QuerySet [<UserGroup: GroupB>]>
    多对多操作

    更多信息参考: http://www.cnblogs.com/wupeiqi/articles/5246483.html

  • 相关阅读:
    树莓派/Debian 搭建 FTP 服务器
    树莓派/Debian “无法定位软件包 mod_ssl” 问题解决方案
    树莓派/Debian HTTP 到 HTTPS 端口重定向
    树莓派/Debian 搭建ownCloud私有云网盘
    树莓派/Debian 构建 LAMP Web 服务器并搭建 WordPress 博客(二)
    改进一维搜索
    实现共轭梯度法蒙皮模拟
    基本实现蒙皮模拟
    实现权重计算
    把状态保存
  • 原文地址:https://www.cnblogs.com/jonathan1314/p/7278645.html
Copyright © 2020-2023  润新知