zoukankan      html  css  js  c++  java
  • Django ORM

    1. Django ORM

    通过代码来描述数据库中的表


    类名 - 表名

    类属性 - 表字段

    表中的每一个记录在代码的层面都是由类实例化的对象, 表中的字段是其属性


    2. 配置ORM


    2.1 安装django 和 pg 模块

    pip install psycopg2  
    pip install django==2.2.15
    

    2.2 准备django项目

    创建库 ormtest


    django-admin startproject salary .
    

    • 创建应用
     python manage.py startapp employee
    

    • 配置

      打开salary/settings.py主配置文件

    # 应用注册
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'employee'
    ]
    
    
    # 数据库配置
    
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': 'ormtest',
            'USER': 'postgres',
            'PASSWORD': 'postgres',
            'HOST': '127.0.0.1',
            'PORT': '5432',
    
        }
    }
    
    # 时区配置
    TIME_ZONE = 'Asia/Shanghai'
    

    2.3 Django日志配置

    打开salary/settings.py主配置文件

    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'handlers': {
            'console': {
                'class': 'logging.StreamHandler',
            },
        },
        'loggers': {
            'django.db.backends': {
                'handlers': ['console'],
                'level': 'DEBUG',
            },
        },
    }
    

    2.4 模型Model下编写ORM类

    打开employee/models.py


    • 基类 django.db.models.Model
    • 表名不指定默认使用 _ 。使用Meta类db_table修改表名
    from django.db import models
    
    # Create your models here.
    
    class Employee(models.Model):
        class Meta:
            db_table = 'employees'
        emp_no = models.IntegerField(primary_key=True)  # Django中如果model类中定义了主键, 自增整数字段主键不会自动创建了
        birth_date = models.DateField(null=False)
        first_name = models.CharField(null=False, max_length=14)
        last_name = models.CharField(null=False, max_length=16)
        gender = models.SmallIntegerField(null=False, default=1) # M=1 F=2
        hire_date = models.DateField(null=False)
    
        def __repr__(self):
            return "<Employee: {} {} {}>".format(self.emp_no, self.first_name,self.last_name)
        __str__ = __repr__
    
    # ORM  查询返回n条员工记录, 每一个记录都是一个实例(employee())
    

    • 创建表

    makemigrations
    migrate
    


    2.5 插入数据

    在项目根目录编写一个test.py,内容如下

    # 参考wsgi.py
    from datetime import datetime
    import os
    import django
    
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'salary.settings')
    
    django.setup(set_prefix=False)
    
    #  其他测试代码都放到这4行下面
    from employee.models import Employee
    
    
    def birth_date(year, month, day):
        dt = datetime(year=year, month=month, day=day)
        return dt.strftime('{}-{}-{}'.format(dt.year, dt.month, dt.day))
    
    
    # Employee.objects   管理类对象
    emp_mgr = Employee.objects  # employee.Employee.objects
    birth_date_list = [birth_date(1953, 9, 2), birth_date(1964, 6, 2), birth_date(1959, 12, 3), birth_date(1954, 5, 1),
                       birth_date(1955, 1, 21),
                       birth_date(1953, 4, 20), birth_date(1957, 5, 23), birth_date(1958, 2, 19), birth_date(1952, 4, 19),
                       birth_date(1963, 6, 1),
                       birth_date(1953, 11, 7), birth_date(1960, 10, 4), birth_date(1963, 6, 7), birth_date(1956, 2, 12),
                       birth_date(1959, 8, 19),
                       birth_date(1961, 5, 12), birth_date(1958, 7, 6), birth_date(1954, 6, 19), birth_date(1953, 1, 23),
                       birth_date(1952, 12, 24)
                       ]
    first_name_list = ['Georgi', 'Bezalel', 'Parto', 'Christian', 'Kyoichi',
                       'Anneke', 'Tzvetan', 'Saniya', 'Sumant', 'Duangkaew',
                       'Mary', 'Patricio', 'Eberhardt', 'Berni', 'Guoxiang',
                       'Kazuhito', 'Cristinel', 'Kazuhide', 'Lillian', 'Mayuko'
                       ]
    last_name_list = ['Facello', 'Simmel', 'Bamford', 'Koblick', 'Maliniak',
                      'Preusig', 'Zielinski', 'Kalloufi', 'Peac', 'Piveteau',
                      'Sluis', 'Bridgland', 'Terkki', 'Genin', 'Nooteboom',
                      'Cappelletti', 'Bouloucos', 'Peha', 'Haddadi', 'Warwick'
                      ]
    gender_list = [1, 2, 1, 1, 1, 2, 2, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1]
    hire_date_list = [birth_date(1986, 6, 26), birth_date(1985, 11, 21), birth_date(1986, 8, 28), birth_date(1986, 12, 1),
                      birth_date(1989, 9, 12),
                      birth_date(1989, 6, 12), birth_date(1989, 2, 10), birth_date(1994, 9, 15), birth_date(1985, 2, 18),
                      birth_date(1989, 8, 24),
                      birth_date(1990, 1, 22), birth_date(1992, 12, 18), birth_date(1985, 10, 20), birth_date(1987, 3, 11),
                      birth_date(1987, 7, 12),
                      birth_date(1995, 11, 27), birth_date(1993, 8, 3), birth_date(1987, 4, 3), birth_date(1999, 4, 30),
                      birth_date(1991, 1, 26)
                      ]
    data = []
    for i in range(20):
        data.append(Employee(emp_no=i+10001, birth_date=birth_date_list[i], first_name=first_name_list[i], last_name=last_name_list[i],
                             gender=gender_list[i], hire_date=hire_date_list[i]))
    
    Employee.objects.bulk_create(data)
    


    3. ORM查询


    3.1 查询所有

    SELECT "employees"."emp_no", "employees"."birth_date", "employees"."first_name", "employees"."last_name", "employees"."gender", "employees"."hire_date" FROM "employees";
    
    


    # Employee.objects   管理类对象
    emp_mgr = Employee.objects  # employee.Employee.objects
    x = emp_mgr.all()  # 操作这个对象就意味着select * from employees; (比如for循环, 比如print)
    for i in x:  
        print(i.pk, i.birth_date, i.first_name, i.last_name, i.gender, i.hire_date)
    
    


    3.2 高效率查询所有

    将 查询集 emp_mgr.all() 封装成列表

    x = list(emp_mgr.all())  # 如果这个对象需要用到多次, 使用列表封装对象, 这样触发这个对象的查询只会执行一次
    print(x)
    print(x)
    
    


    说明:

    1、惰性求值:
    创建查询集不会带来任何数据库的访问,直到调用方法使用数据时,才会访问数据库。在迭代、序列
    化、if语句中都会立即求值。


    2、缓存:
    每一个查询集都包含一个缓存,来最小化对数据库的访问。
    新建查询集,缓存为空。首次对查询集求值时,会发生数据库查询,Django会把查询的结果存在这个缓
    存中,并返回请求的结果,接下来对查询集求值将使用缓存的结果。
    观察下面的2个例子是要看真正生成的语句了


    3.3 条件查询 (filter / exclude)


    • filter
    SELECT * FROM "employees" WHERE "employees"."emp_no" = 10001  LIMIT 21; 
    
    


    print(emp_mgr.filter(pk=10001))
    
    

    • exclude
    SELECT * FROM "employees" WHERE NOT ("employees"."emp_no" = 10001)  LIMIT 21;
    
    


    print(emp_mgr.exclude(pk=10001))
    
    

    3.4 与查询

    SELECT * FROM "employees" WHERE (UPPER("employees"."first_name"::text) LIKE UPPER('p%') AND "employees"."emp_no" > 10009)  LIMIT 21; 
    
    


    from django.db.models import Q
    print(emp_mgr.filter(pk__gt=10009, first_name__istartswith='p'))
    print(emp_mgr.filter(pk__gt=10009) & emp_mgr.filter(first_name__istartswith='p'))
    print(emp_mgr.filter(Q(pk__gt=10009) & Q(first_name__istartswith='p')))
    
    

    3.5 或查询

    SELECT * FROM "employees" WHERE "employees"."emp_no" IN (10005, 10006, 10007)  LIMIT 21; 
    
    


    print(emp_mgr.filter(pk__in=[10005, 10006, 10007]))
    
    

    SELECT * FROM "employees" WHERE ("employees"."emp_no" = 10005 OR "employees"."emp_no" = 10006 OR "employees"."emp_no" = 10007)  LIMIT 21; 
    
    


    print(emp_mgr.filter(pk__exact=10005) | emp_mgr.filter(pk__exact=10006) | emp_mgr.filter(pk__exact=10007))
    print(emp_mgr.filter(Q(pk__exact=10005) | Q(pk__exact=10006) | Q(pk__exact=10007)))
    
    

    3.6 非查询

    SELECT * FROM "employees" WHERE  not ("employees"."emp_no" < 10017)  LIMIT 21; 
    
    

    print(emp_mgr.filter(~(Q(pk__lte=10017))))
    
    

    3.7 排序(order_by)

    • 升序 (默认)
    SELECT * FROM "employees" ORDER BY "employees"."gender" ASC; 
    
    


    print(*emp_mgr.all().order_by('gender'), sep='
    ')
    
    


    • 降序
    SELECT * FROM "employees" ORDER BY "employees"."gender" DESC; 
    
    


    print(*emp_mgr.all().order_by('-gender'), sep='
    ')
    
    


    3.8 字典 / 列表 查询集


    • 字典查询集
    SELECT * FROM "employees"  LIMIT 1 OFFSET 5; 
    
    

    print(emp_mgr.values()[5:6])  # 字典的查询集
    
    


    • 列表查询集
    SELECT * FROM "employees"  LIMIT 1 OFFSET 5; 
    
    

    print(emp_mgr.values_list()[5:6])  # 列表的查询集
    
    


    3.9 返回单个值的方法

    名称 说明
    get() 仅返回单个满足条件的对象
    如果未能返回对象则抛出DoesNotExist异常;
    如果能返回多条,抛出MultipleObjectsReturned异常
    count() 返回当前查询的总条数
    first() 返回第一个对象
    last() 返回最后一个对象
    exist() 判断查询集中是否有数据,如果有则返回True
    mgr = Employee.objects
    print(mgr.filter(pk=10010).get())  # <Employee: 10010 Duangkaew Piveteau 2>
    print(mgr.get(pk=10009)) # <Employee: 10009 Sumant Peac 2>
    print(mgr.get(pk=10029)) # pk=10029的数据不存在, 抛异常, employee.models.DoesNotExist: Employee matching query does not exist.
    print(mgr.first())  # <Employee: 10001 Georgi Facello 1>
    print(mgr.filter(pk=10010, gender=1).first())  # None
    print(mgr.exclude(pk=10020).last()) # <Employee: 10019 Lillian Haddadi 1>
    print(mgr.count()) # 20
    print(mgr.exclude(pk=10010).count()) # 19
    
    

    3.10 聚合查询

    SELECT COUNT("employees"."emp_no") AS "数量" FROM "employees" WHERE "employees"."emp_no" <= 10010;
    
    


    from django.db.models import Count
    print(emp_mgr.values().filter(pk__lte=10010).aggregate(数量=Count('pk')))
    
    

    3.11 分组查询

    SELECT "employees"."gender", COUNT("employees"."gender") AS "数量" FROM "employees" WHERE "employees"."emp_no" <= 10010 GROUP BY "employees"."gender"  LIMIT 21;
    
    


    print(emp_mgr.filter(pk__lte=10010).values('gender').annotate(数量=Count('gender')).values('gender', '数量'))
    
    
  • 相关阅读:
    SQlite数据库
    关于如何获取剪切板的多个图片处理
    aes 和 Md5 分析
    SIP消息
    getItemAt
    C++ map的方法
    C++ 解析Json
    CentOS 6.3安装配置LAMP服务器(Apache+PHP5+MySQL)
    阿里云服务器CentOS 5.7(64位)安装配置LAMP服务器(Apache+PHP5+MySQL)
    Apache虚拟主机(vhost)配置教程
  • 原文地址:https://www.cnblogs.com/cjwnb/p/13587471.html
Copyright © 2011-2022 走看看