Example #1
0
def accept_all_passes_view(request, scheduled_activity_id):
    if request.method != "POST":
        return http.HttpResponseNotAllowed(["POST"], "HTTP 405: METHOD NOT ALLOWED")

    try:
        scheduled_activity = EighthScheduledActivity.objects.get(id=scheduled_activity_id)
    except EighthScheduledActivity.DoesNotExist:
        raise http.Http404

    sponsor = request.user.get_eighth_sponsor()
    can_accept = (scheduled_activity.block.locked and (sponsor and (sponsor in scheduled_activity.get_true_sponsors()) or
                                                       request.user.is_eighth_admin))

    if not can_accept:
        return render(request, "error/403.html", {"reason": "You do not have permission to take accept these passes."}, status=403)

    EighthSignup.objects.filter(after_deadline=True, scheduled_activity=scheduled_activity).update(pass_accepted=True, was_absent=False)
    invalidate_obj(scheduled_activity)

    if "admin" in request.path:
        url_name = "eighth_admin_take_attendance"
    else:
        url_name = "eighth_take_attendance"

    return redirect(url_name, scheduled_activity_id=scheduled_activity.id)
Example #2
0
def remove_member_from_group_view(request, group_id, user_id):
    if request.method != "POST":
        return http.HttpResponseNotAllowed(["POST"], "HTTP 405: METHOD NOT ALLOWED")

    try:
        group = Group.objects.get(id=group_id)
    except Group.DoesNotExist as e:
        raise http.Http404 from e

    if not request.user.can_manage_group(group):
        messages.error(request, "You must be a superuser on Ion to manage administrative groups")
        return redirect("eighth_admin_dashboard")

    uid = request.POST.get("profile_id", 0)
    if uid:
        next_url = reverse("user_profile", args=(uid,))
    else:
        next_url = reverse("eighth_admin_edit_group", kwargs={"group_id": group_id})

    try:
        user = get_user_model().objects.get(id=user_id)
    except get_user_model().DoesNotExist:
        messages.error(request, "There was an error removing this user.")
        return redirect(next_url, status=400)

    group.user_set.remove(user)
    group.save()
    invalidate_obj(group)
    messages.success(request, 'Successfully removed user "{}" from the group.'.format(user.full_name))

    return redirect(next_url)
Example #3
0
def edit_profile_view(request, user_id=None):
    user = get_object_or_404(User, id=user_id)

    defaults = {}
    for field in ProfileEditForm.FIELDS:
        defaults[field] = getattr(user, field)

    for field in ProfileEditForm.ADDRESS_FIELDS:
        if user.address:
            defaults[field] = getattr(user.address, field)
        else:
            defaults[field] = None
    defaults["birthday"] = str(defaults["birthday"]).split(" ")[0]
    defaults["counselor_id"] = user.counselor.id if user.counselor else None

    if request.method == "POST":
        logger.debug("Saving")
        form = ProfileEditForm(request.POST)
        if form.is_valid():
            pass  # We don't care.
        items = form.cleaned_data
        new_data = {}
        for field in items:
            new = items[field]
            # old = defaults[field]
            # if str(new) != str(old):
            #    new_data[field] = new
            new_data[field] = new
        logger.debug(new_data)

        raw_ldap_attributes = ["birthday", "street", "city", "state", "postal_code", "counselor"]
        raw_ldap_override = {"city": "l", "state": "st", "postal_code": "postalCode", "counselor_id": "counselor"}
        override_set = ["graduation_year"]

        for key in new_data:
            if key in raw_ldap_attributes:
                if key in raw_ldap_override:
                    key = raw_ldap_override[key]
                if key in new_data:
                    if new_data[key] == " ":
                        new_data[key] = None
                    logger.debug("Setting raw {}={}".format(key, new_data[key]))
                    user.set_raw_ldap_attribute(key, new_data[key])
            else:
                logger.debug("Setting regular {}={}".format(key, new_data[key]))
                try:
                    user.set_ldap_attribute(key, new_data[key], key in override_set)
                except Exception as e:
                    messages.error(request, "Field {} with value {}: {}".format(key, new_data[key], e))
                    logger.debug("Field {} with value {}: {}".format(key, new_data[key], e))
                else:
                    messages.success(request, "Set field {} to {}".format(key, new_data[key]))
        user.save()
        invalidate_obj(user)
        user.clear_cache()
    else:
        form = ProfileEditForm(initial=defaults)

    context = {"profile_user": user, "form": form}
    return render(request, "eighth/edit_profile.html", context)
Example #4
0
def accept_all_passes_view(request, scheduled_activity_id):
    if request.method != "POST":
        return http.HttpResponseNotAllowed(["POST"], "HTTP 405: METHOD NOT ALLOWED")

    try:
        scheduled_activity = EighthScheduledActivity.objects.get(id=scheduled_activity_id)
    except EighthScheduledActivity.DoesNotExist:
        raise http.Http404

    sponsor = request.user.get_eighth_sponsor()
    can_accept = scheduled_activity.block.locked and (
        sponsor and (sponsor in scheduled_activity.get_true_sponsors()) or request.user.is_eighth_admin
    )

    if not can_accept:
        return render(
            request, "error/403.html", {"reason": "You do not have permission to take accept these passes."}, status=403
        )

    EighthSignup.objects.filter(after_deadline=True, scheduled_activity=scheduled_activity).update(
        pass_accepted=True, was_absent=False
    )
    invalidate_obj(scheduled_activity)

    if "admin" in request.path:
        url_name = "eighth_admin_take_attendance"
    else:
        url_name = "eighth_take_attendance"

    return redirect(url_name, scheduled_activity_id=scheduled_activity.id)
Example #5
0
    def test_44_workaround(self):
        make_query = lambda: list(self.photo.liked_user.order_by('id').cache())
        self.assertEqual(make_query(), [self.suor])

        PhotoLike.objects.create(user=self.peterdds, photo=self.photo)
        invalidate_obj(self.peterdds)
        self.assertEqual(make_query(), [self.suor, self.peterdds])
Example #6
0
def add_member_to_group_view(request, group_id):
    if request.method != "POST":
        return http.HttpResponseNotAllowed(["POST"],
                                           "HTTP 405: METHOD NOT ALLOWED")

    try:
        group = Group.objects.get(id=group_id)
    except Group.DoesNotExist:
        raise http.Http404

    next_url = reverse("eighth_admin_edit_group",
                       kwargs={"group_id": group_id})

    if "user_id" in request.POST:
        user_ids = request.POST.getlist("user_id")
        user_objects = get_user_model().objects.filter(
            id__in=user_ids).exclude(groups=group)
        next_url += "?"
        for user in user_objects:
            user.groups.add(group)
            user.save()
            if len(user_objects) < 25:
                next_url += "added={}&".format(user.id)
        invalidate_obj(group)
        messages.success(
            request, "Successfully added {} user{} to the group.".format(
                len(user_objects), "s" if len(user_objects) != 1 else ""))
        return redirect(next_url)

    if "query" not in request.POST:
        return redirect(next_url + "?error=s")

    query = request.POST["query"]
    from_sid = get_user_model().objects.user_with_student_id(query)
    if from_sid:
        if not from_sid.groups.filter(id=group.id).exists():
            from_sid.groups.add(group)
            from_sid.save()
        messages.success(
            request, 'Successfully added user "{}" to the group.'.format(
                from_sid.full_name))
        return redirect(next_url + "?added=" + str(from_sid.id))

    errors, results = get_search_results(query)
    if errors:
        messages.error(request, "Could not process search query.")
        return redirect(next_url + "?error=n")
    logger.debug(results)
    if not results:
        return redirect(next_url + "?error=n")
    else:
        users = sorted(results, key=lambda x: (x.last_name, x.first_name))
        context = {
            "query": query,
            "users": users,
            "group": group,
            "admin_page_title": "Add Members to Group"
        }
        return render(request, "eighth/admin/possible_students_add_group.html",
                      context)
Example #7
0
 def save(self,
          force_insert=False,
          force_update=False,
          using=None,
          update_fields=None):
     super().save(force_insert, force_update, using, update_fields)
     invalidate_obj(self.board)
