• Python之Django的Model2


    一、创建数据库

    创建数据库

    进入数据库: mysql -uroot -p
    创建数据库: CREATE DATABASE test1 CHARSET=utf8;

    连接数据库

    虚拟环境中安装数据库模块:pip install pymysql

    在Django_model[项目名]/Django_model/__init__py中书写:

    import pymysql
    pymysql.install_as_MySQLdb()

    修改settings.py文件

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',   # postgresql / mysql / sqlite3 / oracle
            'NAME': 'test1',  # 数据库名
            'USER': 'root',
            'PASSWORD': 'root',
            'HOST': 'localhost',  # 本地:localhost
            'PORT': '3306',  # 默认端口:3306
        }
    }

    二、Model使用流程

    • 创建应用python manage.py startapp [应用名]
    • settings.py中的 INSTALLED_APPS = [] 添加应用
    • models.py定义模型类
    • 生成迁移python manage.py makemigrations
    • 执行迁移python manage.py migrate
    • 使用模型

    三、Model字段

    字段类型

    • AutoField: 无需指定,自增长id
    • BooleanField: Boolean类型,默认Flase;表单控件: CheckboxInput
      NullBooleanField: Boolean类型, 支持None, True, False
    • CharField(max_length=字段长度20): 字符串
    • IntegerField: 整数
    • FloatField: 浮点数
    • DateField: datetime.date实例的日期
    • TimeField: datetime.time实例的时间
    • DecimalField(max_digits=位数总数None, decimal_places=小数点后的数字位数None): Decimal的十进制浮点数
      DateTimeField([auto_now=修改时间戳False, auto_now_add=创建时间戳False]): datetime.datetime实例的日期和时间; 表单控件: TextInput + 日历控件

    • FileField: 上传文件(非路径)
    • mageField:上传image

    字段选项

    • null: True:允许None; 默认:False
    • blank: True:允许空白; 默认:False
    • db_column: 字段名; 默认:属性名
    • db_index: True:创建索引; 默认:False
    • default: 默认值
    • primary_key: True:主键
    • unique: True:值唯一

    关系

    • ForeignKey: 一对多, 将该属性定义到多的那一端
    • OneToOneField: 一对一, 将该属性定义到任一端
    • ManyToManyField: 多对多, 将该属性定义到两端
    • 递归关联(自连接/自关联): 一对多, 用一张表存储所有信息

    访问

      BookshelfInfo
        BookInfo
            bookshelf = models.ForeignKey(Bookshelf)
    
        用一访问多:
            对象.模型类_set
            bookshelf.bookinfo_set
        用一访问一:
            对象.模型类
            book.bookshelfinfo
        访问id:
            对象.属性_id
            book.bookshelf_id
    
        使用例子:
            bookshelf = Bookshelf.objects.get(pk=1)  # 查询指定书架
            bookshelf.bookinfo_set.all()  # 获取该书架所有的书信息

    创建表结构

    class Bookshelf(models.Model):
        shelf_type = models.CharField(max_length=10, db_column='shelfType')
        shelf_id = models.IntegerField(db_column='shelfId')
    
        def __str__(self):
            return self.shelf_type
    
    
    class BookInfo(models.Model):
        book_name = models.CharField(max_length=20, db_column='bookName')
        book_time = models.DateTimeField(db_column='bookTime')
        book_type = models.ForeignKey(Bookshelf, db_column='bookType', on_delete=models.CASCADE)
        is_delete = models.BooleanField(db_column='isDelete')
    
        # 元选项
        class Meta:
            db_table = 'bookinfo'  # 表名; 默认: 应用名_表名
            ordering = ['id']  # 排序(正序), 倒序:'-id', 随机:'?id'
    
        def __str__(self):
            return self.book_name
    
    
    # 嵌套关联(自连接/自关联): 一张表存储所有地区(省市区)信息
    class AreaInfo(models.Model):
        area_title = models.CharField(max_length=20)
        area_parent = models.ForeignKey('self', null=True, blank=True, on_delete=models.CASCADE)
    
       def __str__(self):
           return self.area_title
           
    
       数据样式:
           id=1, title='浙江省', parent=null
           id=2, title='杭州市', parent=1
           id=3, title='上城区', parent=2
       使用:
            from booktest.models import AreaInfo
            area = AreaInfo.objects.get(pk=220100)  # 220100, 长春市, 220000(连云港市)
            area.area_parent  # 上级对象: <AreaInfo: 吉林省> (220000, 吉林省, null)
            area.areainfo_set.all()  # 下级对象: [<AreaInfo: 市辖区>, <AreaInfo: 南关区>(220102, 南关区, 220100), <AreaInfo: 宽城区> ...]

    四、管理器Manager

    • 管理器是模型类的属性, 用于对象与数据表之间的映射关系, 是我们用Django与数据库之间操作的接口, 一个模型可以有多个管理器(至少一个)
    • 支持指定管理器(在模型中指定)
    class BookInfo(models.Model):
        # ...
    
        # 指定管理器, 默认:objects
        books = models.Manager()
    • 自定义管理器(用于做一些额外的操作)(在模型中指定)
    class BookInfoManager(models.Manager):
    
        # 在创建时修改
        def create(self, bookname):
            b = BookInfo()
            b.book_name = bookname
            b.book_time = datetime.today()
            b.book_type = Bookshelf.objects.get(pk=1)
            b.is_delete = False
            return b
    
        # 修改查询结果
        def get_queryset(self):
            return super().get_queryset().filter(is_delete=False)
    
    class BookInfo(models.Model):
        # ...
    
        # 一个模型可以使用多个管理器
        # 指定管理器, 默认:objects
        # 方式一: 使用指定管理器(同时多个自定义管理器也是可以的)
        books = models.Manager()
        # 方式二: 使用自定义管理器
        books1 = BookInfoManager()
    • 测试:python manage.py shell
    from booktest.models import BookInfo
    # 使用默认管理器(指定管理器之后, 默认管理器就不存在)
    # Bookshelf.objects.all()
    # 使用指定管理器
    BookInfo.books.all()
    # 使用自定义管理器
    BookInfo.books1.all()
    BookInfo.books1.create('456').save()

    五、查询集

    # --- 查询集 ---
    '''
    惰性执行: 创建查询集, 不会访问数据库, 调用数据时才会访问
    查询集缓存: 查询过的结果集会进行缓存(不访问数据库), 所以查询集可重用(这点不同于Java)
        --- 全部缓存 ---
        例子: list = BookInfo.books1.all()  # 不访问数据库
              print([book.book_name for book in list])  # 访问数据库, 并缓存
              print([book.book_name for book in list])  # 访问查询集缓存
        --- 部分缓存 ---
        例子: list = BookInfo.books1.all()  # 不访问数据库
              print([book.book_name for book in list[0:2]])  # 访问数据库, 并缓存
              print([book.book_name for book in list[1:3]])  # 访问查询集缓存, 不在缓存去访问数据库, 不在缓存的那部分数据不缓存
    
    
    过滤器:(支持链式调用)
        --- 多个值 ---
        all(): 查询所有
        filter(is_delete=True): 通过满足
        exclude(is_delete=True): 通过不满足
        order_by(): 排序
        values(): [{对象}, {对象}]
        使用例子: BookInfo.books1.all()
        --- 单个值 ---
        get(pk=1): 单个满足条件的数据, 没找到DoesNotExist异常, 找到多个MultipleObjectsReturned异常
        count(): 总条数
        first():第一条数据
        last(): 最后一条数据
        exists(): 是否有数据, True:有
        --- 下标限制(不支持-) ---
        [0] / [1:3]
        使用例子: BookInfo.books1.all()[1:3]
    
    字段查询:
        语法: 属性名__比较运算符=值(无需转义)
        外键: 属性名_id
        --- 比较运算符 ---
        exact: ==, 区分大小写(不区分iexact)
        contains: 是否包含, 区分大小写(不区分icontains)
        startswith / endswith: 开头/结尾, 区分大小写(不区分istarswith / iendswith)
        isnull / isnotnull: 是否为null
        gt / gte / lt / lte: > / >= / < / <=
        例子:  BookInfo.books.filter(book_type_id__exact=1)
    
        in: 是否在该[]范围内
            例子: filter(pk__in=[1, 2, 3, 4, 5])
        year / month / day / week_day / hour / minute / second / gt: / / / / / / / 
            例子: BookInfo.books.filter(book_time__year=1980)
            例子: BookInfo.books.filter(book_time__gt=date(1980, 12, 31))  # >(1980,12,31), (date是datetime里的函数)
        pk: 主键(primary key)
            例子: BookInfo.books.filter(pk__lte=2)
    
        --- 关联查询 ---
        # 语法: 模型名__属性名__比较运算符
        Bookshelf.objects.filter(bookinfo__book_name__in=[123, 456, 789])  # 查询书架上有"书名包含123,456,789"的所有书架
    
        --- 聚合函数 ---
        函数: Avg / Count / Max / Min / Sum
        例子:
            from django.db.models import Max
            max_date = BookInfo.books.all().aggregate(Max('book_time'))  # aggregate(Max(xxx))
    
    
    F对象(用于字段与字段的比较)
        语法:
            字段名1__比较运算符=F('字段名2')
            字段名=F('关联模型名__关联字段名')
    
        例子:
            from django.db.models import F
            BookInfo.books.filter(id__exact=F('book_type_id'))  # 对比同表字段
            Bookshelf.objects.filter(id=F('bookinfo__id'))  # 对比关联表字段
            BookInfo.books.filter(book_time__lt=F('book_time') + timedelta(days=1))  # 直接运算
    
    
    Q对象(or查询)
        语法:
            Q(字段__比较运算符=值)
            取反: ~Q(字段__比较运算符=值)
    
        与逻辑运算符一起使用: &(and) / |(or)
        语法: Q(字段1__比较运算符1=值1) 逻辑运算符 Q(字段2__比较运算符2=值2)
    
        例子:
            from django.db.models import Q
                list.filter(Q(pk__exact=1))  # id==1
                list.filter(~Q(pk__exact=2))  # id=/=1
                list.filter(Q(pk__exact=1) | Q(pk__exact=2))  # id=1or2

    六、事务

    from django.db import transaction
    from django.shortcuts import redirect
    
    # 事务
    @transaction.atomic()
    def order_handle(request):
        # 事务回滚点, 操作失败可回到此点
        tran_id = transaction.savepoint()
        try:
            # ...
    
            # 提交事务
            transaction.savepoint_commit(tran_id)
        except Exception as e:
            print(e)
            # 回滚事务
            transaction.savepoint_rollback(tran_id)
        return redirect('xxx')
  • 相关阅读:
    [转]Centos 查看端口占用情况和开启端口命令
    [转]简单美观的文字标签云组件
    [转]scp、sftp命令使用
    清华大学《C++语言程序设计基础》线上课程笔记03---数据的共享和保护&数组
    清华大学《C++语言程序设计基础》线上课程笔记02---类与对象
    清华大学《C++语言程序设计基础》线上课程笔记01---基础概念与一些注意事项
    新的玩具:Windows上的awesome
    环境变量ANDROID_SDK_HOME的作用
    Android Dalvik和JVM的区别
    是否使用TDD(测试驱动开发)进行UI开发
  • 原文地址:https://www.cnblogs.com/chdltanke/p/10418981.html
Copyright © 2020-2023  润新知