employee models
import os
import django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'salary.settings')
django.setup(set_prefix=False)
from employee.models import Employee, Salary, Department, Dept_emp
from students.models import Student, Score
from django.db.models import Q, Avg, Sum, Max, Min, Count
emps = Employee.objects.all()
smps = Salary.objects
dmps = Department.objects
demps = Dept_emp.objects
# --- 多對多查詢
# 查詢10010員工的所在的部門編号及員工資訊
# es = emps.get(pk=10010)
# ed = es.dept_emp_set.all() # 記得加all(),不然會傳回None
# print(es)
# print(ed)
# for i in ed:
# print(type(i), i)
# e = i.emp_no
# print(type(e), e)
# d = i.dept_no
# print(type(d), d, d.dept_no, d.dept_name)
# --- 一對多查詢
# print(smps.all())
# print(smps.filter(pk__gt=30)) # 直接用Salary.objects即可管理
#
# print(*Employee.__dict__.items(), sep='\n')
# print('-'*30)
# print(*Salary.__dict__.items(), sep='\n')
# 查詢1004号員工的所有工資(建議從"一"端查,隻查詢一次)
# print(emps.get(pk=10004).salary_set.all()) # 記得加all()
# 工資大于55000的所有員工的姓名
# print(smps.filter(salary__gt=55000).values('emp_no').distinct())
# 查詢1004号員工的所有工資及姓名(建議從"一"端查,隻查詢一次)
# print(emps.get(pk=10004).salary_set.all()) # 記得加all()
# print(emps.get(pk=10004).name)
# 查詢工資大于55000的所有員工姓名(emp_no僅表示關系,salary_set,emp_no才是2個表真正用的屬性)
# nos = smps.filter(salary__gt=55000)
# names = set()
# for i in nos:
# names.add(i.emp_no.name)
# print(names)
# 查詢10004員工所有工資及姓名
# slist = list(smps.filter(emp_no=10004).filter(salary__gt=55000))
# for s in slist:
# print(s.emp_no.name, s.emp_no_id, s.salary) # s.emp_no 這裡的emp_no表示【關系】
# 員工大于55000的所有員工的姓名
#
# sql = """
# SELECT DISTINCT e.emp_no, e.first_name, e.last_name
# FROM employees e JOIN salaries s
# ON e.emp_no=s.emp_no
# WHERE s.salary > 55000
# """
# # print(emps.raw(sql)) #惰性的set
# print(list(emps.raw(sql)))
# --- 緩存驗證
# print(emps)
# print(*emps, sep='\n')
# print(emps[0].gender, emps[0].get_gender_display())
# print(type(emps))
# print(1, emps)
# print(2, emps)
# print(3, emps[0])
# print(4, emps[0])
# print(emps._result_cache)
# # 上面共查詢了4次資料庫,emps._result_cache為None,說明emps是惰性的
# print(type(emps)) # QuerySet查詢集
# print(list(emps)) # print(*emps) 先周遊一遍,緩存住
# print(1, emps)
# print(2, emps)
# print(3, emps[0])
# print(4, emps[:])
# print(emps._result_cache) # 結果集清單
# # 上面list(emps)進行了緩存,是以下面4個就不進行查詢了,直接利用了緩存,綜合查詢了1次
# # --- 切片和步長
# print(emps[10:15])
# print(emps[20:30])
# print(emps[0:20:5])
# print(emps[::5])
# # --- 結果集查詢
# print(emps.values())
# print(emps.filter(pk=10010).values())
# print(emps.exclude(emp_no=10001))
# print(emps.exclude(emp_no=10002).order_by('emp_no'))
# print(emps.exclude(emp_no=10002).order_by('-pk'))
# print(emps.exclude(emp_no=10002).order_by('-pk').values())
# # values傳回的集合裡的元素是字典
# # --- 單值查詢
# print(emps.filter(pk=10010).get())
# print(emps.get(pk=10001))
# #print(emps.exclude(pk=10010).get()) # get嚴格一個
# print(emps.first()) # limit 1
# print(emps.exclude(pk=10010).last()) # desc, limit 1
# print(emps.filter(pk=10010, gender=1).first()) # AND,找不到傳回None
# print(emps.count())
# print(emps.exclude(pk=10010).count())
# # --- LOOKUP表達式
# print(emps.filter(emp_no__exact=10010)) # 就是等于,是以很少用exact
# print(emps.filter(pk__in=[10010, 10009]))
# print(emps.filter(last_name__startswith='P'))
# print(emps.exclude(pk__gt=10003))
# # --- Q對象
# print(emps.filter(Q(pk__lt=10006))) # 不如直接寫filter(pk__lt=10006)
# # 下面幾句一樣
# print(emps.filter(pk__gt=10003).filter(pk__lt=10006)) # 與
# print(emps.filter(pk__gt=10003, pk__lt=10006)) # 與
# print(emps.filter(Q(pk__gt=10003), Q(pk__lt=10006)))
# print(emps.filter(Q(pk__gt=10003) & Q(pk__lt=10006))) # 與
# print(emps.filter(pk__gt=10003) & emps.filter(pk__lt=10006))
# # 下面幾句等價
# print(emps.filter(pk__in=[10003, 10006])) # in
# print(emps.filter(Q(pk=10003) | Q(pk=10006))) # 或
# print(emps.filter(pk=10003) | emps.filter(pk=10006))
#
# print(emps.filter(~Q(pk__gt=10003))) # 非
# # 可使用&|和Q對象來構造複雜的邏輯表達式,可以使用一個或多個Q對象。
# # 如果混用關鍵字參數和Q對象,那麼Q對象必須位于關鍵字參數的前面。
# --- 聚合分組
# # aggregate() 傳回字典,友善使用
# print(emps.filter(pk__gt=10010).count()) # 單值
# print(emps.filter(pk__gt=10010).aggregate(Count('pk'), Max('pk'))) # 字典
# print(emps.filter(pk__lte=10010).aggregate(Avg('pk')))
# print(emps.aggregate(Max('pk'), min=Min('pk'))) # 别名
# # annotate()方法用來分組聚合,傳回查詢集。
# print(emps.filter(pk__gt=10010).aggregate(Count('pk'))) # 字典
# s = emps.filter(pk__gt=10010).annotate(Count('pk')) # 傳回查詢集,沒指定分組字段,
# # print(s)
# # 使用主鍵分組
# for x in s:
# print(x)
# print(x.__dict__) # 裡面多了一個屬性pk__count
# # values()方法,放在annotate前就是指定分組字段,之後就是取結果中的字段。
# s = emps.filter(pk__gt=10010).values('gender').annotate(Count('pk')) # 查詢集
# print(s)
# for x in s:
# print(x) # 字典
# s = emps.filter(pk__gt=10010).values('gender').annotate(c=Count('pk')).order_by('-c') # 查詢集
# print(s)
# for x in s:
# print(x) # 字典
# s = emps.filter(pk__gt=10010).values('gender').annotate(Avg('pk'), c=Count('pk')).order_by('-c').values('pk__avg', 'c') # 查詢集,但後面的values過濾了每個對象字典的key
# print(s)
# for x in s:
# print(x) # 字典
# --- 練習題(記得用test2資料庫)
# # # 導入資料
#
# stu_list = [('王一涵',10),('張青陽',12),('韓名博',12),('王梓',13),('駱銘峰',11),('赢乘風',11),('林烽',10),('吳博文',12),('馬小文',12)]
# sco_list = [(1,'國文',90,'王一涵'),(2,'數學',80,'王一涵'),(3,'英語',75,'王一涵'),(4,'國文',95,'張青陽'),(5,'數學',90,'張青陽'),(6,'英語',98,'張青陽'),(7,'國文',80,'韓名博'),(8,'數學',89,'韓名博'),(9,'英語',70,'韓名博'),(10,'國文',60,'王梓'),(11,'數學',75,'王梓'),(12,'英語',65,'王梓'),(13,'國文',81,'駱銘峰'),(14,'數學',82,'駱銘峰'),(15,'英語',55,'駱銘峰'),(16,'國文',78,'赢乘風'),(17,'數學',89,'赢乘風'),(18,'英語',65,'赢乘風'),(19,'國文',89,'林烽'),(20,'數學',60,'林烽'),(21,'英語',49,'林烽'),(22,'國文',89,'吳博文'),(23,'數學',92,'吳博文'),(24,'英語',79,'吳博文'),(25,'國文',50,'馬小文'),(26,'數學',60,'馬小文'),(27,'英語',62,'馬小文')]
#
# for k,v in stu_list:
# Student(k,v).save()
#
# for s1,s2,s3,s4 in sco_list:
# Score(s1,s2,s3,s4).save()
#
#
# # 查詢
#
# stu = Student.objects.all()
# sco = Score.objects.all()
#
# # 總成績大于250分的學生資訊
# print(sco.values('name').annotate(Sum('score')).filter(score__sum__gt=250))
# # 國文成績在80-90分之間的學生資訊
# print(sco.filter(exam_subjects='國文').filter(score__gt=80,score__lt=90))
# # 有一門科目低于60分的學生資訊
# print(sco.filter(score__lt=60).values('name').annotate())
# # 平均分70以上的學生資訊
# print(sco.values('name').annotate(Avg('score')).filter(score__avg__gt=70))
# # 三門成績都大于90分的學生姓名
# print(sco.filter(score__gte=90).values('name').annotate(Count('score')).filter(score__count=3))
students models
from django.db import models
# Create your models here.
class Student(models.Model):
class Mate:
db_table = 'students'
# id = models.AutoField(primary_key=True)
name = models.CharField(primary_key=True, max_length=30, verbose_name='姓名')
age = models.PositiveSmallIntegerField(verbose_name='年齡')
def __repr__(self):
return '{} {}'.format(self.name, self.age)
__str__ = __repr__
class Score(models.Model):
class Mate:
db_table = 'scroes'
id = models.AutoField(primary_key=True)
exam_subjects = models.CharField(max_length=40, verbose_name='科目')
score = models.PositiveSmallIntegerField(verbose_name='分數')
name = models.ForeignKey(Student, db_column='name', on_delete=models.CASCADE)
# to_field = name (預設用的Studentde主鍵)
# name表示關系,db_column='name'的name表示資料庫顯示的名稱(資料庫用的名稱),ORM真正與資料的name對應的卻是name_id
def __repr__(self):
return '{} {} {}'.format(self.exam_subjects, self.score, self.name_id)
__str__ = __repr__
test.py
import os
import django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'salary.settings')
django.setup(set_prefix=False)
from employee.models import Employee, Salary, Department, Dept_emp
from students.models import Student, Score
from django.db.models import Q, Avg, Sum, Max, Min, Count
emps = Employee.objects.all()
smps = Salary.objects
dmps = Department.objects
demps = Dept_emp.objects
# --- 多對多查詢
# 查詢10010員工的所在的部門編号及員工資訊
# es = emps.get(pk=10010)
# ed = es.dept_emp_set.all() # 記得加all(),不然會傳回None
# print(es)
# print(ed)
# for i in ed:
# print(type(i), i)
# e = i.emp_no
# print(type(e), e)
# d = i.dept_no
# print(type(d), d, d.dept_no, d.dept_name)
# --- 一對多查詢
# print(smps.all())
# print(smps.filter(pk__gt=30)) # 直接用Salary.objects即可管理
#
# print(*Employee.__dict__.items(), sep='\n')
# print('-'*30)
# print(*Salary.__dict__.items(), sep='\n')
# 查詢1004号員工的所有工資(建議從"一"端查,隻查詢一次)
# print(emps.get(pk=10004).salary_set.all()) # 記得加all()
# 工資大于55000的所有員工的姓名
# print(smps.filter(salary__gt=55000).values('emp_no').distinct())
# 查詢1004号員工的所有工資及姓名(建議從"一"端查,隻查詢一次)
# print(emps.get(pk=10004).salary_set.all()) # 記得加all()
# print(emps.get(pk=10004).name)
# 查詢工資大于55000的所有員工姓名(emp_no僅表示關系,salary_set,emp_no才是2個表真正用的屬性)
# nos = smps.filter(salary__gt=55000)
# names = set()
# for i in nos:
# names.add(i.emp_no.name)
# print(names)
# 查詢10004員工所有工資及姓名
# slist = list(smps.filter(emp_no=10004).filter(salary__gt=55000))
# for s in slist:
# print(s.emp_no.name, s.emp_no_id, s.salary) # s.emp_no 這裡的emp_no表示【關系】
# 員工大于55000的所有員工的姓名
#
# sql = """
# SELECT DISTINCT e.emp_no, e.first_name, e.last_name
# FROM employees e JOIN salaries s
# ON e.emp_no=s.emp_no
# WHERE s.salary > 55000
# """
# # print(emps.raw(sql)) #惰性的set
# print(list(emps.raw(sql)))
# --- 緩存驗證
# print(emps)
# print(*emps, sep='\n')
# print(emps[0].gender, emps[0].get_gender_display())
# print(type(emps))
# print(1, emps)
# print(2, emps)
# print(3, emps[0])
# print(4, emps[0])
# print(emps._result_cache)
# # 上面共查詢了4次資料庫,emps._result_cache為None,說明emps是惰性的
# print(type(emps)) # QuerySet查詢集
# print(list(emps)) # print(*emps) 先周遊一遍,緩存住
# print(1, emps)
# print(2, emps)
# print(3, emps[0])
# print(4, emps[:])
# print(emps._result_cache) # 結果集清單
# # 上面list(emps)進行了緩存,是以下面4個就不進行查詢了,直接利用了緩存,綜合查詢了1次
# # --- 切片和步長
# print(emps[10:15])
# print(emps[20:30])
# print(emps[0:20:5])
# print(emps[::5])
# # --- 結果集查詢
# print(emps.values())
# print(emps.filter(pk=10010).values())
# print(emps.exclude(emp_no=10001))
# print(emps.exclude(emp_no=10002).order_by('emp_no'))
# print(emps.exclude(emp_no=10002).order_by('-pk'))
# print(emps.exclude(emp_no=10002).order_by('-pk').values())
# # values傳回的集合裡的元素是字典
# # --- 單值查詢
# print(emps.filter(pk=10010).get())
# print(emps.get(pk=10001))
# #print(emps.exclude(pk=10010).get()) # get嚴格一個
# print(emps.first()) # limit 1
# print(emps.exclude(pk=10010).last()) # desc, limit 1
# print(emps.filter(pk=10010, gender=1).first()) # AND,找不到傳回None
# print(emps.count())
# print(emps.exclude(pk=10010).count())
# # --- LOOKUP表達式
# print(emps.filter(emp_no__exact=10010)) # 就是等于,是以很少用exact
# print(emps.filter(pk__in=[10010, 10009]))
# print(emps.filter(last_name__startswith='P'))
# print(emps.exclude(pk__gt=10003))
# # --- Q對象
# print(emps.filter(Q(pk__lt=10006))) # 不如直接寫filter(pk__lt=10006)
# # 下面幾句一樣
# print(emps.filter(pk__gt=10003).filter(pk__lt=10006)) # 與
# print(emps.filter(pk__gt=10003, pk__lt=10006)) # 與
# print(emps.filter(Q(pk__gt=10003), Q(pk__lt=10006)))
# print(emps.filter(Q(pk__gt=10003) & Q(pk__lt=10006))) # 與
# print(emps.filter(pk__gt=10003) & emps.filter(pk__lt=10006))
# # 下面幾句等價
# print(emps.filter(pk__in=[10003, 10006])) # in
# print(emps.filter(Q(pk=10003) | Q(pk=10006))) # 或
# print(emps.filter(pk=10003) | emps.filter(pk=10006))
#
# print(emps.filter(~Q(pk__gt=10003))) # 非
# # 可使用&|和Q對象來構造複雜的邏輯表達式,可以使用一個或多個Q對象。
# # 如果混用關鍵字參數和Q對象,那麼Q對象必須位于關鍵字參數的前面。
# --- 聚合分組
# # aggregate() 傳回字典,友善使用
# print(emps.filter(pk__gt=10010).count()) # 單值
# print(emps.filter(pk__gt=10010).aggregate(Count('pk'), Max('pk'))) # 字典
# print(emps.filter(pk__lte=10010).aggregate(Avg('pk')))
# print(emps.aggregate(Max('pk'), min=Min('pk'))) # 别名
# # annotate()方法用來分組聚合,傳回查詢集。
# print(emps.filter(pk__gt=10010).aggregate(Count('pk'))) # 字典
# s = emps.filter(pk__gt=10010).annotate(Count('pk')) # 傳回查詢集,沒指定分組字段,
# # print(s)
# # 使用主鍵分組
# for x in s:
# print(x)
# print(x.__dict__) # 裡面多了一個屬性pk__count
# # values()方法,放在annotate前就是指定分組字段,之後就是取結果中的字段。
# s = emps.filter(pk__gt=10010).values('gender').annotate(Count('pk')) # 查詢集
# print(s)
# for x in s:
# print(x) # 字典
# s = emps.filter(pk__gt=10010).values('gender').annotate(c=Count('pk')).order_by('-c') # 查詢集
# print(s)
# for x in s:
# print(x) # 字典
# s = emps.filter(pk__gt=10010).values('gender').annotate(Avg('pk'), c=Count('pk')).order_by('-c').values('pk__avg', 'c') # 查詢集,但後面的values過濾了每個對象字典的key
# print(s)
# for x in s:
# print(x) # 字典
# --- 練習題(記得用test2資料庫)
# # # 導入資料
#
# stu_list = [('王一涵',10),('張青陽',12),('韓名博',12),('王梓',13),('駱銘峰',11),('赢乘風',11),('林烽',10),('吳博文',12),('馬小文',12)]
# sco_list = [(1,'國文',90,'王一涵'),(2,'數學',80,'王一涵'),(3,'英語',75,'王一涵'),(4,'國文',95,'張青陽'),(5,'數學',90,'張青陽'),(6,'英語',98,'張青陽'),(7,'國文',80,'韓名博'),(8,'數學',89,'韓名博'),(9,'英語',70,'韓名博'),(10,'國文',60,'王梓'),(11,'數學',75,'王梓'),(12,'英語',65,'王梓'),(13,'國文',81,'駱銘峰'),(14,'數學',82,'駱銘峰'),(15,'英語',55,'駱銘峰'),(16,'國文',78,'赢乘風'),(17,'數學',89,'赢乘風'),(18,'英語',65,'赢乘風'),(19,'國文',89,'林烽'),(20,'數學',60,'林烽'),(21,'英語',49,'林烽'),(22,'國文',89,'吳博文'),(23,'數學',92,'吳博文'),(24,'英語',79,'吳博文'),(25,'國文',50,'馬小文'),(26,'數學',60,'馬小文'),(27,'英語',62,'馬小文')]
#
# for k,v in stu_list:
# Student(k,v).save()
#
# for s1,s2,s3,s4 in sco_list:
# Score(s1,s2,s3,s4).save()
#
#
# # 查詢
#
# stu = Student.objects.all()
# sco = Score.objects.all()
#
# # 總成績大于250分的學生資訊
# print(sco.values('name').annotate(Sum('score')).filter(score__sum__gt=250))
# # 國文成績在80-90分之間的學生資訊
# print(sco.filter(exam_subjects='國文').filter(score__gt=80,score__lt=90))
# # 有一門科目低于60分的學生資訊
# print(sco.filter(score__lt=60).values('name').annotate())
# # 平均分70以上的學生資訊
# print(sco.values('name').annotate(Avg('score')).filter(score__avg__gt=70))
# # 三門成績都大于90分的學生姓名
# print(sco.filter(score__gte=90).values('name').annotate(Count('score')).filter(score__count=3))
settings.py
"""
Django settings for salary project.
Generated by 'django-admin startproject' using Django 3.2.6.
For more information on this file, see
https://docs.djangoproject.com/en/3.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.2/ref/settings/
"""
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-(uouz1h2%5ey)2+n6o8efxd+p+h!@m&we+1%6erp6ng79j9p#2'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'employee',
'students',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'salary.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'salary.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'OPTIONS': {'charset': 'utf8'},
'NAME': 'test',
'USER': 'soymilk',
'PASSWORD': '123456',
'HOST': '172.16.241.2',
'PORT': '3306',
}
}
# Password validation
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/3.2/topics/i18n/
LANGUAGE_CODE = 'zh-Hans' # 'en-us'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/
STATIC_URL = '/static/'
# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'level': 'DEBUG',
},
},
}