Example #8
0
def migrate_outstanding_passes_view(request):
    if request.method == "POST":
        try:
            block_id = request.POST.get("block", None)
            block = EighthBlock.objects.get(id=block_id)
        except EighthBlock.DoesNotExist:
            raise http.Http404

        activity, created = (EighthActivity.objects.get_or_create(name="Z - 8th Period Pass Not Received", deleted=False))
        activity.restricted = True
        activity.sticky = True
        activity.administrative = True

        if not activity.description:
            activity.description = ("Pass received from the 8th period " "office was not turned in.")

        activity.save()
        invalidate_obj(activity)

        pass_not_received, created = (EighthScheduledActivity.objects.get_or_create(block=block, activity=activity))

        EighthSignup.objects.filter(scheduled_activity__block=block, after_deadline=True,
                                    pass_accepted=False).update(scheduled_activity=pass_not_received)

        messages.success(request, "Successfully migrated outstanding passes.")

        return redirect("eighth_admin_dashboard")
    else:
        blocks = EighthBlock.objects.filter(date__gte=get_start_date(request))

        context = {"admin_page_title": "Migrate Outstanding Passes", "blocks": blocks}

        return render(request, "eighth/admin/migrate_outstanding_passes.html", context)
def clear_cache(objects=None, models=None, purge=False):
    # this is required to refresh the templates content
    # otherwise after any update the page will not refresh properly
    try:
        cache.clear()
    except Exception as e:
        # ignore errors
        logger.error(str(e))

    if _is_cacheops_enabled():
        from cacheops import invalidate_all, invalidate_model, invalidate_obj

        if objects:
            for obj in objects:
                invalidate_obj(obj)

        if models:
            for model in models:
                get_content_type(model=model)  # add it to the models list
                invalidate_model(model)

        if purge:
            try:
                invalidate_all()
            except Exception as e:
                # Fixes: unknown command `FLUSHDB`
                #   In helm charts FLUSHDB and FLUSHALL commands are disabled
                logger.error(str(e))
                clear_cache(models=list(CONTENT_TYPE_CACHE.keys()))
Example #10
0
File: groups.py Project: tjcsl/ion
def remove_member_from_group_view(request, group_id, user_id):
    if request.method != "POST":
        return http.HttpResponseNotAllowed(["POST"], "HTTP 405: METHOD NOT ALLOWED")

    try:
        group = Group.objects.get(id=group_id)
    except Group.DoesNotExist:
        raise http.Http404

    uid = request.POST.get("profile_id", 0)
    if uid:
        next_url = reverse("user_profile", args=(uid,))
    else:
        next_url = reverse("eighth_admin_edit_group", kwargs={"group_id": group_id})

    try:
        user = User.objects.get(id=user_id)
    except User.DoesNotExist:
        messages.error(request, "There was an error removing this user.")
        return redirect(next_url, status=400)

    group.user_set.remove(user)
    group.save()
    invalidate_obj(group)
    messages.success(request, "Successfully removed user \"{}\" from the group.".format(user.full_name))

    return redirect(next_url)
Example #11
0
def add_activity_view(request):
    if request.method == "POST":
        form = QuickActivityForm(request.POST)
        if form.is_valid():
            new_id = request.POST.get("id", "default")
            if new_id == "default":
                activity = form.save()
            else:
                activity = (EighthActivity.objects.create(
                    name=form.cleaned_data["name"], id=int(new_id)))
            invalidate_obj(activity)
            messages.success(request, "Successfully added activity.")
            return redirect("eighth_admin_edit_activity",
                            activity_id=activity.id)
        else:
            messages.error(request, "Error adding activity.")
            request.session["add_activity_form"] = pickle.dumps(form)
            return redirect("eighth_admin_dashboard")
    else:
        context = {
            "admin_page_title": "Add Activity",
            "form": QuickActivityForm(),
            "available_ids": EighthActivity.available_ids()
        }
        return render(request, "eighth/admin/add_activity.html", context)
Example #12
0
    def test_big_invalidation(self):
        for x in range(8000):
            list(Category.objects.cache().exclude(pk=x))

        c = Category.objects.get(pk=1)
        invalidate_obj(
            c)  # lua unpack() fails with 8000 keys, workaround works
Example #13
0
def remove_member_from_group_view(request, group_id, user_id):
    if request.method != "POST":
        return http.HttpResponseNotAllowed(["POST"],
                                           "HTTP 405: METHOD NOT ALLOWED")

    try:
        group = Group.objects.get(id=group_id)
    except Group.DoesNotExist:
        raise http.Http404

    uid = request.POST.get("profile_id", 0)
    if uid:
        next_url = reverse("user_profile", args=(uid, ))
    else:
        next_url = reverse("eighth_admin_edit_group",
                           kwargs={"group_id": group_id})

    try:
        user = User.get_user(id=user_id)
    except User.DoesNotExist:
        messages.error(request, "There was an error removing this user.")
        return redirect(next_url, status=400)

    group.user_set.remove(user)
    group.save()
    invalidate_obj(group)
    messages.success(
        request, "Successfully removed user \"{}\" from the group.".format(
            user.full_name))

    return redirect(next_url)
Example #14
0
 def save(self, *args, **kwargs):
     if self.answer_type not in [
             MultiChoiceAnswer.choice_name(),
             MultiSelectAnswer.choice_name()]:
         self.options.all().delete()
     invalidate_obj(self.qset)       # to fix update of flow_question update
     return super(Question, self).save(*args, **kwargs)
Example #15
0
def delete_activity_view(request, activity_id=None):
    try:
        activity = EighthActivity.objects.get(id=activity_id)
    except EighthActivity.DoesNotExist:
        raise http.Http404

    perm_delete = False
    if activity.deleted and "perm" in request.GET:
        perm_delete = True

    if request.method == "POST":
        if perm_delete:
            activity.delete()
        else:
            activity.deleted = True
            activity.save()
            invalidate_obj(activity)
        messages.success(request, "Successfully deleted activity.")
        return redirect("eighth_admin_dashboard")
    else:
        context = {
            "admin_page_title":
            "Delete Activity",
            "item_name":
            activity.name,
            "help_text":
            ("Deleting will not destroy past attendance data for this "
             "activity. The activity will just be marked as deleted "
             "and hidden from non-attendance views."
             if not perm_delete else "This will destroy past attendance data.")
        }

        return render(request, "eighth/admin/delete_form.html", context)
Example #16
0
def migrate_outstanding_passes_view(request):
    if request.method == "POST":
        try:
            block_id = request.POST.get("block", None)
            block = EighthBlock.objects.get(id=block_id)
        except EighthBlock.DoesNotExist as e:
            raise http.Http404 from e

        activity, _ = EighthActivity.objects.get_or_create(name="Z - 8th Period Pass Not Received", deleted=False)
        activity.restricted = True
        activity.sticky = True
        activity.administrative = True

        if not activity.description:
            activity.description = "Pass received from the 8th period office was not turned in."

        activity.save()
        invalidate_obj(activity)

        pass_not_received, _ = EighthScheduledActivity.objects.get_or_create(block=block, activity=activity)

        EighthSignup.objects.filter(scheduled_activity__block=block, after_deadline=True, pass_accepted=False).update(
            scheduled_activity=pass_not_received
        )

        messages.success(request, "Successfully migrated outstanding passes.")

        return redirect("eighth_admin_dashboard")
    else:
        blocks = EighthBlock.objects.filter(date__gte=get_start_date(request))

        context = {"admin_page_title": "Migrate Outstanding Passes", "blocks": blocks}

        return render(request, "eighth/admin/migrate_outstanding_passes.html", context)
Example #17
0
def media_post_save(sender, **kwargs):

    obj = kwargs['instance']

    # ingest fingerprint
    if (AUTOCREATE_FPRINT and obj.master) and not obj.fprint_ingested:
        ingest_fprint_for_media.apply_async((obj, ))

    if not obj.folder:

        log.debug('no directory for media %s - create it.' % obj.pk)
        directory = get_dir_for_object(obj)
        abs_directory = os.path.join(settings.MEDIA_ROOT, directory)

        try:
            if not os.path.exists(abs_directory):
                os.makedirs(abs_directory, 0755)

            obj.folder = directory
            log.debug('creating directory: %s' % abs_directory)

        except Exception as e:
            log.warning('unable to create directory: %s - %s' %
                        (abs_directory, e))
            obj.folder = None
            obj.status = 99

    # invalidate cache
    invalidate_obj(obj)
Example #18
0
 def save(self, *args, **kwargs):
     if self.answer_type not in [
             MultiChoiceAnswer.choice_name(),
             MultiSelectAnswer.choice_name()]:
         self.options.all().delete()
     invalidate_obj(self.qset)       # to fix update of flow_question update
     return super(Question, self).save(*args, **kwargs)
