Bootstrap

ORM中一对一 一对多 多对多的模型构建、联表查询

一对一 (models.OneToOneField)

 id_card = models.OneToOneField('demo4.IdCard', null=True, blank=True, on_delete=models.CASCADE)

一对多 (外键)models.ForeignKey

dept = models.ForeignKey('DeptModel', verbose_name='员工所属的部门', related_name='emps_list', null=True, blank=True, on_delete=models.SET_NULL)

多对多   models.ManyToManyField    related_name='role_emps_list',

roles = models.ManyToManyField('demo4.RoleModel', related_name='role_emps_list', db_table='t_emp_roles', null=True, blank=True)

null=True  可以为None, blank=True  可以为空字符串 ''

一对一 身份证模型

from django.db import models
from demo1.base_model import BaseModel


# Create your models here.

class IdCard(BaseModel):
    """省份证的模型类"""
    id_number = models.CharField(verbose_name='省份证号码', unique=True, max_length=18)
    start_date = models.DateField(verbose_name='发证日期', null=True, blank=True)
    end_date = models.DateField(verbose_name='发证日期', null=True, blank=True)

    class Meta:
        db_table = 't_id_card'
        verbose_name = '员工表'
        verbose_name_plural = verbose_name
        ordering = ['id']


class RoleModel(BaseModel):
    """权限的模型类, 一个员工可以拥有多个权限, 一个权限可以被多个员工所拥有"""
    name = models.CharField(verbose_name='权限的名称', unique=True, max_length=18)

    class Meta:
        db_table = 't_role'
        verbose_name = '权限表'
        verbose_name_plural = verbose_name
        ordering = ['id']

员工与权限的多对多关联模型 员工与部门间一对多关联模型

from datetime import date

from django.db import models
from django.db.models import Model
from demo1.base_model import BaseModel

# Create your models here.


class JobChoices(models.TextChoices):
    """枚举类"""
    MR = 'MR', '部门经理'
    CE = 'CE', '普通雇员'
    PR = 'PR', '总裁级别'


# 员工的模型类
class Employee(BaseModel):
    name = models.CharField(verbose_name='员工姓名', max_length=20, unique=True)
    job = models.CharField(verbose_name='员工职位', max_length=2, choices=JobChoices.choices, default=JobChoices.CE)
    entry_date = models.DateField(verbose_name='入职日期', default=date.today())
    sal = models.IntegerField(verbose_name='级别薪资')
    bonus = models.SmallIntegerField(verbose_name='津贴', default=0)
    is_leave = models.BooleanField(verbose_name='是否离职', default=False)
    dept = models.ForeignKey('DeptModel', verbose_name='员工所属的部门', related_name='emps_list', null=True, blank=True, on_delete=models.SET_NULL)

    id_card = models.OneToOneField('demo4.IdCard', null=True, blank=True, on_delete=models.CASCADE)

    # 表示:员工拥有的多个角色,员工和角色之前是多对多的关系。在数据库通过第三张表来描述的。
    # 可以自己定义第三张表的名字:db_table='t_emp_roles'
    roles = models.ManyToManyField('demo4.RoleModel', related_name='role_emps_list', db_table='t_emp_roles', null=True, blank=True)

    class Meta:
        db_table = 't_emp'
        verbose_name = '员工表'
        verbose_name_plural = verbose_name
        ordering = ['id']

    def __str__(self):
        # get_ + 属性名字 + _display
        return f"当前的员工是:{self.name}, 职位:{self.get_job_display()}"


# 部门, 之前存在有层级关系(一对多)
# 一个类,内部之前的一对多关系,也叫树形结构模型类,
class DeptModel(BaseModel):
    name = models.CharField(verbose_name='部门名字', max_length=20, unique=True)
    address = models.CharField(verbose_name='部门地址', max_length=100, null=True, blank=True)
    parent = models.ForeignKey('self', null=True, blank=True, on_delete=models.SET_NULL)

    class Meta:
        db_table = 't_dept'
        verbose_name = '部门表'
        verbose_name_plural = verbose_name
        ordering = ['id']

    def __str__(self):
        # get_ + 属性名字 + _display
        return f"当前的部门是:{self.name}"

