def by_id(request, sample_id, path_suffix): """Pure re-direct view in case a sample is accessed by ID instead of by name. It redirects to the URL with the name. The query string, if given, is passed, too. :param request: the current HTTP Request object :param sample_id: the numeric ID of the sample :param path_suffix: the trailing path, e.g. ``"/split/"``; if you just view a sample, it is empty (or only the query string) :type request: HttpRequest :type sample_id: unicode :type path_suffix: unicode :return: the HTTP response object :rtype: HttpResponse """ sample = get_object_or_404(models.Sample, pk=utils.convert_id_to_int(sample_id)) if is_json_requested(request): # No redirect for the remote client. This also makes a POST request # possible. if path_suffix == "/edit/": return edit(request, sample.name) else: # FixMe: More path_suffixes should be tested return show(request, sample.name) # Necessary so that the sample's name isn't exposed through the URL permissions.get_sample_clearance(request.user, sample) query_string = request.META["QUERY_STRING"] or "" return HttpResponseSeeOther( django.core.urlresolvers.reverse("show_sample_by_name", kwargs={"sample_name": sample.name}) + path_suffix + ("?" + query_string if query_string else ""))
def process_response(self, request, response): """Return a HTTP 422 response if a JSON response was requested and an HTML page with form errors is returned. """ if is_json_requested(request) and response._headers["content-type"][1].startswith("text/html") and \ response.status_code == 200: user = request.user if not user.is_authenticated(): # Login view was returned return HttpResponseUnauthorised() hash_ = hashlib.sha1() hash_.update(six.text_type(random.random()).encode("ascii")) # For some very obscure reason, a random number was not enough -- # it led to collisions time after time. hash_.update(six.text_type(time.time()).encode("ascii")) hash_value = hash_.hexdigest() ErrorPage.objects.create(hash_value=hash_value, user=user, requested_url=request.get_full_path(), html=response.content) return HttpResponseUnprocessableEntity( json.dumps((1, request.build_absolute_uri( django.core.urlresolvers.reverse( "jb_common:show_error_page", kwargs={"hash_value": hash_value})))), content_type="application/json") return response
def process_request(self, request): if is_json_requested(request): # JSON responses are made for programs, so strings must be stable language = "en" else: language = self.get_language_for_user(request) translation.activate(language) request.LANGUAGE_CODE = translation.get_language()
def process_request(self, request): if is_json_requested(request): # JSON responses are made for programs, so strings must be stable language = "en" else: language = self.get_language_for_user(request) translation.activate(language) request.LANGUAGE_CODE = translation.get_language()
def edit(request, username): """View for doing various things with the samples listed under “My Samples”. For example, copying them to the “My Samples” list of another user, or simply removing them from the list. Note that there are two different user variables in this view and its associated functions. ``current_user`` is the same as ``request.user``. Thus, it is the currently logged-in user. However, ``user`` is the user whose “My Samples” are to be processed. Almost always both are the same, especially because you are not allowed to see or change the “My Samples” of another user. However, staff users *are* allowed to change them, so then both are different. :param request: the current HTTP Request object :param username: the login name of the user whose “My Samples” should be changed :type request: HttpRequest :type username: unicode :return: the HTTP response object :rtype: HttpResponse """ user = get_object_or_404(django.contrib.auth.models.User, username=username) if not request.user.is_superuser and request.user != user: raise permissions.PermissionError( request.user, _("You can't access the “My Samples” section of another user.")) if request.method == "POST": my_samples_form = MySamplesForm(user, request.POST) action_form = ActionForm(user, request.POST) referentially_valid = is_referentially_valid(request.user, my_samples_form, action_form) if my_samples_form.is_valid() and action_form.is_valid( ) and referentially_valid: save_to_database(user, my_samples_form, action_form) return utils.successful_response( request, _("Successfully processed “My Samples”.")) else: if is_json_requested(request): return respond_in_json( request.user.my_samples.values_list("id", flat=True)) my_samples_form = MySamplesForm(user) action_form = ActionForm(user) return render( request, "samples/edit_my_samples.html", { "title": _("Manage “My Samples” of {user_name}").format( user_name=get_really_full_name(user)), "my_samples": my_samples_form, "action": action_form })
def show(request, sample_name): """A view for showing existing samples. :param request: the current HTTP Request object :param sample_name: the name of the sample :type request: HttpRequest :type sample_name: unicode :return: the HTTP response object :rtype: HttpResponse """ start = time.time() if request.method == "POST": samples_and_processes = SamplesAndProcesses.samples_and_processes(sample_name, request.user, request.POST) if samples_and_processes.is_valid(): added, removed = samples_and_processes.save_to_database() if is_json_requested(request): return respond_in_json(True) if added: success_message = ungettext("Sample {samples} was added to My Samples.", "Samples {samples} were added to My Samples.", len(added)).format(samples=format_enumeration(added)) else: success_message = "" if removed: if added: success_message += " " success_message += ungettext("Sample {samples} was removed from My Samples.", "Samples {samples} were removed from My Samples.", len(removed)).format(samples=format_enumeration(removed)) elif not added: success_message = _("Nothing was changed.") messages.success(request, success_message) else: if is_json_requested(request): sample = utils.lookup_sample(sample_name, request.user) return respond_in_json(sample.get_data()) samples_and_processes = SamplesAndProcesses.samples_and_processes(sample_name, request.user) messages.debug(request, "DB-Zugriffszeit: {0:.1f} ms".format((time.time() - start) * 1000)) return render(request, "samples/show_sample.html", {"title": _("Sample “{sample}”").format(sample=samples_and_processes.sample_context["sample"]), "samples_and_processes": samples_and_processes})
def process_exception(self, request, exception): """Convert response to exceptions to JSONised version if the response is requested to be JSON. """ if isinstance(exception, django.http.Http404): if is_json_requested(request): return django.http.HttpResponseNotFound(json.dumps((2, exception.args[0])), content_type="application/json") elif isinstance(exception, JSONRequestException): return HttpResponseUnprocessableEntity(json.dumps((exception.error_number, exception.error_message)), content_type="application/json")
def process_exception(self, request, exception): """Convert response to exceptions to JSONised version if the response is requested to be JSON. """ if isinstance(exception, django.http.Http404): if is_json_requested(request): return django.http.HttpResponseNotFound( json.dumps((2, exception.args[0])), content_type="application/json") elif isinstance(exception, JSONRequestException): return HttpResponseUnprocessableEntity( json.dumps((exception.error_number, exception.error_message)), content_type="application/json")
def is_all_valid(self): """Tests the “inner” validity of all forms belonging to this view. This function calls the ``is_valid()`` method of all forms, even if one of them returns ``False`` (and makes the return value clear prematurely). :return: whether all forms are valid. :rtype: bool """ all_valid = not self._change_structure() if not is_json_requested(self.request) else True all_valid = super(DepositionView, self).is_all_valid() and all_valid return all_valid
def is_all_valid(self): """Tests the “inner” validity of all forms belonging to this view. This function calls the ``is_valid()`` method of all forms, even if one of them returns ``False`` (and makes the return value clear prematurely). :return: whether all forms are valid. :rtype: bool """ all_valid = not self._change_structure() if not is_json_requested( self.request) else True all_valid = super(DepositionView, self).is_all_valid() and all_valid return all_valid
def split_and_rename_after_deposition(request, deposition_number): """View for renaming and/or splitting samples immediately after they have been deposited in the same run. Optionally, you can give query string parameters of the form ``new-name-21=super`` where 21 is the sample ID and “super” is the suggested new name of this sample. :param request: the current HTTP Request object :param deposition_number: the number of the deposition after which samples should be split and/or renamed :type request: HttpRequest :type deposition_number: unicode :return: the HTTP response object :rtype: HttpResponse """ deposition = get_object_or_404(models.Deposition, number=deposition_number).actual_instance permissions.assert_can_edit_physical_process(request.user, deposition) if not deposition.finished: raise Http404("This deposition is not finished yet.") if deposition.split_done: raise Http404("You can use the split and rename function only once after a deposition.") remote_client = is_json_requested(request) if request.POST: original_data_forms, new_name_form_lists, global_new_data_form = \ forms_from_post_data(request.user, request.POST, deposition, remote_client) all_valid = is_all_valid(original_data_forms, new_name_form_lists, global_new_data_form) structure_changed = change_structure(request.user, original_data_forms, new_name_form_lists) referentially_valid = is_referentially_valid(original_data_forms, new_name_form_lists, deposition) if all_valid and referentially_valid and not structure_changed: sample_splits = save_to_database(original_data_forms, new_name_form_lists, global_new_data_form, deposition) for sample_split in sample_splits: utils.Reporter(request.user).report_sample_split(sample_split, sample_completely_split=True) return utils.successful_response(request, _("Samples were successfully split and/or renamed."), json_response=True) else: new_names = dict((int_or_zero(key[len("new-name-"):]), new_name) for key, new_name in request.GET.items() if key.startswith("new-name-")) new_names.pop(0, None) original_data_forms, new_name_form_lists, global_new_data_form = \ forms_from_database(request.user, deposition, remote_client, new_names) return render(request, "samples/split_after_deposition.html", {"title": _("Bulk sample rename for {deposition}").format(deposition=deposition), "samples": list(zip(original_data_forms, new_name_form_lists)), "new_sample_data": global_new_data_form})
def topics_and_permissions(request, login_name): user = get_object_or_404(django.contrib.auth.models.User, username=login_name) if not request.user.is_superuser and request.user != user: raise permissions.PermissionError( request.user, _("You can't access the list of topics and permissions of another user.")) if jb_common_utils.is_json_requested(request): return jb_common_utils.respond_in_json((user.topics.values_list("pk", flat=True), user.managed_topics.values_list("pk", flat=True), user.get_all_permissions())) return render(request, "samples/topics_and_permissions.html", {"title": _("Topics and permissions for {user_name}").format(user_name=get_really_full_name(request.user)), "topics": user.topics.all(), "managed_topics": user.managed_topics.all(), "permissions": permissions.get_user_permissions(user), "full_user_name": get_really_full_name(request.user), "permissions_url": django.core.urlresolvers.reverse("samples.views.permissions.list_")})
def topics_and_permissions(request, login_name): user = get_object_or_404(django.contrib.auth.models.User, username=login_name) if not request.user.is_superuser and request.user != user: raise permissions.PermissionError( request.user, _("You can't access the list of topics and permissions of another user.")) if jb_common_utils.is_json_requested(request): return jb_common_utils.respond_in_json((user.topics.values_list("pk", flat=True), user.managed_topics.values_list("pk", flat=True), user.get_all_permissions())) return render(request, "samples/topics_and_permissions.html", {"title": _("Topics and permissions for {user_name}").format(user_name=get_really_full_name(request.user)), "topics": user.topics.all(), "managed_topics": user.managed_topics.all(), "permissions": permissions.get_user_permissions(user), "full_user_name": get_really_full_name(request.user), "permissions_url": django.core.urlresolvers.reverse("samples:list_permissions")})
def show_process(request, process_id, process_name="Process"): """Show an existing physical process. This is some sort of fallback view in case a process doesn't provide its own show view (which is mostly the case). The ``process_id`` needn't be the ``"id"`` field: If `process_name` is not ``None``, its ``JBMeta.identifying_field``, it given, is used instead for the lookup. :param request: the current HTTP Request object :param process_id: the ID or the process's identifying field value :param process_name: the class name of the process; if ``None``, ``Process`` is assumed :type request: HttpRequest :type process_id: unicode :type process_name: unicode :return: the HTTP response object :rtype: HttpResponse """ process_class = get_all_models()[process_name] try: identifying_field = process_class.JBMeta.identifying_field except AttributeError: identifying_field = "id" try: process = get_object_or_404(process_class, **{ identifying_field: process_id }).actual_instance except ValueError: raise Http404("Invalid value for {} passed: {}".format( identifying_field, repr(process_id))) if not isinstance(process, models.PhysicalProcess): raise Http404("No physical process with that ID was found.") permissions.assert_can_view_physical_process(request.user, process) if is_json_requested(request): return respond_in_json(process.get_data()) template_context = { "title": six.text_type(process), "samples": process.samples.all(), "process": process } template_context.update(utils.digest_process(process, request.user)) return render(request, "samples/show_process.html", template_context)
def edit(request, username): """View for doing various things with the samples listed under “My Samples”. For example, copying them to the “My Samples” list of another user, or simply removing them from the list. Note that there are two different user variables in this view and its associated functions. ``current_user`` is the same as ``request.user``. Thus, it is the currently logged-in user. However, ``user`` is the user whose “My Samples” are to be processed. Almost always both are the same, especially because you are not allowed to see or change the “My Samples” of another user. However, staff users *are* allowed to change them, so then both are different. :param request: the current HTTP Request object :param username: the login name of the user whose “My Samples” should be changed :type request: HttpRequest :type username: unicode :return: the HTTP response object :rtype: HttpResponse """ user = get_object_or_404(django.contrib.auth.models.User, username=username) if not request.user.is_superuser and request.user != user: raise permissions.PermissionError(request.user, _("You can't access the “My Samples” section of another user.")) if request.method == "POST": my_samples_form = MySamplesForm(user, request.POST) action_form = ActionForm(user, request.POST) referentially_valid = is_referentially_valid(request.user, my_samples_form, action_form) if my_samples_form.is_valid() and action_form.is_valid() and referentially_valid: save_to_database(user, my_samples_form, action_form) return utils.successful_response(request, _("Successfully processed “My Samples”.")) else: if is_json_requested(request): return respond_in_json(request.user.my_samples.values_list("id", flat=True)) my_samples_form = MySamplesForm(user) action_form = ActionForm(user) return render(request, "samples/edit_my_samples.html", {"title": _("Manage “My Samples” of {user_name}").format(user_name=get_really_full_name(user)), "my_samples": my_samples_form, "action": action_form})
def process_response(self, request, response): """Return a HTTP 422 response if a JSON response was requested and an HTML page with form errors is returned. """ if is_json_requested(request) and response._headers["content-type"][1].startswith("text/html") and \ response.status_code == 200: user = request.user if not user.is_authenticated(): # Login view was returned return HttpResponseUnauthorised() hash_ = hashlib.sha1() hash_.update(six.binary_type(random.random())) # For some very obscure reason, a random number was not enough -- # it led to collisions time after time. hash_.update(six.binary_type(time.time())) hash_value = hash_.hexdigest() ErrorPage.objects.create(hash_value=hash_value, user=user, requested_url=request.get_full_path(), html=response.content) return HttpResponseUnprocessableEntity( json.dumps((1, request.build_absolute_uri( django.core.urlresolvers.reverse("jb_common.views.show_error_page", kwargs={"hash_value": hash_value})))), content_type="application/json") return response