Example #19
0
def delete_activity_view(request, activity_id=None):
    try:
        activity = EighthActivity.objects.get(id=activity_id)
    except EighthActivity.DoesNotExist:
        raise http.Http404

    perm_delete = False
    if activity.deleted and "perm" in request.GET:
        perm_delete = True

    if request.method == "POST":
        if perm_delete:
            activity.delete()
        else:
            activity.deleted = True
            activity.save()
            invalidate_obj(activity)
        messages.success(request, "Successfully deleted activity.")
        return redirect("eighth_admin_dashboard")
    else:
        context = {
            "admin_page_title": "Delete Activity",
            "item_name": activity.name,
            "help_text": (
                "Deleting will not destroy past attendance data for this "
                "activity. The activity will just be marked as deleted "
                "and hidden from non-attendance views."
                if not perm_delete
                else "This will destroy past attendance data."
            ),
        }

        return render(request, "eighth/admin/delete_form.html", context)
Example #20
0
def media_post_save(sender, **kwargs):

    obj = kwargs['instance']

    # ingest fingerprint
    if (AUTOCREATE_FPRINT and obj.master) and not obj.fprint_ingested:
        ingest_fprint_for_media.apply_async((obj.pk,))


    if not obj.folder:

        log.debug('no directory for media %s - create it.' % obj.pk)
        directory = get_dir_for_object(obj)
        abs_directory = os.path.join(settings.MEDIA_ROOT, directory)

        try:
            if not os.path.exists(abs_directory):
                os.makedirs(abs_directory, 0755)

            obj.folder = directory
            log.debug('creating directory: %s' % abs_directory)

        except Exception as e:
            log.warning('unable to create directory: %s - %s' % (abs_directory, e))
            obj.folder = None
            obj.status = 99

    # invalidate cache
    invalidate_obj(obj)
 def on_commit(items, init_flag):
     if init_flag:
         invalidate_model(BayesDictionary)
     else:
         # у запроса aggregate также сбросится кэш при сбрасывании кэша одной записи
         for instance in items:
             invalidate_obj(instance)
Example #22
0
def BorradoLogico(self):
	#to_delete, access = get_related_objects(self)
	#for i in range(0, len(access)):
	#	for obj in to_delete[i]:
	#		obj.delete()invalidate_obj
	self.is_active = timezone.now()
	super(type(self), self).save((), {})
	invalidate_obj(self)
Example #23
0
def open_passes_view(request):
    passes = (EighthSignup.objects
                          .filter(after_deadline=True,
                                  pass_accepted=False))
    if request.method == "POST":
        pass_ids = list(request.POST.keys())

        csrf = "csrfmiddlewaretoken"
        if csrf in pass_ids:
            pass_ids.remove(csrf)

        accepted = 0
        rejected = 0
        for signup_id in pass_ids:
            signup = EighthSignup.objects.get(id=signup_id)
            status = request.POST.get(signup_id)
            if status == "accept":
                signup.accept_pass()
                accepted += 1
            elif status == "reject":
                signup.reject_pass()
                rejected += 1
            invalidate_obj(signup)

        messages.success(request, "Accepted {} and rejected {} passes.".format(accepted, rejected))

    if request.resolver_match.url_name == "eighth_admin_view_open_passes_csv":
        response = http.HttpResponse(content_type="text/csv")
        filename = "\"open_passes.csv\""
        response["Content-Disposition"] = "attachment; filename=" + filename

        writer = csv.writer(response)
        writer.writerow(["Block",
                         "Activity",
                         "Student",
                         "Grade",
                         "Absences",
                         "Time (Last Modified)",
                         "Time (Created)"])

        for p in passes:
            row = []
            row.append(p.scheduled_activity.block)
            row.append(p.scheduled_activity.activity)
            row.append("{}, {} {}".format(p.user.last_name, p.user.first_name, p.user.nickname if p.user.nickname else ""))
            row.append(int(p.user.grade))
            row.append(p.user.absence_count())
            row.append(p.last_modified_time)
            row.append(p.created_time)
            writer.writerow(row)

        return response

    context = {
        "admin_page_title": "Open Passes",
        "passes": passes
    }
    return render(request, "eighth/admin/open_passes.html", context)
Example #24
0
def edit_activity_view(request, activity_id):
    try:
        activity = EighthActivity.undeleted_objects.get(id=activity_id)
    except EighthActivity.DoesNotExist:
        raise http.Http404

    if request.method == "POST":
        form = ActivityForm(request.POST, instance=activity)
        if form.is_valid():
            try:
                form.save()
            except forms.ValidationError as error:
                error = str(error)
                messages.error(request, error)
            else:
                messages.success(request, "Successfully edited activity.")
                if "add_group" in request.POST:
                    grp_name = "Activity: {}".format(activity.name)
                    grp, status = Group.objects.get_or_create(name=grp_name)
                    logger.debug(grp)
                    activity.restricted = True
                    activity.groups_allowed.add(grp)
                    activity.save()
                    invalidate_obj(activity)
                    messages.success(
                        request, "{} to '{}' group".format("Created and added" if status else "Added", grp_name)
                    )
                    return redirect("eighth_admin_edit_group", grp.id)

                return redirect("eighth_admin_edit_activity", activity_id)
        else:
            messages.error(request, "Error adding activity.")
    else:
        form = ActivityForm(instance=activity)

    activities = EighthActivity.undeleted_objects.order_by("name")

    activity_groups = []
    for g in activity.groups_allowed.all():
        group = {}
        group["id"] = g.id
        group["name"] = "{}".format(g)
        group["members_alpha"] = sorted(g.user_set.all(), key=lambda x: (x.last_name, x.first_name))
        group["members_alpha_count"] = len(group["members_alpha"])
        activity_groups.append(group)

    activity_members = sorted(activity.users_allowed.all(), key=lambda x: (x.last_name, x.first_name))
    context = {
        "form": form,
        "admin_page_title": "Edit Activity",
        "delete_url": reverse("eighth_admin_delete_activity", args=[activity_id]),
        "activity": activity,
        "activity_groups": activity_groups,
        "activities": activities,
        "activity_members": activity_members,
    }

    return render(request, "eighth/admin/edit_activity.html", context)
Example #25
0
def add_member_to_group_view(request, group_id):
    if request.method != "POST":
        return http.HttpResponseNotAllowed(["POST"], "HTTP 405: METHOD NOT ALLOWED")

    try:
        group = Group.objects.get(id=group_id)
    except Group.DoesNotExist:
        raise http.Http404

    next_url = reverse("eighth_admin_edit_group", kwargs={"group_id": group_id})

    if "user_id" in request.POST:
        user_ids = request.POST.getlist("user_id")
        user_objects = User.objects.filter(id__in=user_ids)
        next_url += "?"
        for user in user_objects:
            user.groups.add(group)
            user.save()
            if len(user_objects) < 25:
                next_url += "added={}&".format(user.id)
        invalidate_obj(group)
        messages.success(request, "Successfully added {} user{} to the group.".format(len(user_objects), "s" if len(user_objects) != 1 else ""))
        return redirect(next_url)

    if "query" not in request.POST:
        return redirect(next_url + "?error=s")

    query = request.POST["query"]
    from_sid = User.objects.user_with_student_id(query)
    if from_sid:
        from_sid.groups.add(group)
        from_sid.save()
        messages.success(request, "Successfully added user \"{}\" to the group.".format(from_sid.full_name))
        return redirect(next_url + "?added=" + str(from_sid.id))

    errors, results = get_search_results(query)
    logger.debug(results)
    if len(results) == 1:
        user_id = results[0].id
        logger.debug("User id: {}".format(user_id))
        user = User.objects.user_with_ion_id(user_id)

        user.groups.add(group)
        user.save()
        messages.success(request, "Successfully added user \"{}\" to the group.".format(user.full_name))
        return redirect(next_url + "?added=" + str(user_id))
    elif len(results) == 0:
        return redirect(next_url + "?error=n")
    else:
        users = results
        results = sorted(results, key=lambda x: (x.last_name, x.first_name))
        context = {
            "query": query,
            "users": users,
            "group": group,
            "admin_page_title": "Add Members to Group"
        }
        return render(request, "eighth/admin/possible_students_add_group.html", context)
Example #26
0
 def handle_obj(self, app_name, model_name, obj_pk):
     model = get_model(app_name, model_name)
     if model is None:
         raise CommandError('Unknown model: %s.%s' % (app_name, model_name))
     try:
         obj = model.objects.get(pk=obj_pk)
     except model.DoesNotExist:
         raise CommandError('No %s.%s with pk = %s' % (app_name, model_name, obj_pk))
     invalidate_obj(obj)
