dm.management.commands.updategraduatestatus 源代码
from django.core.management.base import BaseCommand, CommandParser, CommandError
from django.db import transaction
from app.models import (
NaturalPerson,
User
)
import csv
import os
status_map = {
0: '在读',
1: '已毕业',
2: '住宿辅导员',
3: '延毕',
4: '休学',
}
def _load_from_csv(file_path):
"""从csv文件加载学号和状态"""
if not os.path.exists(file_path):
raise CommandError('指定的文件路径不存在: %s' % file_path)
records = []
with open(file_path, 'r', encoding='utf-8') as f:
reader = csv.reader(f)
for row in reader:
if len(row) != 2:
raise CommandError('文件格式错误,每行应包含学号和状态两列,用逗号分隔: %s' % ','.join(row))
stu_id = row[0].strip()
try:
status = int(row[1].strip())
if status not in status_map:
raise ValueError
except ValueError:
raise CommandError('状态值错误,应为 %s: %s' % str(status_map), row[1])
records.append((stu_id, status))
return records
[文档]
class Command(BaseCommand):
help = '通过文件批量修改学生的毕业情况状态(毕业、休学、延毕、住宿辅导员)'
[文档]
def add_arguments(self, parser: CommandParser):
parser.add_argument(
'--config',
type=str,
help='指定包含特殊处理名单的csv文件路径,每行学号和状态(0-在读,1-已毕业,2-住宿辅导员,3-延毕,4-休学)用逗号分隔',
required=True
)
[文档]
def handle(self, *args, **options):
config = options['config']
data = _load_from_csv(config)
# Test run
cnt_modify = 0
cnt_nochange = 0
cnt_notfound = 0
for stu_id, status in data:
try:
person = NaturalPerson.objects.get(
stu_id_dbonly=stu_id,
identity = NaturalPerson.Identity.STUDENT)
except NaturalPerson.DoesNotExist:
self.stdout.write(self.style.ERROR('学号%s的学生不存在,跳过' % stu_id))
cnt_notfound += 1
continue
old_status = status_map[person.status]
new_status = status_map[status]
if old_status != new_status:
cnt_modify += 1
self.stdout.write(self.style.SUCCESS('学号%s的学生状态: %s -> %s' % (stu_id, old_status, new_status)))
else:
cnt_nochange += 1
self.stdout.write(self.style.SUCCESS('学号%s的学生状态: %s 不变' % (stu_id, old_status)))
self.stdout.write(self.style.WARNING('=> 共处理学生%d人, 修改状态%d人, 未修改%d人, 未找到%d人' % (
cnt_modify + cnt_nochange + cnt_notfound, cnt_modify, cnt_nochange, cnt_notfound)))
self.stdout.write(self.style.WARNING('请确认无误后,输入y以继续,n以取消'))
confirm = input()
if confirm.lower() != 'y':
self.stdout.write(self.style.ERROR('操作已取消'))
return
else:
with transaction.atomic():
for stu_id, status in data:
try:
person = NaturalPerson.objects.get(
stu_id_dbonly=stu_id,
identity = NaturalPerson.Identity.STUDENT)
except NaturalPerson.DoesNotExist:
self.stdout.write(self.style.ERROR('学号%s的学生不存在,跳过' % stu_id))
continue
person.status = status
if status == NaturalPerson.GraduateStatus.GRADUATED or status == NaturalPerson.GraduateStatus.ONLEAVE:
person.person_id.active = False # 毕业和休学的账号也要设置
person.accept_promote = False
person.person_id.save()
else:
person.person_id.active = True
person.accept_promote = True
person.person_id.save()
person.save()
self.stdout.write(self.style.SUCCESS('成功将学号%s的学生状态调整为%s' % (stu_id, status_map[status])))