annuaire-eleves/fiches/management/commands/add_conscrits.py
2020-11-13 11:45:32 +01:00

109 lines
3.8 KiB
Python

from datetime import date
from io import BytesIO
from urllib.error import HTTPError
from urllib.request import urlopen
from django.conf import settings
from django.contrib.auth.models import User
from django.core.files import File
from django.core.management.base import BaseCommand
from fiches.models import Department, Profile
from ._ldap import AnnuaireLDAP, ClipperLDAP
class Command(BaseCommand):
help = (
"Importe les noms et (si possible) les photos des conscrit·e·s dans l'annuaire."
)
def add_arguments(self, parser):
group = parser.add_mutually_exclusive_group()
group.add_argument(
"--all", action="store_true", help="Importe l'intégralité des promotions"
)
group.add_argument("--promo", help="Spécifie la promotion à importer")
parser.add_argument(
"--without-photos",
action="store_true",
help="N'essaie pas d'importer les photos associées",
)
def get_current_promo(self):
today = date.today()
year = today.year
if today.month < 9:
year -= 1
return str(year)
def handle(self, *args, **options):
if options["all"]:
promo = None
elif options["promo"] is not None:
promo = options["promo"]
if len(promo) == 2:
promo = "20" + promo
else:
promo = self.get_current_promo()
# On récupère la liste des élèves à créer
ldap = ClipperLDAP()
clipper_list = ldap.get_clipper_list(promo_filter=promo)
# On vire les élèves déjà existants
existing_users = set(User.objects.values_list("username", flat=True))
clippers = [
clipper for clipper in clipper_list if clipper.uid not in existing_users
]
# Les départements sont créés à la main ; il y en a peu.
depts = {
dept: Department.objects.get_or_create(name=dept)[0].id
for dept in ldap.verbose_depts.values()
}
users_to_create = []
profiles_to_create = []
dept_m2m_to_create = []
for clipper in clippers:
user = User(username=clipper.uid, email=clipper.email)
profile = Profile(user=user, full_name=clipper.name, promotion=clipper.year)
users_to_create.append(user)
profiles_to_create.append(profile)
dept_m2m_to_create.append(
Profile.department.through(
profile=profile, department_id=depts[clipper.dept]
)
)
User.objects.bulk_create(users_to_create)
for profile in profiles_to_create:
profile.user_id = profile.user.id
profiles = Profile.objects.bulk_create(profiles_to_create)
for dept_m2m in dept_m2m_to_create:
dept_m2m.profile_id = dept_m2m.profile.id
Profile.department.through.objects.bulk_create(dept_m2m_to_create)
# Gestion des images
if not options["without_photos"]:
cri_ldap = AnnuaireLDAP()
base_annuaire = "{PROTOCOL}://{URL}:{PORT}".format(**settings.ANNUAIRE)
for clipper, profile in zip(clippers, profiles):
cri_login = cri_ldap.try_match(clipper)
if cri_login is not None:
img_url = "{}/photos/{}.jpg".format(base_annuaire, cri_login)
try:
istream = urlopen(img_url)
profile.picture.save(
name="{}.jpg".format(profile.user.username),
content=File(BytesIO(istream.read())),
)
except HTTPError:
# Parfois il y a une erreur 404 : dans ce cas, pas de photo
pass