Example #27
0
def invalidate_organization_cache(sender, **kwargs):
    """
    Invalidate org cache when users are added and removed.
    Done w/ special methods so the m2m isn't detected. (I think)
    either way this fixes some bugs.
    :param sender:
    :param kwargs:
    :return:
    """
    invalidate_obj(sender)
Example #28
0
def save_dark_mode_settings(request, user):
    dark_mode_form = DarkModeForm(user, data=request.POST, initial={"dark_mode_enabled": user.dark_mode_properties.dark_mode_enabled})
    if dark_mode_form.is_valid():
        if dark_mode_form.has_changed():
            user.dark_mode_properties.dark_mode_enabled = dark_mode_form.cleaned_data["dark_mode_enabled"]
            user.dark_mode_properties.save()
            invalidate_obj(request.user.dark_mode_properties)
            messages.success(request, ("Dark mode enabled" if user.dark_mode_properties.dark_mode_enabled else "Dark mode disabled"))

    return dark_mode_form
Example #29
0
 def handle_obj(self, app_name, model_name, obj_pk):
     model = get_model(app_name, model_name)
     if model is None:
         raise CommandError('Unknown model: %s.%s' % (app_name, model_name))
     try:
         obj = model.objects.get(pk=obj_pk)
     except model.DoesNotExist:
         raise CommandError('No %s.%s with pk = %s' %
                            (app_name, model_name, obj_pk))
     invalidate_obj(obj)
Example #30
0
def open_passes_view(request):
    passes = EighthSignup.objects.filter(after_deadline=True,
                                         pass_accepted=False)
    if request.method == "POST":
        pass_ids = list(request.POST.keys())

        csrf = "csrfmiddlewaretoken"
        if csrf in pass_ids:
            pass_ids.remove(csrf)

        accepted = 0
        rejected = 0
        for signup_id in pass_ids:
            signup = EighthSignup.objects.get(id=signup_id)
            status = request.POST.get(signup_id)
            if status == "accept":
                signup.accept_pass()
                accepted += 1
            elif status == "reject":
                signup.reject_pass()
                rejected += 1
            invalidate_obj(signup)

        messages.success(
            request,
            "Accepted {} and rejected {} passes.".format(accepted, rejected))

    if request.resolver_match.url_name == "eighth_admin_view_open_passes_csv":
        response = http.HttpResponse(content_type="text/csv")
        filename = '"open_passes.csv"'
        response["Content-Disposition"] = "attachment; filename=" + filename

        writer = csv.writer(response)
        writer.writerow([
            "Block", "Activity", "Student", "Grade", "Absences",
            "Time (Last Modified)", "Time (Created)"
        ])

        for p in passes:
            row = []
            row.append(p.scheduled_activity.block)
            row.append(p.scheduled_activity.activity)
            row.append("{}, {} {}".format(
                p.user.last_name, p.user.first_name,
                p.user.nickname if p.user.nickname else ""))
            row.append(int(p.user.grade))
            row.append(p.user.absence_count())
            row.append(p.last_modified_time)
            row.append(p.created_time)
            writer.writerow(row)

        return response

    context = {"admin_page_title": "Open Passes", "passes": passes}
    return render(request, "eighth/admin/open_passes.html", context)
Example #31
0
def feature_announcements(request):
    """Adds a list of feature announcements that should be displayed on the current page to the context."""
    feat_announcements = FeatureAnnouncement.objects.filter_for_request(
        request)

    if request.user.is_authenticated:
        for feat_announcement in feat_announcements:
            feat_announcement.users_seen.add(request.user)
            invalidate_obj(request.user)

    return {"feature_announcements": feat_announcements}
Example #32
0
def rebuild_paths(obj):
    """
    Rebuild all CablePaths which traverse the specified node
    """
    cable_paths = CablePath.objects.filter(path__contains=obj)

    with transaction.atomic():
        for cp in cable_paths:
            invalidate_obj(cp.origin)
            cp.delete()
            create_cablepath(cp.origin)
Example #33
0
def rebuild_paths(obj):
    """
    Rebuild all CablePaths which traverse the specified node
    """
    cable_paths = CablePath.objects.filter(path__contains=obj)

    with transaction.atomic():
        for cp in cable_paths:
            invalidate_obj(cp.origin)
            cp.delete()
            # Prevent looping back to rebuild_paths during the atomic transaction.
            create_cablepath(cp.origin, rebuild=False)
Example #34
0
def dismiss_feat_announcement_view(request, feat_announcement_id):
    """Dismiss the specified FeatureAnnouncement for the current user."""
    try:
        feat_announcement = FeatureAnnouncement.objects.get(
            id=feat_announcement_id)
    except FeatureAnnouncement.DoesNotExist:
        return http.HttpResponse("Already dismissed")

    feat_announcement.users_dismissed.add(request.user)
    invalidate_obj(feat_announcement)
    invalidate_obj(request.user)
    return http.HttpResponse("Dismissed")
Example #35
0
 def update(self, **kwargs):
     """
     django-cacheops 는 update 쿼리를 invalidate 해주지 않기 때문에
     이렇게 커스텀 하거나 invalidated_update() 를 써줘야 한다
     """
     row = super().update(**kwargs)
     try:
         invalidate_obj(self.get())
     except self.model.DoesNotExist:
         capture_exception(
             Exception(f'{self.model} : invalidate update fail'))
     return row
Example #36
0
def clear_absence_view(request, signup_id):
    if request.method == "POST":
        try:
            signup = EighthSignup.objects.get(id=signup_id)
        except (EighthSignup.DoesNotExist, ValueError) as e:
            raise http.Http404 from e
        signup.was_absent = False
        signup.save()
        invalidate_obj(signup)
        if "next" in request.GET:
            return redirect(request.GET["next"])
        return redirect("eighth_admin_dashboard")
    else:
        return http.HttpResponseNotAllowed(["POST"], "HTTP 405: METHOD NOT ALLOWED")
Example #37
0
def ActualizacionLogica(self, *args, **kwargs):
	if self.pk is None:
		super(type(self), self).save(*args, **kwargs)
		invalidate_obj(self)
		return
	if self.is_active is None:
		original = type(self).objects.alls().get(pk=self.pk)
		original.pk = None
		original.origin = self.pk
		original.is_active = timezone.now()
		super(type(original), original).save((), {})

	super(type(self), self).save(*args, **kwargs)
	invalidate_obj(self)
Example #38
0
def clear_absence_view(request, signup_id):
    if request.method == "POST":
        try:
            signup = EighthSignup.objects.get(id=signup_id)
        except (EighthSignup.DoesNotExist, ValueError):
            raise http.Http404
        signup.was_absent = False
        signup.save()
        invalidate_obj(signup)
        if "next" in request.GET:
            return redirect(request.GET["next"])
        return redirect("eighth_admin_dashboard")
    else:
        return http.HttpResponseNotAllowed(["POST"], "HTTP 405: METHOD NOT ALLOWED")
Example #39
0
def rebuild_paths_circuits(obj):
    """
    Rebuild all CablePaths which traverse, begin or end with the specified node.
    """
    termination_type = ContentType.objects.get_for_model(CircuitTermination)

    cable_paths = CablePath.objects.filter(
        Q(path__contains=obj)
        | Q(destination_type=termination_type, destination_id=obj.pk)
        | Q(origin_type=termination_type, origin_id=obj.pk))

    with transaction.atomic():
        for cp in cable_paths:
            invalidate_obj(cp.origin)
            cp.delete()
            # Prevent looping back to rebuild_paths during the atomic transaction.
            create_cablepath(cp.origin, rebuild=False)
Example #40
0
def add_activity_view(request):
    if request.method == "POST":
        form = QuickActivityForm(request.POST)
        if form.is_valid():
            new_id = request.POST.get("id", "default")
            if new_id == "default":
                activity = form.save()
            else:
                activity = (EighthActivity.objects.create(name=form.cleaned_data["name"], id=int(new_id)))
            invalidate_obj(activity)
            messages.success(request, "Successfully added activity.")
            return redirect("eighth_admin_edit_activity", activity_id=activity.id)
        else:
            messages.error(request, "Error adding activity.")
            request.session["add_activity_form"] = pickle.dumps(form)
            return redirect("eighth_admin_dashboard")
    else:
        context = {"admin_page_title": "Add Activity", "form": QuickActivityForm(), "available_ids": EighthActivity.available_ids()}
        return render(request, "eighth/admin/add_activity.html", context)
