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)
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)
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)
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)
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])
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)
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)
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()))
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)
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)
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
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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
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)
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}
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)
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)
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")
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
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")
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)
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")
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
def save(self, *args, **kwargs): invalidate_obj(self.loop_starter) invalidate_obj(self.loop_ender) return super(QuestionLoop, self).save(*args, **kwargs)
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)
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)
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)
def invalidate_count(): invalidate_obj(c)
def do_invalidate_obj(obj): invalidate_obj(obj)
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)
def get_calls(_=None, **kw): # Invalidate during first run if calls[0] < 1: invalidate_obj(c) calls[0] += 1 return calls[0]
def invalidate(post): with no_invalidation: with no_invalidation: pass invalidate_obj(post)
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
def test_invalidate_model_with_geometry(self): geom = Geometry() geom.save() # Raises ValueError if this doesn't work invalidate_obj(geom)