from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt from django.shortcuts import render, redirect from common.models import * from django.db.models import Q from django.contrib.auth.decorators import login_required from .forms import RequestForm, SequenceForm, AlbumForm, PlanForm from .validators import check_plan_validity, check_album_validity, check_sequence_validity, check_request_validity from .RequestSerializer import RequestSerializer import scheduler """ logger """ from django.conf import settings import utils.Logger as l log = l.setupLogger("routine_manager-views", "routine_manager-views") """ XML Export / Import utils """ from wsgiref.util import FileWrapper from django.utils.encoding import smart_str from django.http import HttpResponse import mimetypes import os from pprint import pprint SAVED_REQUESTS_FOLDER = "misc/saved_requests/" @login_required def requests_list(request, status=0, message=""): """ Retrieves and display the routines list (routine manager main page) """ if settings.DEBUG: log.info("From requests_list") if status == "-1": error = True elif status == "1": success = True # TODO: uncomment for alert filter # requests_objs = Request.objects.filter(pyros_user=request.user).filter(is_alert=False).order_by("-updated") requests_objs = Request.objects.filter(pyros_user=request.user).order_by("-updated") print("REQ/views: Les requetes sont:") requests = [] for req in requests_objs: #print("- REQ/views: requete", req) sequences = req.sequences nb_executed = sequences.filter(status=Sequence.EXECUTED).count nb_cancelled = sequences.filter(Q(status=Sequence.INVALID) | Q(status=Sequence.CANCELLED) | Q(status=Sequence.UNPLANNABLE)).count() requests.append({'req': req, 'nb_seq': sequences.count(), 'nb_executed': nb_executed, 'nb_cancelled': nb_cancelled}) print("REQ/views: ICI:") # opens template src/routine_manager/templates/routine_manager/requests_list.html with all local variables return render(request, "routine_manager/requests_list.html", locals()) @login_required def action_request(request, req_id, action, status=0, message=""): """ Apply actions (view, edit, delete) on a given request """ req = Request.objects.get(id=req_id) depth_level = 1 if settings.DEBUG: log.info("From action_request") if status == "-1": error = True elif status == "1": success = True if req.submitted == True and action == "edit": error = True message = "You can't edit a submitted request" action = "view" if check_request_validity(req) == True: return redirect(unsubmit_request, req_id) if action == "edit": form = RequestForm(instance=req) edit = True return render(request, "routine_manager/view_request.html", locals()) elif action == "view": form = RequestForm(instance=req, readonly=True) edit = False return render(request, "routine_manager/view_request.html", locals()) elif action == "delete": req.delete() return redirect(requests_list, status='1', message="Successfully deleted the request") return redirect(requests_list) @login_required def request_validate(request, req_id): """ Called when the request form was validated. Possible actions : Cancel, Save, Save and add sequence, Delete """ action = request.POST.get("action") req = Request.objects.get(id=req_id) form = RequestForm(instance=req, data=request.POST) if (settings.DEBUG): log.info("From request_validate") if action == "cancel": if req.name == "New request": req.delete() return redirect(requests_list, status=1, message="Cancelled request modification") elif action == "delete": return redirect(action_request, req_id, "delete") elif form.is_valid(): req = form.save() if action == "save": return redirect(action_request, req_id=req_id, action="edit", status=1, message="Request saved") if action == "save_and_add": return redirect(create_sequence, req_id=req_id) else: error = True message = "Please check your field's validity" depth_level = 1 edit = True return render(request, "routine_manager/view_request.html", locals()) @login_required def action_sequence(request, seq_id, action, status=0, message=""): """ Apply actions (view, edit, delete) on a given sequence """ seq_id = int(seq_id) seq = Sequence.objects.get(id=seq_id) req = seq.request req_id = req.id depth_level = 2 if (settings.DEBUG): log.info("From action_sequence") if status == "-1": error = True elif status == "1": success = True if seq.status != Sequence.INCOMPLETE and seq.status != Sequence.COMPLETE and action == "edit": error = True message = "You can't edit a submitted request" action = "view" if check_sequence_validity(seq) == True: return redirect(unsubmit_request, req_id) if action == "edit": form = SequenceForm(instance=seq) edit = True return render(request, "routine_manager/view_sequence.html", locals()) elif action == "view": form = SequenceForm(instance=seq, readonly=True) edit = False return render(request, "routine_manager/view_sequence.html", locals()) elif action == "delete": seq.delete() if check_request_validity(req) == True: return redirect(unsubmit_request, req_id) return redirect(action_request, req_id=seq.request.id, action="edit", status='1', message="Successfully deleted the sequence") return redirect(requests_list) @login_required def sequence_validate(request, seq_id): """ Called when the sequence form was validated. Possible actions : Cancel, Save, Save and add album, Delete """ if (settings.DEBUG): log.info("From sequence_validate") seq_id = int(seq_id) action = request.POST.get("action") seq = Sequence.objects.get(id=seq_id) form = SequenceForm(instance=seq, data=request.POST) if action == "cancel": if seq.name == "New sequence": seq.delete() return redirect(action_request, req_id=seq.request.id, action="edit", status='1', message="Cancelled sequence modification") elif action == "delete": return redirect(action_sequence, seq_id, "delete") elif form.is_valid(): seq = form.save() if action == "save": return redirect(action_sequence, seq_id=seq_id, action="edit", status=1, message="Sequence saved") if action == "save_and_add": return redirect(create_album, seq_id=seq_id) else: error = True message = "Please check your field's validity" depth_level = 2 edit = True req = seq.request req_id = req.id return render(request, "routine_manager/view_sequence.html", locals()) @login_required def action_album(request, alb_id, action, status=0, message=""): """ Apply actions (view, edit, delete) on a given album """ alb_id = int(alb_id) alb = Album.objects.get(id=alb_id) req = alb.sequence.request req_id = req.id seq_id = alb.sequence.id depth_level = 3 if (settings.DEBUG): log.info("From action_album") if status == "-1": error = True elif status == "1": success = True if alb.sequence.status != Sequence.INCOMPLETE and alb.sequence.status != Sequence.COMPLETE and action == "edit": error = True message = "You can't edit a submitted request" action = "view" if check_album_validity(alb) == True: return redirect(unsubmit_request, req_id) if action == "edit": form = AlbumForm(instance=alb) edit = True return render(request, "routine_manager/view_album.html", locals()) elif action == "view": form = AlbumForm(instance=alb, readonly=True) edit = False return render(request, "routine_manager/view_album.html", locals()) elif action == "delete": alb.delete() return redirect(action_sequence, seq_id=alb.sequence.id, action="edit", status='1', message="Successfully deleted the album") return redirect(requests_list) @login_required def album_validate(request, alb_id): """ Called when the album form was validated. Possible actions : Cancel, Save, Save and add plan, Delete """ alb_id = int(alb_id) action = request.POST.get("action") alb = Album.objects.get(id=alb_id) form = AlbumForm(instance=alb, data=request.POST) if (settings.DEBUG): log.info("From album_validate") if action == "cancel": if alb.name == "New album": alb.delete() return redirect(action_sequence, seq_id=alb.sequence.id, action="edit", status='1', message="Cancelled album modification") elif action == "delete": return redirect(action_album, alb_id, "delete") elif form.is_valid(): alb = form.save() if action == "save": return redirect(action_album, alb_id=alb_id, action="edit", status=1, message="Album saved") if action == "save_and_add": return redirect(create_plan, alb_id=alb_id) else: error = True message = "Please check your field's validity" depth_level = 3 edit = True req = alb.sequence.request req_id = req.id seq_id = alb.sequence.id action = "edit" return render(request, "routine_manager/view_album.html", locals()) @login_required def action_plan(request, plan_id, action, status=0, message=""): """ Apply actions (view, edit, delete) on a given plan """ plan_id = int(plan_id) plan = Plan.objects.get(id=plan_id) req = plan.album.sequence.request req_id = req.id seq_id = plan.album.sequence.id alb_id = plan.album.id depth_level = 4 if (settings.DEBUG): log.info("From action_plan") if status == "-1": error = True elif status == "1": success = True if plan.album.sequence.status != Sequence.INCOMPLETE and plan.album.sequence.status != Sequence.COMPLETE and action == "edit": error = True message = "You can't edit a submitted request" action = "view" if check_plan_validity(plan) == True: return redirect(unsubmit_request, req_id) if action == "edit": form = PlanForm(instance=plan) edit = True return render(request, "routine_manager/view_plan.html", locals()) elif action == "view": form = PlanForm(instance=plan, readonly=True) edit = False return render(request, "routine_manager/view_plan.html", locals()) elif action == "delete": plan.delete() return redirect(action_album, alb_id=plan.album.id, action="edit", status='1', message="Successfully deleted the plan") return redirect(requests_list) @login_required def plan_validate(request, plan_id): """ Called when the plan form was validated. Possible actions : Cancel, Save, Delete """ plan_id = int(plan_id) action = request.POST.get("action") plan = Plan.objects.get(id=plan_id) form = PlanForm(instance=plan, data=request.POST) if (settings.DEBUG): log.info("From plan_validate") if action == "cancel": if plan.name == "New plan": plan.delete() return redirect(action_album, alb_id=plan.album.id, action="edit", status='1', message="Cancelled plan modification") elif action == "delete": return redirect(action_plan, plan_id, "delete") elif form.is_valid(): plan = form.save() if action == "save": return redirect(action_plan, plan_id=plan_id, action="edit", status=1, message="Plan saved") else: error = True message = "Please check your field's validity" edit = True req = plan.album.sequence.request req_id = req.id seq_id = plan.album.sequence.id alb_id = plan.album.id depth_level = 4 return render(request, "routine_manager/view_plan.html", locals()) @login_required def create_request(request): """ Create a new request and redirects to the editing action on it """ req = Request.objects.create(pyros_user=request.user, name="New request", is_alert=False, autodeposit=False, complete=False, submitted=False) return redirect(action_request, req.id, "edit") @login_required def create_sequence(request, req_id): """ Create a new sequence and redirects to the editing action on it """ req = Request.objects.get(id=req_id) seq = Sequence.objects.create(request=req, name="New sequence", status=Sequence.INCOMPLETE) return redirect(action_sequence, seq.id, "edit") @login_required def create_album(request, seq_id): """ Create a new album and redirects to the editing action on it """ seq = Sequence.objects.get(id=seq_id) alb = Album.objects.create(sequence=seq, name="New album", complete=False) return redirect(action_album, alb.id, "edit") @login_required def create_plan(request, alb_id): """ Create a new plan and redirects to the editing action on it """ alb = Album.objects.get(id=alb_id) plan = Plan.objects.create(album=alb, name="New plan", complete=False) return redirect(action_plan, plan.id, "edit") @login_required def submit_request(request, req_id, redir): """ Submits a request and its sequences for scheduling """ if (settings.DEBUG): log.info("From submit_request") req = Request.objects.get(id=req_id) error = False if req.complete == False: error = True message = "A request must be complete to be submitted" elif req.submitted == True: error = True message = "The request is already submitted" if error == True: return redirect(action_request, req_id=req_id, action="view", status=-1, message=message) for seq in req.sequences.all(): seq.status = Sequence.TOBEPLANNED seq.save() req.submitted = True req.save() # TODO : changer le first_schedule ... if settings.USE_CELERY: print("WITH CELERY") scheduler.tasks.scheduling.delay(first_schedule=True, alert=False) else: print("WITHOUT CELERY") scheduler.tasks.scheduling().run(first_schedule=True, alert=False) message = "The request was submitted" if redir == "action_request": return redirect(action_request, req_id=req_id, action="view", status=1, message=message) else: return redirect(requests_list, status=1, message=message) @login_required def unsubmit_request(request, req_id): """ Unsubmits a request and remove its sequences from scheduling """ if (settings.DEBUG): log.info("From unsubmit_request") req = Request.objects.get(id=req_id) # TODO: uncomment pour la production # if req.sequences.filter(Q(status=Sequence.EXECUTED) | Q(status=Sequence.EXECUTING)).exists(): # message = "You can't unsubmit a request with executed sequences" # return redirect(action_request, req_id=req_id, action="view", status=-1, message=message) req.submitted = False req.save() sequences = req.sequences.filter(Q(status=Sequence.TOBEPLANNED) | Q(status=Sequence.PLANNED) | Q(status=Sequence.INVALID) | Q(status=Sequence.UNPLANNABLE)) for seq in sequences: seq.status = Sequence.COMPLETE seq.save() # TODO: uncomment # scheduler.tasks.scheduling.delay(first_schedule=True, alert=False) # TODO : changer le first_schedule ... if req.complete == True: message = "The request was unsubmitted" else: message = "The request was unsubmitted because it is incomplete" return redirect(action_request, req_id=req_id, action="edit", status=1, message=message) @login_required def export_request(request, req_id): """ Create an XML file with the given request, and send a download request to the user """ if (settings.DEBUG): log.info("From export_request") req = Request.objects.get(id=req_id) if req.complete == False: message = "Request must be completely valid to be serialized" return redirect(action_request, req_id=req_id, action="view", status=-1, message=message) file_name = SAVED_REQUESTS_FOLDER + "request" + str(req.id) + ".xml" rs = RequestSerializer() rs.serialize(req, file_name) wrapper = FileWrapper(open(file_name, "r")) content_type = mimetypes.guess_type(file_name)[0] response = HttpResponse(wrapper, content_type=content_type) response['Content-Length'] = os.path.getsize(file_name) response['Content-Disposition'] = 'attachment; filename=%s' % smart_str(os.path.basename(file_name)) return response @login_required @csrf_exempt def import_request(request): """ Ask for a XML file, parse it and create a request in DB Don't do anything if there is a single error into the file """ if (settings.DEBUG): log.info("From import_request") log.info(request) if request.method == "POST": file = request.FILES.get("request_file") if file is None: status = -1 message = "File does not exist" elif file.size > 1000000: status = -1 message = "File is too big (more than 1 000 000 bytes)" else: rs = RequestSerializer() message = rs.unserialize(file.read(), request.user) if message != "": status = -1 else: status = 1 message = "Request imported successfully. Please check it before submitting for scheduling." print("message is", message) else: status = -1 message = "Internal error" # Now, display the list of requests (updated with this new request) return redirect(requests_list, status=status, message=message)