Example #41
0
def increment_view_counts(self, pks, retry=False):
    """
    :param self:
    :param pks:
    :return:
    """
    with redis.lock("tasks:increment_view_counts", timeout=LOCK_TIMEOUT):

        # update DB directly
        with connection.cursor() as cursor:
            id_as_str = ",".join(str(id) for id in pks)
            query = f"UPDATE dashboard_activity SET view_count = view_count + 1 WHERE id in ({id_as_str});"
            cursor.execute(query)
            cursor.close()

        # invalidate cache
        activities = Activity.objects.filter(pk__in=pks)
        for obj in activities:
            invalidate_obj(obj)
Example #42
0
def clear_comments_view(request):
    context = {"admin_page_title": "Clear Admin Comments", "completed": False}
    if request.method == "POST" and request.POST.get("confirm"):
        deleted_comments = ""
        count = 0

        c = LDAPConnection()
        comments = c.search(settings.USER_DN, "objectClass=tjhsstStudent", ["eighthoffice-comments"])
        for row in comments:
            if "eighthoffice-comments" in row:
                c.del_attribute(row["dn"], "eighthoffice-comments")
                u = User.objects.get(dn=row["dn"])
                invalidate_obj(u)
                u.clear_cache()
                deleted_comments += "=== {} ({})\n{}\n".format(u.full_name, u.username, row["eighthoffice-comments"])
                count += 1

        context["deleted_comments"] = deleted_comments or "No comments were deleted."
        context["deleted_comments_count"] = count
        context["completed"] = True
    return render(request, "eighth/admin/clear_comments.html", context)
Example #43
0
def increment_view_counts(self, pks, retry=False):
    """
    :param self:
    :param pks:
    :return:
    """
    if settings.FLUSH_QUEUE:
        return

    if len(pks) == 0:
        return
    # update DB directly
    with connection.cursor() as cursor:
        id_as_str = ",".join(str(id) for id in pks)
        query = f"UPDATE dashboard_activity SET view_count = view_count + 1 WHERE id in ({id_as_str});"
        cursor.execute(query)
        cursor.close()

    # invalidate cache
    activities = Activity.objects.filter(pk__in=pks)
    for obj in activities:
        invalidate_obj(obj)
Example #44
0
def clear_comments_view(request):
    context = {"admin_page_title": "Clear Admin Comments", "completed": False}
    if request.method == "POST" and request.POST.get("confirm"):
        deleted_comments = ""
        count = 0

        c = LDAPConnection()
        comments = c.search(settings.USER_DN, "objectClass=tjhsstStudent",
                            ["eighthoffice-comments"])
        for row in comments:
            if "eighthoffice-comments" in row:
                c.del_attribute(row["dn"], "eighthoffice-comments")
                u = User.objects.get(dn=row["dn"])
                invalidate_obj(u)
                u.clear_cache()
                deleted_comments += "=== {} ({})\n{}\n".format(
                    u.full_name, u.username, row["eighthoffice-comments"])
                count += 1

        context[
            "deleted_comments"] = deleted_comments or "No comments were deleted."
        context["deleted_comments_count"] = count
        context["completed"] = True
    return render(request, "eighth/admin/clear_comments.html", context)
Example #45
0
def transfer_students_action(request):
    """Do the actual process of transferring students."""
    if "source_act" in request.GET:
        source_act = EighthScheduledActivity.objects.get(
            id=request.GET.get("source_act"))
    elif "source_act" in request.POST:
        source_act = EighthScheduledActivity.objects.get(
            id=request.POST.get("source_act"))
    else:
        raise Http404

    dest_act = None
    dest_unsignup = False

    if "dest_act" in request.GET:
        dest_act = EighthScheduledActivity.objects.get(
            id=request.GET.get("dest_act"))
    elif "dest_act" in request.POST:
        dest_act = EighthScheduledActivity.objects.get(
            id=request.POST.get("dest_act"))
    elif "dest_unsignup" in request.POST or "dest_unsignup" in request.GET:
        dest_unsignup = True
    else:
        raise Http404

    num = source_act.members.count()

    context = {
        "admin_page_title": "Transfer Students",
        "source_act": source_act,
        "dest_act": dest_act,
        "dest_unsignup": dest_unsignup,
        "num": num
    }

    if request.method == "POST":
        if dest_unsignup and not dest_act:
            source_act.eighthsignup_set.all().delete()
            invalidate_obj(source_act)
            messages.success(
                request,
                "Successfully removed signups for {} students.".format(num))
        else:
            source_act.eighthsignup_set.update(scheduled_activity=dest_act)

            invalidate_obj(source_act)
            invalidate_obj(dest_act)
            messages.success(
                request, "Successfully transfered {} students.".format(num))
        return redirect("eighth_admin_dashboard")
    else:
        return render(request, "eighth/admin/transfer_students.html", context)
Example #46
0
def transfer_students_action(request):
    """Do the actual process of transferring students."""
    if "source_act" in request.GET:
        source_act = EighthScheduledActivity.objects.get(id=request.GET.get("source_act"))
    elif "source_act" in request.POST:
        source_act = EighthScheduledActivity.objects.get(id=request.POST.get("source_act"))
    else:
        raise Http404

    dest_act = None
    dest_unsignup = False

    if "dest_act" in request.GET:
        dest_act = EighthScheduledActivity.objects.get(id=request.GET.get("dest_act"))
    elif "dest_act" in request.POST:
        dest_act = EighthScheduledActivity.objects.get(id=request.POST.get("dest_act"))
    elif "dest_unsignup" in request.POST or "dest_unsignup" in request.GET:
        dest_unsignup = True
    else:
        raise Http404

    num = source_act.members.count()

    context = {
        "admin_page_title": "Transfer Students",
        "source_act": source_act,
        "dest_act": dest_act,
        "dest_unsignup": dest_unsignup,
        "num": num
    }

    if request.method == "POST":
        if dest_unsignup and not dest_act:
            source_act.eighthsignup_set.all().delete()
            invalidate_obj(source_act)
            messages.success(request, "Successfully removed signups for {} students.".format(num))
        else:
            source_act.eighthsignup_set.update(
                scheduled_activity=dest_act
            )

            invalidate_obj(source_act)
            invalidate_obj(dest_act)
            messages.success(request, "Successfully transfered {} students.".format(num))
        return redirect("eighth_admin_dashboard")
    else:
        return render(request, "eighth/admin/transfer_students.html", context)