跨app的权限模型(demo4app)

from django.db import models
from demo1.base_model import BaseModel


# Create your models here.

class IdCard(BaseModel):
    """省份证的模型类"""
    id_number = models.CharField(verbose_name='省份证号码', unique=True, max_length=18)
    start_date = models.DateField(verbose_name='发证日期', null=True, blank=True)
    end_date = models.DateField(verbose_name='发证日期', null=True, blank=True)

    class Meta:
        db_table = 't_id_card'
        verbose_name = '员工表'
        verbose_name_plural = verbose_name
        ordering = ['id']


class RoleModel(BaseModel):
    """权限的模型类, 一个员工可以拥有多个权限, 一个权限可以被多个员工所拥有"""
    name = models.CharField(verbose_name='权限的名称', unique=True, max_length=18)

    class Meta:
        db_table = 't_role'
        verbose_name = '权限表'
        verbose_name_plural = verbose_name
        ordering = ['id']

view中的联表查询

from datetime import date

from django.db.models import Count
from django.http import HttpResponse
from django.shortcuts import render

# Create your views here.
from demo3.models import JobChoices, Employee, DeptModel
from demo4.models import IdCard, RoleModel


def test_db4(request):
    #  给员工增加部门
    # emp = Employee.objects.create(name='lisi', job=JobChoices.CE, entry_date=date(2020, 10, 9), sal=3500, bonus=800)
    #
    # emp.dept_id = 6
    # emp.save()  # 触发数据库的修改


    # emps = Employee.objects.all()
    # d = DeptModel.objects.get(pk=4)
    #
    # for emp in emps:
    #反向查询按类名小写_set或者related_name
    #     d.employee_set.add(emp)


    # 一对一新增数据
    # ic = IdCard.objects.create(id_number='11111111111')
    # emp = Employee.objects.get(pk=8)
    # emp.id_card = ic
    # emp.save()

    # 多对一的新增数据
    # r1 = RoleModel.objects.create(name='销售人员')
    # r2 = RoleModel.objects.create(name='出库人员')
    # r3 = RoleModel.objects.create(name='财务人员')

    # emp = Employee.objects.get(pk=3)
    # r1.role_emps_list.add(emp)  # 给ID为3的员工授予了一个角色:销售人员
    # r2.role_emps_list.add(emp)  # 给ID为3的员工授予了一个角色:出库人员
    # r3.role_emps_list.add(emp)  # 给ID为1的员工授予了一个角色:财务人员

    # emp.roles.add(r1, r2, r3)
    # emp.save()



    # 关联查询
    # 1、查询2020年入职的员工姓名以及该员工的所在部门名称
    # result = Employee.objects.filter(entry_date__year=2020).values('name', 'dept__name')

    # 2、 查询省份号码是:11111111111。 的员工的姓名,以及该员工所属的部门
    # dept 是员工的关联对象, 如果要访问:dept里面的属性,采用"__", 不过,主机ID可以不用__
    # result = Employee.objects.filter(id_card__id_number='11111111111').values('name', 'dept__name', 'dept_id')

    # 3、 查询,每个部门名字、地址以及该部门下面的员工个数
    result = DeptModel.objects.values('name', 'address').annotate(c=Count('emps_list__name'))

    # 4、查询拥有角色数量超过1的 员工姓名以及他所拥有的角色数量。
    result = Employee.objects.annotate(c=Count('roles__name')).filter(c__gt=1).values('name', 'c')

    # 5、 查询每个部门的名字以及它里面的员工数量,并且按照员工数量的个数降序排序。
    result = DeptModel.objects.annotate(c=Count('emps_list__name')).order_by('-c').values('name', 'c')
    for d in result:
        print(d)

    return HttpResponse('test_db4')


;