Example #47
0
def repair_durations(limit_range, dump_to, load_from, tolerance, log_file):
    """
    Repair/reprocess master durations.
    """
    from base.audio.fileinfo import FileInfoProcessor

    items_to_reprocess = []
    affected_playlists = []
    affected_playlist_ids = []

    # invalidate cache for Media
    invalidate_model(Media)

    if load_from:

        if limit_range:
            raise NotImplementedError('--limit-range option not allowed in combination with --load-from')

        # using `set` to remove duplicate ids
        item_ids = set([
            int(l.strip().split(',')[0]) for l in load_from.readlines() if float(l.strip().split(',')[1]) > tolerance
        ])


        click.echo('loaded {} ids from dump file'.format(len(item_ids)))

        items_to_reprocess = Media.objects.filter(pk__in=item_ids)

    else:

        # mysql does not support remote/streaming cursors
        # to save memory items are loaded from db individually
        values = Media.objects.order_by('pk').values('id').nocache()

        if limit_range:
            _limits = limit_range.split(':')
            values = values[_limits[0]:_limits[1]]

        item_ids = [i['id'] for i in values]

        with click.progressbar(item_ids, show_pos=True, width=48, label='Reprocessing {} tracks'.format(len(item_ids))) as bar:

            for item_pk in bar:

                close_old_connections()

                item = Media.objects.get(pk=item_pk)

                if item.master and item.master.path:

                    p = FileInfoProcessor(item.master.path)

                    current_duration = item.master_duration
                    new_duration = p.duration

                    try:
                        diff = abs(current_duration - new_duration)
                    except TypeError:
                        diff = 100.0

                    if diff > tolerance:
                        items_to_reprocess.append(item)

                    # add to csv log
                    if diff > tolerance and dump_to:
                        dump_to.write('{pk},{diff}\n'.format(pk=item.pk, diff=diff))
                        dump_to.flush()


    click.echo('{} tracks have differences in duration'.format(len(items_to_reprocess)))


    if click.confirm('Do you want to update/repair the durations on {} tracks?'.format(len(items_to_reprocess))):

        base_url = 'http://{}'.format(Site.objects.get_current().domain)


        tpl = u'''id: {id} - "{name}"
{url}
old: {current_duration} new: {new_duration} diff: {diff}
        '''


        tpl_log = u'{ct},{pk},{type},{current_duration},{new_duration},{diff},{url}\n'

        # write column header
        if log_file:
            log_file.write(tpl_log.format(
                ct='content-type',
                pk='id',
                url='url',
                type='type',
                #
                current_duration='old_duration',
                new_duration='new_duration',
                diff='diff',
            ))


        # loop affected media, fix durations, get playlist appearances & print/log info
        for item in items_to_reprocess:

            p = FileInfoProcessor(item.master.path)

            current_duration = item.master_duration
            new_duration = p.duration

            try:
                diff = current_duration - new_duration
            except TypeError:
                diff = '-'


            click.echo(tpl.format(
                id=item.id,
                name=item.name,
                url=base_url + item.get_absolute_url(),
                #
                current_duration=current_duration,
                new_duration=new_duration,
                diff=diff
            ))

            if log_file:
                log_file.write(tpl_log.format(
                    ct='media',
                    pk=item.pk,
                    url=base_url + item.get_absolute_url(),
                    type=item.get_mediatype_display(),
                    #
                    current_duration=current_duration,
                    new_duration=new_duration,
                    diff=diff
                ))
                log_file.flush()

            for p in item.get_appearances():
                if not p.pk in affected_playlist_ids:
                    affected_playlist_ids.append(p.pk)
                    # we need to store the 'current' value of the duration
                    affected_playlists.append({
                        'obj': p,
                        'current_duration': p.get_duration()
                    })

            # update media duration
            Media.objects.filter(pk=item.pk).update(master_duration=new_duration)
            invalidate_obj(item)


        # loop playlists & print/log info
        for item in affected_playlists:

            invalidate_obj(item['obj'])

            current_duration = float(item['current_duration']) / 1000
            new_duration = float(item['obj'].get_duration()) / 1000

            try:
                diff = current_duration - new_duration
            except TypeError:
                diff = '-'

            click.echo(tpl.format(
                id=item['obj'].id,
                name=item['obj'].name,
                url=base_url + item['obj'].get_absolute_url(),
                #
                current_duration=current_duration,
                new_duration=new_duration,
                diff=diff
            ))

            if log_file:
                log_file.write(tpl_log.format(
                    ct='playlist',
                    pk=item['obj'].pk,
                    url=base_url + item['obj'].get_absolute_url(),
                    type=item['obj'].get_type_display(),
                    #
                    current_duration=current_duration,
                    new_duration=new_duration,
                    diff=diff
                ))
                log_file.flush()

            # update playlist duration
            Playlist.objects.filter(pk=item['obj'].pk).update(duration=new_duration * 1000)
            invalidate_obj(item)
Example #48
0
def schedule_activity_view(request):

    if request.method == "POST":
        formset = ScheduledActivityFormset(request.POST)

        if formset.is_valid():
            for form in formset:
                block = form.cleaned_data["block"]
                activity = form.cleaned_data["activity"]

                # Save changes to cancelled activities and scheduled activities
                cancelled = (EighthScheduledActivity.objects.filter(block=block, activity=activity, cancelled=True).exists())

                instance = None
                if form["scheduled"].value() or cancelled:
                    instance, created = (EighthScheduledActivity.objects.get_or_create(block=block, activity=activity))
                    invalidate_obj(instance)
                    invalidate_obj(block)
                    invalidate_obj(activity)
                else:
                    schact = EighthScheduledActivity.objects.filter(block=block, activity=activity)
                    logger.debug(block)
                    logger.debug(activity)
                    logger.debug(schact)

                    # Instead of deleting and messing up attendance,
                    # cancel the scheduled activity if it is unscheduled.
                    # If the scheduled activity needs to be completely deleted,
                    # the "Unschedule" box can be checked after it has been cancelled.

                    # If a both blocks activity, unschedule the other
                    # scheduled activities of it on the same day.
                    if schact:
                        if activity.both_blocks:
                            other_act = schact[0].get_both_blocks_sibling()
                            logger.debug("other_act: {}".format(other_act))
                            if other_act:
                                other_act.cancelled = True
                                other_act.save()
                                invalidate_obj(other_act)
                        else:
                            schact.update(cancelled=True)
                            for s in schact:
                                invalidate_obj(s)
                        instance = schact[0]

                        cancelled = True

                if instance:
                    fields = ["rooms", "capacity", "sponsors", "title", "special", "administrative", "restricted", "sticky", "comments", "admin_comments"]
                    if "rooms" in form.cleaned_data:
                        for o in form.cleaned_data["rooms"]:
                            invalidate_obj(o)

                    if "sponsors" in form.cleaned_data:
                        for o in form.cleaned_data["sponsors"]:
                            invalidate_obj(o)

                    for field_name in fields:
                        obj = form.cleaned_data[field_name]
                        logger.debug("{} {}".format(field_name, obj))
                        setattr(instance, field_name, obj)

                        if field_name in ["rooms", "sponsors"]:
                            for o in obj:
                                invalidate_obj(o)

                if form["scheduled"].value() or cancelled:
                    # Uncancel if this activity/block pairing was already
                    # created and cancelled
                    if not form["scheduled"].value():
                        instance.cancelled = True
                    else:
                        instance.cancelled = False

                    # If an activity has already been cancelled and the
                    # unschedule checkbox has been checked, delete the
                    # EighthScheduledActivity instance. If there are students
                    # in the activity then error out.
                    if form["unschedule"].value() and instance.cancelled:
                        name = "{}".format(instance)
                        count = instance.eighthsignup_set.count()
                        logger.debug("Unschedule {} - signups {}".format(name, count))
                        bb_ok = True
                        sibling = False
                        if activity.both_blocks:
                            sibling = instance.get_both_blocks_sibling()
                            if sibling:
                                if not sibling.eighthsignup_set.count() == 0:
                                    bb_ok = False

                        if count == 0 and bb_ok:
                            instance.delete()
                            if sibling:
                                sibling.delete()
                            messages.success(request, "Unscheduled {}".format(name))

                            continue  # don't run instance.save()
                        elif count == 1:
                            messages.error(request, "Did not unschedule {} because there is {} student signed up.".format(name, count))
                        else:
                            messages.error(request, "Did not unschedule {} because there are {} students signed up.".format(name, count))
                    instance.save()
                    logger.debug(instance)

            messages.success(request, "Successfully updated schedule.")

            # Force reload everything from the database to reset
            # forms that weren't saved
            return redirect(request.get_full_path())
        else:
            messages.error(request, "Error updating schedule.")

    activities = EighthActivity.undeleted_objects.order_by("name")
    activity_id = request.GET.get("activity", None)
    activity = None

    if activity_id is not None and len(activity_id) > 0:
        try:
            activity = EighthActivity.undeleted_objects.get(id=activity_id)
        except (EighthActivity.DoesNotExist, ValueError):
            pass

    all_sponsors = {s["id"]: s for s in EighthSponsor.objects.values()}
    all_rooms = {r["id"]: r for r in EighthRoom.objects.values()}

    for sid, sponsor in all_sponsors.items():
        if sponsor["show_full_name"]:
            all_sponsors[sid]["full_name"] = sponsor["last_name"] + ", " + sponsor["first_name"]
        else:
            all_sponsors[sid]["full_name"] = sponsor["last_name"]

    for rid, room in all_rooms.items():
        all_rooms[rid]["description"] = room["name"] + " (" + str(room["capacity"]) + ")"

    all_signups = {}
    all_default_capacities = {}

    context = {
        "activities": activities,
        "activity": activity,
        "sponsors": all_sponsors,
        "all_signups": all_signups,
        "rooms": all_rooms,
        "sponsors_json": safe_json(all_sponsors),
        "rooms_json": safe_json(all_rooms)
    }

    if activity is not None:
        start_date = get_start_date(request)
        # end_date = start_date + timedelta(days=60)

        blocks = EighthBlock.objects.filter(date__gte=start_date)
        # , date__lte=end_date)
        initial_formset_data = []

        sched_act_queryset = (EighthScheduledActivity.objects.filter(activity=activity).select_related("block").prefetch_related("rooms", "sponsors",
                                                                                                                                 "members"))
        all_sched_acts = {sa.block.id: sa for sa in sched_act_queryset}

        for block in blocks:
            initial_form_data = {"block": block, "activity": activity}
            try:
                sched_act = all_sched_acts[block.id]

                all_signups[block.id] = sched_act.members.count()
                all_default_capacities[block.id] = sched_act.get_true_capacity()
                logger.debug(sched_act)
                initial_form_data.update({
                    "rooms": sched_act.rooms.all(),
                    "capacity": sched_act.capacity,
                    "sponsors": sched_act.sponsors.all(),
                    "title": sched_act.title,
                    "special": sched_act.special,
                    "administrative": sched_act.administrative,
                    "restricted": sched_act.restricted,
                    "sticky": sched_act.sticky,
                    "comments": sched_act.comments,
                    "admin_comments": sched_act.admin_comments,
                    "scheduled": not sched_act.cancelled,
                    "cancelled": sched_act.cancelled
                })
            except KeyError:
                all_signups[block.id] = 0
                all_default_capacities[block.id] = activity.capacity()
                pass
            initial_formset_data.append(initial_form_data)

        if request.method != "POST":
            # There must be an error in the form if this is reached
            formset = ScheduledActivityFormset(initial=initial_formset_data)
        context["formset"] = formset
        context["rows"] = list(zip(blocks, formset))

        context["default_rooms"] = activity.rooms.all()
        context["default_sponsors"] = activity.sponsors.all()
        context["default_capacities"] = all_default_capacities

    context["admin_page_title"] = "Schedule an Activity"
    return render(request, "eighth/admin/schedule_activity.html", context)
Example #49
0
 def save(self, *args, **kwargs):
     invalidate_obj(self.question)
     invalidate_obj(QuestionSet.get(pk=self.question.qset.pk))
     if self.next_question:
         invalidate_obj(self.next_question)
     return super(QuestionFlow, self).save(*args, **kwargs)
Example #50
0
 def save(self, *args, **kwargs):
     invalidate_obj(self.loop_starter)
     invalidate_obj(self.loop_ender)
     return super(QuestionLoop, self).save(*args, **kwargs)
Example #51
0
File: groups.py Project: tjcsl/ion
def edit_group_view(request, group_id):
    try:
        group = Group.objects.get(id=group_id)
    except Group.DoesNotExist:
        raise http.Http404

    if request.method == "POST":
        invalidate_model(Group)
        if group.name.lower().startswith("all students"):
            cache.delete("users:students")
        if "remove_all" in request.POST:
            users = group.user_set.all()
            num = users.count()
            for u in users:
                group.user_set.remove(u)
            group.save()
            invalidate_obj(group)
            messages.success(request, "Successfully deleted {} members of the group.".format(num))
            return redirect("eighth_admin_edit_group", group.id)
        form = GroupForm(request.POST, instance=group)
        if form.is_valid():
            if 'student_visible' in form.cleaned_data:
                props = group.properties
                props.student_visible = form.cleaned_data['student_visible']
                props.save()
                invalidate_obj(props)

            form.save()
            messages.success(request, "Successfully edited group.")
            return redirect("eighth_admin_dashboard")
        else:
            messages.error(request, "Error modifying group.")
    else:
        form = GroupForm(instance=group, initial={"student_visible": group.properties.student_visible})

    student_query = None
    if request.method == "GET":
        student_query = request.GET.get("q", None)

    if not student_query:
        users = group.user_set.all()  # Order not strictly alphabetical
    else:
        ion_ids = [sid.strip() for sid in student_query.split(",")]
        users = group.user_set.filter(username__in=ion_ids)
    users = users.order_by('username', 'first_name', 'last_name', 'student_id')
    p = Paginator(users, 100)  # Paginating to limit LDAP queries (slow)

    page_num = request.GET.get('p', 1)
    try:
        page = p.page(page_num)
    except PageNotAnInteger:
        page = p.page(1)
    except EmptyPage:
        page = p.page(p.num_pages)
    members = []
    for user in page:
        grade = user.grade
        emails = user.emails
        members.append({
            "id": user.id,
            "first_name": user.first_name,
            "last_name": user.last_name,
            "student_id": user.student_id,
            "email": user.tj_email if user.tj_email else emails.first() if emails.count() > 0 else "",
            "grade": grade.number if user.grade and not user.grade.number == 13 else "Staff"
        })
    members = sorted(members, key=lambda m: (m["last_name"], m["first_name"]))
    linked_activities = EighthActivity.objects.filter(groups_allowed=group)

    def parse_int(value):
        return int(value) if value.isdigit() else None

    context = {
        "group": group,
        "members": members,
        "member_count": users.count(),
        "members_page": page,
        "edit_form": form,
        "added_ids": [parse_int(x) for x in request.GET.getlist("added")],
        "linked_activities": linked_activities,
        "admin_page_title": "Edit Group",
        "delete_url": reverse("eighth_admin_delete_group", args=[group_id])
    }

    if "possible_student" in request.GET:
        student_ids = request.GET.getlist("possible_student")
        possible_students = User.objects.get(id__in=student_ids)
        context["possible_students"] = possible_students

    return render(request, "eighth/admin/edit_group.html", context)
Example #52
0
def upload_group_members_view(request, group_id):
    try:
        group = Group.objects.get(id=group_id)
    except Group.DoesNotExist:
        raise http.Http404
    stage = "upload"
    data = {}
    filetext = False
    if request.method == "POST":
        form = UploadGroupForm(request)
        logger.debug(request.FILES)
        if "file" in request.FILES:
            fileobj = request.FILES['file']
            filetext = get_file_string(fileobj)
        elif "filetext" in request.POST:
            filetext = request.POST.get("filetext")
        elif "user_id" in request.POST:
            userids = request.POST.getlist("user_id")
            num_added = 0
            for uid in userids:
                user = User.objects.get(id=uid)
                if user is None:
                    messages.error(request, "User with ID {} does not exist".format(uid))
                else:
                    user.groups.add(group)
                    user.save()
                    num_added += 1
            invalidate_obj(group)
            messages.success(request, "{} added to group {}".format(num_added, group))
            return redirect("eighth_admin_edit_group", group.id)
        elif "import_group" in request.POST:
            try:
                import_group = Group.objects.get(id=request.POST["import_group"])
            except Group.DoesNotExist:
                raise http.Http404
            num_users = import_group.user_set.count()
            if "import_confirm" in request.POST:
                for member in import_group.user_set.all():
                    member.groups.add(group)
                    member.save()
                invalidate_obj(group)
                messages.success(request, "Added {} users from {} to {}".format(num_users, import_group, group))
                return redirect("eighth_admin_edit_group", group.id)
            return render(request, "eighth/admin/upload_group.html", {
                "admin_page_title": "Import Group Members: {}".format(group),
                "stage": "import_confirm",
                "group": group,
                "import_group": import_group,
                "num_users": num_users
            })

    else:
        form = UploadGroupForm()
    all_groups = Group.objects.order_by("name")
    context = {
        "admin_page_title": "Upload/Import Group Members: {}".format(group),
        "form": form,
        "stage": stage,
        "data": data,
        "group": group,
        "all_groups": all_groups
    }

    if filetext:
        context["stage"] = "parse"
        data = handle_group_input(filetext)
        context["sure_users"], context["unsure_users"] = data

    return render(request, "eighth/admin/upload_group.html", context)
Example #53
0
def edit_group_view(request, group_id):
    try:
        group = Group.objects.get(id=group_id)
    except Group.DoesNotExist:
        raise http.Http404

    if request.method == "POST":
        invalidate_model(Group)
        if group.name.lower().startswith("all students"):
            cache.delete("users:students")
        if "remove_all" in request.POST:
            users = group.user_set.all()
            num = users.count()
            for u in users:
                group.user_set.remove(u)
            group.save()
            invalidate_obj(group)
            messages.success(request, "Successfully deleted {} members of the group.".format(num))
            return redirect("eighth_admin_edit_group", group.id)
        form = GroupForm(request.POST, instance=group)
        if form.is_valid():
            if 'student_visible' in form.cleaned_data:
                props = group.properties
                props.student_visible = form.cleaned_data['student_visible']
                props.save()
                invalidate_obj(props)

            form.save()
            messages.success(request, "Successfully edited group.")
            return redirect("eighth_admin_dashboard")
        else:
            messages.error(request, "Error modifying group.")
    else:
        form = GroupForm(instance=group, initial={"student_visible": group.properties.student_visible})

    users = group.user_set.all()
    members = []
    for user in users:
        grade = user.grade
        emails = user.emails
        members.append({
            "id": user.id,
            "first_name": user.first_name,
            "last_name": user.last_name,
            "student_id": user.student_id,
            "email": user.tj_email if user.tj_email else emails[0] if emails else "",
            "grade": grade.number if user.grade else "Staff"
        })
    members = sorted(members, key=lambda m: (m["last_name"], m["first_name"]))
    linked_activities = EighthActivity.objects.filter(groups_allowed=group)
    context = {
        "group": group,
        "members": members,
        "edit_form": form,
        "added_ids": request.GET.getlist("added"),
        "linked_activities": linked_activities,
        "admin_page_title": "Edit Group",
        "delete_url": reverse("eighth_admin_delete_group",
                              args=[group_id])
    }

    if "possible_student" in request.GET:
        student_ids = request.GET.getlist("possible_student")
        possible_students = User.objects.get(id__in=student_ids)
        context["possible_students"] = possible_students

    return render(request, "eighth/admin/edit_group.html", context)
Example #54
0
def invalidate_count():
    invalidate_obj(c)
Example #55
0
def do_invalidate_obj(obj):
    invalidate_obj(obj)
Example #56
0
def take_attendance_view(request, scheduled_activity_id):
    try:
        scheduled_activity = EighthScheduledActivity.objects.select_related("activity", "block").get(
            activity__deleted=False, id=scheduled_activity_id
        )
    except EighthScheduledActivity.DoesNotExist:
        raise http.Http404

    if request.user.is_eighth_admin or scheduled_activity.user_is_sponsor(request.user):
        logger.debug("User has permission to edit")
        edit_perm = True
    else:
        logger.debug("User does not have permission to edit")
        edit_perm = False

    edit_perm_cancelled = False

    if scheduled_activity.cancelled and not request.user.is_eighth_admin:
        logger.debug("Non-admin user does not have permission to edit cancelled activity")
        edit_perm = False
        edit_perm_cancelled = True

    if request.method == "POST":

        if not edit_perm:
            if edit_perm_cancelled:
                return render(
                    request,
                    "error/403.html",
                    {
                        "reason": "You do not have permission to take attendance for this activity. The activity was cancelled."
                    },
                    status=403,
                )
            else:
                return render(
                    request,
                    "error/403.html",
                    {
                        "reason": "You do not have permission to take attendance for this activity. You are not a sponsor."
                    },
                    status=403,
                )

        if "admin" in request.path:
            url_name = "eighth_admin_take_attendance"
        else:
            url_name = "eighth_take_attendance"

        if "clear_attendance_bit" in request.POST:
            scheduled_activity.attendance_taken = False
            scheduled_activity.save()
            invalidate_obj(scheduled_activity)

            messages.success(request, "Attendance bit cleared for {}".format(scheduled_activity))

            redirect_url = reverse(url_name, args=[scheduled_activity.id])

            if "no_attendance" in request.GET:
                redirect_url += "?no_attendance={}".format(request.GET["no_attendance"])

            return redirect(redirect_url)

        if not scheduled_activity.block.locked and not request.user.is_eighth_admin:
            return render(
                request,
                "error/403.html",
                {
                    "reason": "You do not have permission to take attendance for this activity. The block has not been locked yet."
                },
                status=403,
            )

        if not scheduled_activity.block.locked and request.user.is_eighth_admin:
            messages.success(request, "Note: Taking attendance on an unlocked block.")

        present_user_ids = list(request.POST.keys())

        csrf = "csrfmiddlewaretoken"
        if csrf in present_user_ids:
            present_user_ids.remove(csrf)

        absent_signups = (
            EighthSignup.objects.filter(scheduled_activity=scheduled_activity).exclude(user__in=present_user_ids)
        ).nocache()
        absent_signups.update(was_absent=True)

        for s in absent_signups:
            invalidate_obj(s)

        present_signups = (
            EighthSignup.objects.filter(scheduled_activity=scheduled_activity, user__in=present_user_ids)
        ).nocache()
        present_signups.update(was_absent=False)

        for s in present_signups:
            invalidate_obj(s)

        passes = (
            EighthSignup.objects.filter(scheduled_activity=scheduled_activity, after_deadline=True, pass_accepted=False)
        ).nocache()
        passes.update(was_absent=True)

        for s in passes:
            invalidate_obj(s)

        scheduled_activity.attendance_taken = True
        scheduled_activity.save()
        invalidate_obj(scheduled_activity)

        messages.success(request, "Attendance updated.")

        redirect_url = reverse(url_name, args=[scheduled_activity.id])

        if "no_attendance" in request.GET:
            redirect_url += "?no_attendance={}".format(request.GET["no_attendance"])

        return redirect(redirect_url)
    else:
        passes = (
            EighthSignup.objects.select_related("user").filter(
                scheduled_activity=scheduled_activity, after_deadline=True, pass_accepted=False
            )
        ).nocache()

        users = scheduled_activity.members.exclude(eighthsignup__in=passes)
        members = []

        absent_user_ids = (
            EighthSignup.objects.select_related("user")
            .filter(scheduled_activity=scheduled_activity, was_absent=True)
            .values_list("user__id", flat=True)
        ).nocache()

        pass_users = (
            EighthSignup.objects.select_related("user")
            .filter(scheduled_activity=scheduled_activity, after_deadline=True, pass_accepted=True)
            .values_list("user__id", flat=True)
        ).nocache()

        for user in users:
            members.append(
                {
                    "id": user.id,
                    "name": user.last_first,  # includes nickname
                    "grade": user.grade.number if user.grade else None,
                    "present": (scheduled_activity.attendance_taken and (user.id not in absent_user_ids)),
                    "had_pass": user.id in pass_users,
                    "pass_present": (
                        not scheduled_activity.attendance_taken
                        and user.id in pass_users
                        and user.id not in absent_user_ids
                    ),
                    "email": user.tj_email,
                }
            )
            invalidate_obj(user)

        members.sort(key=lambda m: m["name"])

        context = {
            "scheduled_activity": scheduled_activity,
            "passes": passes,
            "members": members,
            "p": pass_users,
            "no_edit_perm": not edit_perm,
            "edit_perm_cancelled": edit_perm_cancelled,
            "show_checkboxes": (scheduled_activity.block.locked or request.user.is_eighth_admin),
            "show_icons": (
                scheduled_activity.block.locked
                and scheduled_activity.block.attendance_locked()
                and not request.user.is_eighth_admin
            ),
        }

        if request.user.is_eighth_admin:
            context["scheduled_activities"] = EighthScheduledActivity.objects.filter(
                block__id=scheduled_activity.block.id
            )
            logger.debug(context["scheduled_activities"])
            context["blocks"] = (
                EighthBlock.objects
                # .filter(date__gte=get_start_date(request))
                .order_by("date")
            )

        if request.resolver_match.url_name == "eighth_admin_export_attendance_csv":
            response = http.HttpResponse(content_type="text/csv")
            response["Content-Disposition"] = 'attachment; filename="attendance.csv"'

            writer = csv.writer(response)
            writer.writerow(
                [
                    "Block",
                    "Activity",
                    "Name",
                    "Student ID",
                    "Grade",
                    "Email",
                    "Locked",
                    "Rooms",
                    "Sponsors",
                    "Attendance Taken",
                    "Present",
                    "Had Pass",
                ]
            )
            for member in members:
                row = []
                logger.debug(member)
                row.append(str(scheduled_activity.block))
                row.append(str(scheduled_activity.activity))
                row.append(member["name"])
                row.append(member["id"])
                row.append(member["grade"])
                row.append(member["email"])
                row.append(scheduled_activity.block.locked)
                rooms = scheduled_activity.get_true_rooms()
                row.append(", ".join(["{} ({})".format(room.name, room.capacity) for room in rooms]))
                sponsors = scheduled_activity.get_true_sponsors()
                row.append(" ,".join([sponsor.name for sponsor in sponsors]))
                row.append(scheduled_activity.attendance_taken)
                row.append(member["present"] if scheduled_activity.block.locked else "N/A")

                row.append(member["had_pass"] if scheduled_activity.block.locked else "N/A")
                writer.writerow(row)

            return response
        else:
            return render(request, "eighth/take_attendance.html", context)
Example #57
0
 def get_calls(_=None, **kw):
     # Invalidate during first run
     if calls[0] < 1:
         invalidate_obj(c)
     calls[0] += 1
     return calls[0]
Example #58
0
 def invalidate(post):
     with no_invalidation:
         with no_invalidation:
             pass
         invalidate_obj(post)
Example #59
0
    def test_big_invalidation(self):
        for x in range(8000):
            list(Category.objects.cache().exclude(pk=x))

        c = Category.objects.get(pk=1)
        invalidate_obj(c) # lua unpack() fails with 8000 keys, workaround works
Example #60
0
 def test_invalidate_model_with_geometry(self):
     geom = Geometry()
     geom.save()
     # Raises ValueError if this doesn't work
     invalidate_obj(geom)