def delete_process(request, process_id): """Deletes an existing physical process. :param request: the current HTTP Request object :param process_id: the process's ID :type request: HttpRequest :type process_id: unicode :return: the HTTP response object :rtype: HttpResponse """ process = get_object_or_404(Process, pk=int_or_zero(process_id)).actual_instance affected_objects = permissions.assert_can_delete_physical_process( request.user, process) for instance in affected_objects: if isinstance(instance, models.Sample): utils.Reporter(request.user).report_deleted_sample(instance) elif isinstance(instance, models.Process): utils.Reporter(request.user).report_deleted_process(instance) success_message = _( "Process {process} was successfully deleted in the database.").format( process=process) process.delete() return utils.successful_response(request, success_message)
def delete_process_confirmation(request, process_id): """View for confirming that you really want to delete the given process. Typically, it is visited by clicking on an icon. :param request: the current HTTP Request object :param process_id: the ID of the process :type request: HttpRequest :type process_id: unicode :return: the HTTP response object :rtype: HttpResponse """ process = get_object_or_404(Process, pk=int_or_zero(process_id)).actual_instance affected_objects = permissions.assert_can_delete_physical_process( request.user, process) digested_affected_objects = {} for instance in affected_objects: try: class_name = instance.__class__._meta.verbose_name_plural.title() except AttributeError: class_name = capfirst(_("miscellaneous")) digested_affected_objects.setdefault(class_name, set()).add(instance) return render( request, "samples/delete_process_confirmation.html", { "title": _("Delete process “{process}”").format(process=process), "process": process, "affected_objects": digested_affected_objects })
def fold_main_menu_element(request): """Fold a single topic or sample series from the main menu. :param request: The current HTTP Request object. It must contain the topic ID or sample series name. :type request: HttpRequest :return: True if the topic or sample series is now folded else False :rtype: HttpResponse """ def fold_element(element_id, folded_elements): folded_elements = json.loads(folded_elements) if element_id in folded_elements: folded_elements.remove(element_id) is_folded = False else: folded_elements.append(element_id) is_folded = True folded_elements = json.dumps(folded_elements) return is_folded, folded_elements element_id = int_or_zero(request.POST["element_id"]) if not element_id: element_id = request.POST["element_id"] element_is_folded, request.user.samples_user_details.folded_series = \ fold_element(element_id, request.user.samples_user_details.folded_series) else: element_is_folded, request.user.samples_user_details.folded_topics = \ fold_element(element_id, request.user.samples_user_details.folded_topics) request.user.samples_user_details.save() return respond_in_json(element_is_folded)
def fold_process(request, sample_id): """Fold a single process in one sample data sheet. The new behavior is also saved. :param request: The current HTTP Request object. It must contain the process ID of the process which behavior should be changed. :param sample_id: The sample ID represent the data sheet where the process has to be changed. :type request: HttpRequest :type sample_id: unicode :return: True when the process is now folded else False. :rtype: HttpResponse """ process_id = int_or_zero(request.POST["process_id"]) folded_process_classes = ContentType.objects.filter( dont_show_to_user=request.user.samples_user_details) folded_processes = json.loads( request.user.samples_user_details.folded_processes) exceptional_processes = folded_processes.setdefault(sample_id, []) is_folded = _is_folded(process_id, folded_process_classes, exceptional_processes, switch=True) request.user.samples_user_details.folded_processes = json.dumps( folded_processes) request.user.samples_user_details.save() return respond_in_json(is_folded)
def cancel_match(request, id_): match = get_object_or_404(models.Match, pk=int_or_zero(id_)) if id_ else None if match and match.reporter != request.user: raise JSONRequestException(3005, _("You must be the original reporter of this match.")) if match.finished: raise JSONRequestException(3003, _("A finished match can't be canceled.")) match.delete() return respond_in_json(True)
def edit(request, id): """View for changing the members of a particular topic, and to set the restriction status. This is only allowed to heads of institute groups and topic managers. :param request: the current HTTP Request object :param id: the id of the topic :type request: HttpRequest :type name: unicode :return: the HTTP response object :rtype: HttpResponse """ topic = get_object_or_404(Topic, id=int_or_zero(id), parent_topic=None) permissions.assert_can_edit_topic(request.user, topic) if request.method == "POST": edit_topic_form = EditTopicForm(request.user, topic, request.POST) added_members = [] removed_members = [] if edit_topic_form.is_valid(): old_manager = topic.manager new_manager = edit_topic_form.cleaned_data["topic_manager"] topic.manager = new_manager old_members = list(topic.members.all()) new_members = edit_topic_form.cleaned_data["members"] + [new_manager] topic.members = new_members topic.confidential = edit_topic_form.cleaned_data["confidential"] topic.save() if old_manager != new_manager: if not old_manager.managed_topics.all(): old_manager.user_permissions.remove(PermissionsModels.topic_manager_permission) if not permissions.has_permission_to_edit_users_topics(new_manager): new_manager.user_permissions.add(PermissionsModels.topic_manager_permission) for user in new_members: if user not in old_members: added_members.append(user) topic.auto_adders.add(user.samples_user_details) for user in old_members: if user not in new_members: removed_members.append(user) topic.auto_adders.remove(user.samples_user_details) if added_members: utils.Reporter(request.user).report_changed_topic_membership(added_members, topic, "added") if removed_members: utils.Reporter(request.user).report_changed_topic_membership(removed_members, topic, "removed") return utils.successful_response( request, _("Members of topic “{name}” were successfully updated.").format(name=topic.name)) else: edit_topic_form = \ EditTopicForm(request.user, topic, initial={"members": topic.members.values_list("pk", flat=True), "topic_manager": topic.manager.pk}) return render(request, "samples/edit_topic.html", {"title": _("Change topic memberships of “{0}”").format(topic.name), "edit_topic": edit_topic_form})
def cancel_match(request, id_): match = get_object_or_404(models.Match, pk=int_or_zero(id_)) if id_ else None if match and match.reporter != request.user: raise JSONRequestException( 3005, "You must be the original reporter of this match.") if match.finished: raise JSONRequestException(3003, "A finished match can't be canceled.") match.delete() return respond_in_json(True)
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 search(request): """View for searching for samples. The rule is: Everyone can see the *names* (not the data sheets) of all samples, unless they are in a confidential topic, unless the user is a member in that topic, its currently responsible person, or you have a clearance for the sample. A POST request on this URL will add samples to the “My Samples” list. *All* search parameters are in the query string, so if you just want to search, this is a GET requets. Therefore, this view has two submit buttons. :param request: the current HTTP Request object :type request: HttpRequest :return: the HTTP response object :rtype: HttpResponse """ too_many_results = False base_query = utils.restricted_samples_query(request.user) search_samples_form = SearchSamplesForm(request.GET) found_samples = [] if search_samples_form.is_valid(): name_pattern = search_samples_form.cleaned_data["name_pattern"] if name_pattern: if search_samples_form.cleaned_data["aliases"]: found_samples = base_query.filter(Q(name__icontains=name_pattern) | Q(aliases__name__icontains=name_pattern)) else: found_samples = base_query.filter(name__icontains=name_pattern) too_many_results = found_samples.count() > max_results found_samples = found_samples[:max_results] if too_many_results else found_samples my_samples = request.user.my_samples.all() if request.method == "POST": sample_ids = set(int_or_zero(key.partition("-")[0]) for key, value in request.POST.items() if value == "on") samples = base_query.in_bulk(sample_ids).values() request.user.my_samples.add(*samples) add_to_my_samples_forms = [AddToMySamplesForm(prefix=str(sample.pk)) if sample not in my_samples else None for sample in found_samples] return render(request, "samples/search_samples.html", {"title": _("Search for sample"), "search_samples": search_samples_form, "found_samples": list(zip(found_samples, add_to_my_samples_forms)), "too_many_results": too_many_results, "max_results": max_results})
def fold_process(request, sample_id): """Fold a single process in one sample data sheet. The new behavior is also saved. :param request: The current HTTP Request object. It must contain the process ID of the process which behavior should be changed. :param sample_id: The sample ID represent the data sheet where the process has to be changed. :type request: HttpRequest :type sample_id: unicode :return: True when the process is now folded else False. :rtype: HttpResponse """ process_id = int_or_zero(request.POST["process_id"]) folded_process_classes = ContentType.objects.filter(dont_show_to_user=request.user.samples_user_details) folded_processes = json.loads(request.user.samples_user_details.folded_processes) exceptional_processes = folded_processes.setdefault(sample_id, []) is_folded = _is_folded(process_id, folded_process_classes, exceptional_processes, switch=True) request.user.samples_user_details.folded_processes = json.dumps(folded_processes) request.user.samples_user_details.save() return respond_in_json(is_folded)
def fold_main_menu_element(request): """Fold a single topic or sample series from the main menu. :param request: The current HTTP Request object. It must contain the the topic ID or sample series name. :param element_id: The id from the topic or sample series :type request: HttpRequest :return: True when the topic or sample series is now folded else False :rtype: HttpResponse """ def fold_element(element_id, folded_elements): folded_elements = json.loads(folded_elements) if element_id in folded_elements: folded_elements.remove(element_id) is_folded = False else: folded_elements.append(element_id) is_folded = True folded_elements = json.dumps(folded_elements) return is_folded, folded_elements element_id = int_or_zero(request.POST["element_id"]) if not element_id: element_id = request.POST["element_id"] element_is_folded, request.user.samples_user_details.folded_series = \ fold_element(element_id, request.user.samples_user_details.folded_series) else: element_is_folded, request.user.samples_user_details.folded_topics = \ fold_element(element_id, request.user.samples_user_details.folded_topics) request.user.samples_user_details.save() return respond_in_json(element_is_folded)
def edit_match(request, id_=None): match = get_object_or_404(models.Match, pk=int_or_zero(id_)) if id_ else None if match and match.reporter != request.user: raise JSONRequestException( 3005, _("You must be the original reporter of this match.")) try: if not match: player_a_1 = get_object_or_404(django.contrib.auth.models.User, username=request.POST["player_a_1"]) player_a_2 = get_object_or_404(django.contrib.auth.models.User, username=request.POST["player_a_2"]) player_b_1 = get_object_or_404(django.contrib.auth.models.User, username=request.POST["player_b_1"]) player_b_2 = get_object_or_404(django.contrib.auth.models.User, username=request.POST["player_b_2"]) goals_a = int(request.POST["goals_a"]) goals_b = int(request.POST["goals_b"]) seconds = float(request.POST["seconds"]) finished = request.POST.get("finished") == "on" timestamp = django.utils.timezone.make_aware( datetime.datetime.strptime(request.POST["timestamp"], "%Y-%m-%d %H:%M:%S")) except KeyError as error: raise JSONRequestException(3, error.args[0]) except ValueError as error: raise JSONRequestException(5, error.args[0]) if not match: if player_a_1 == player_a_2 and player_b_1 != player_b_2 or player_a_1 != player_a_2 and player_b_1 == player_b_2: raise JSONRequestException( 3000, _("Matches with three players can't be processed.")) if player_a_1 == player_a_2 == player_b_1 == player_b_2: raise JSONRequestException(3001, _("All players are the same person.")) models.Match.objects.filter(finished=False, reporter=request.user).delete() else: if match.finished: raise JSONRequestException( 3003, _("A finished match can't be edited anymore.")) player_a_1 = match.player_a_1 player_a_2 = match.player_a_2 player_b_1 = match.player_b_1 player_b_2 = match.player_b_2 try: if finished and models.KickerNumber.objects.latest( ).timestamp > timestamp: raise JSONRequestException( 3002, _("This match is older than the most recent kicker numbers.")) except models.KickerNumber.DoesNotExist: pass if match: match.player_a_1 = player_a_1 match.player_a_2 = player_a_2 match.player_b_1 = player_b_1 match.player_b_2 = player_b_2 match.goals_a = goals_a match.goals_b = goals_b match.timestamp = timestamp match.finished = finished match.seconds = seconds match.save() else: match = models.Match.objects.create(player_a_1=player_a_1, player_a_2=player_a_2, player_b_1=player_b_1, player_b_2=player_b_2, goals_a=goals_a, goals_b=goals_b, timestamp=timestamp, finished=finished, seconds=seconds, reporter=request.user) if match.finished: if seconds <= 0: raise JSONRequestException(5, _("Seconds must be positive.")) match_result = MatchResult(match) match_result.add_kicker_numbers() match_result.add_stock_values() else: match.seconds = max(1, match.seconds) match_result = MatchResult(match) return respond_in_json((match.pk, match_result.expected_goal_difference, match_result.estimated_win_team_1))
def add_samples_to_database(add_samples_form, user): """Create the new samples and add them to the database. This routine consists of two parts: First, it tries to find a consecutive block of provisional sample names. Then, in actuall creates the samples. :param add_samples_form: the form with the samples' common data, including the substrate :param user: the current user :type add_samples_form: `AddSamplesForm` :type user: django.contrib.auth.models.User :return: the names of the new samples :rtype: list of unicode """ cleaned_data = add_samples_form.cleaned_data cleaning_number = cleaned_data.get("cleaning_number") substrate = institute_models.Substrate.objects.create( operator=user, timestamp=cleaned_data["timestamp"], material=cleaned_data["substrate"], comments=cleaned_data["substrate_comments"], external_operator=cleaned_data["substrate_originator"]) inaccuracy = cleaned_data["timestamp_inaccuracy"] if inaccuracy: substrate.timestamp_inaccuracy = inaccuracy substrate.save() provisional_sample_names = \ models.Sample.objects.filter(name__startswith="*").values_list("name", flat=True) occupied_provisional_numbers = [ int(name[1:]) for name in provisional_sample_names ] occupied_provisional_numbers.sort() occupied_provisional_numbers.insert(0, 0) number_of_samples = cleaned_data["number_of_samples"] if add_samples_form.cleaned_data.get("rename") == "cleaning": subnumbers = [ int_or_zero(name.rpartition("-")[2]) for name in models.Sample.objects.filter( name__startswith=cleaning_number).values_list("name", flat=True) ] starting_number = max(subnumbers) + 1 if subnumbers else 1 names = [ cleaning_number + "-{0:02}".format(i) for i in range(starting_number, starting_number + number_of_samples) ] else: for i in range(len(occupied_provisional_numbers) - 1): if occupied_provisional_numbers[i + 1] - occupied_provisional_numbers[ i] - 1 >= number_of_samples: starting_number = occupied_provisional_numbers[i] + 1 break else: starting_number = occupied_provisional_numbers[-1] + 1 names = [ "*{0:05}".format(i) for i in range(starting_number, starting_number + number_of_samples) ] new_names = [] samples = [] current_location, purpose, tags, topic = cleaned_data["current_location"], cleaned_data["purpose"], \ cleaned_data["tags"], cleaned_data["topic"] for new_name in names: sample = models.Sample.objects.create( name=new_name, current_location=current_location, currently_responsible_person=user, purpose=purpose, tags=tags, topic=topic) samples.append(sample) sample.processes.add(substrate) if cleaning_number: models.SampleAlias.objects.create(name=cleaning_number, sample=sample) sample.watchers.add(user) if topic: for watcher in (user_details.user for user_details in topic.auto_adders.all()): watcher.my_samples.add(sample) new_names.append(six.text_type(sample)) return new_names, samples
def add_samples_to_database(add_samples_form, user): """Create the new samples and add them to the database. This routine consists of two parts: First, it tries to find a consecutive block of provisional sample names. Then, in actuall creates the samples. :param add_samples_form: the form with the samples' common data, including the substrate :param user: the current user :type add_samples_form: `AddSamplesForm` :type user: django.contrib.auth.models.User :return: the names of the new samples :rtype: list of unicode """ cleaned_data = add_samples_form.cleaned_data cleaning_number = cleaned_data.get("cleaning_number") substrate = institute_models.Substrate.objects.create(operator=user, timestamp=cleaned_data["timestamp"], material=cleaned_data["substrate"], comments=cleaned_data["substrate_comments"], external_operator=cleaned_data["substrate_originator"]) inaccuracy = cleaned_data["timestamp_inaccuracy"] if inaccuracy: substrate.timestamp_inaccuracy = inaccuracy substrate.save() provisional_sample_names = \ models.Sample.objects.filter(name__startswith="*").values_list("name", flat=True) occupied_provisional_numbers = [int(name[1:]) for name in provisional_sample_names] occupied_provisional_numbers.sort() occupied_provisional_numbers.insert(0, 0) number_of_samples = cleaned_data["number_of_samples"] if add_samples_form.cleaned_data.get("rename") == "cleaning": subnumbers = [int_or_zero(name.rpartition("-")[2]) for name in models.Sample.objects.filter(name__startswith=cleaning_number).values_list("name", flat=True)] starting_number = max(subnumbers) + 1 if subnumbers else 1 names = [cleaning_number + "-{0:02}".format(i) for i in range(starting_number, starting_number + number_of_samples)] else: for i in range(len(occupied_provisional_numbers) - 1): if occupied_provisional_numbers[i + 1] - occupied_provisional_numbers[i] - 1 >= number_of_samples: starting_number = occupied_provisional_numbers[i] + 1 break else: starting_number = occupied_provisional_numbers[-1] + 1 names = ["*{0:05}".format(i) for i in range(starting_number, starting_number + number_of_samples)] new_names = [] samples = [] current_location, purpose, tags, topic = cleaned_data["current_location"], cleaned_data["purpose"], \ cleaned_data["tags"], cleaned_data["topic"] for new_name in names: sample = models.Sample.objects.create(name=new_name, current_location=current_location, currently_responsible_person=user, purpose=purpose, tags=tags, topic=topic) samples.append(sample) sample.processes.add(substrate) if cleaning_number: models.SampleAlias.objects.create(name=cleaning_number, sample=sample) sample.watchers.add(user) if topic: for watcher in (user_details.user for user_details in topic.auto_adders.all()): watcher.my_samples.add(sample) new_names.append(six.text_type(sample)) return new_names, samples
def edit_match(request, id_=None): match = get_object_or_404(models.Match, pk=int_or_zero(id_)) if id_ else None if match and match.reporter != request.user: raise JSONRequestException( 3005, "You must be the original reporter of this match.") try: if not match: player_a_1 = get_object_or_404(django.contrib.auth.models.User, username=request.POST["player_a_1"]) player_a_2 = get_object_or_404(django.contrib.auth.models.User, username=request.POST["player_a_2"]) player_b_1 = get_object_or_404(django.contrib.auth.models.User, username=request.POST["player_b_1"]) player_b_2 = get_object_or_404(django.contrib.auth.models.User, username=request.POST["player_b_2"]) goals_a = int(request.POST["goals_a"]) goals_b = int(request.POST["goals_b"]) seconds = float(request.POST["seconds"]) finished = request.POST.get("finished") == "on" timestamp = datetime.datetime.strptime(request.POST["timestamp"], "%Y-%m-%d %H:%M:%S") except KeyError as error: raise JSONRequestException(3, error.args[0]) except ValueError as error: raise JSONRequestException(5, error.args[0]) if not match: if player_a_1 == player_a_2 and player_b_1 != player_b_2 or player_a_1 != player_a_2 and player_b_1 == player_b_2: raise JSONRequestException( 3000, "Games with three players can't be processed.") if player_a_1 == player_a_2 == player_b_1 == player_b_2: raise JSONRequestException(3001, "All players are the same person.") unfinished_matches = models.Match.objects.filter(finished=False) if unfinished_matches.exists(): if unfinished_matches.exclude(reporter=request.user).exists(): raise JSONRequestException( 3004, "You can't add a match if another one of another reporter is not yet finished." ) for match in unfinished_matches.all(): match.delete() else: if match.finished: raise JSONRequestException( 3003, "A finished match can't be edited anymore.") player_a_1 = match.player_a_1 player_a_2 = match.player_a_2 player_b_1 = match.player_b_1 player_b_2 = match.player_b_2 try: seconds_since_most_recent = ( timestamp - models.Match.objects.latest("timestamp").timestamp ).total_seconds() if seconds_since_most_recent <= 0: if seconds_since_most_recent < -10: raise JSONRequestException( 3002, "This game is not the most recent one.") else: timestamp = models.Match.objects.latest( "timestamp").timestamp + datetime.timedelta(seconds=1) except models.Match.DoesNotExist: pass if match: match.player_a_1 = player_a_1 match.player_a_2 = player_a_2 match.player_b_1 = player_b_1 match.player_b_2 = player_b_2 match.goals_a = goals_a match.goals_b = goals_b match.timestamp = timestamp match.finished = finished match.seconds = seconds match.save() else: match = models.Match.objects.create(player_a_1=player_a_1, player_a_2=player_a_2, player_b_1=player_b_1, player_b_2=player_b_2, goals_a=goals_a, goals_b=goals_b, timestamp=timestamp, finished=finished, seconds=seconds, reporter=request.user) if match.finished: if seconds <= 0: raise JSONRequestException(5, "Seconds must be positive.") match_result = MatchResult(match) match_result.add_kicker_numbers() match_result.add_stock_values() else: match.seconds = max(1, match.seconds) match_result = MatchResult(match) return respond_in_json((match.pk, match_result.expected_goal_difference, match_result.estimated_win_team_1))
def clean_number_of_layers_to_add(self): return int_or_zero(self.cleaned_data["number_of_layers_to_add"])
def edit_match(request, id_=None): match = get_object_or_404(models.Match, pk=int_or_zero(id_)) if id_ else None if match and match.reporter != request.user: raise JSONRequestException(3005, _("You must be the original reporter of this match.")) try: if not match: player_a_1 = get_object_or_404(django.contrib.auth.models.User, username=request.POST["player_a_1"]) player_a_2 = get_object_or_404(django.contrib.auth.models.User, username=request.POST["player_a_2"]) player_b_1 = get_object_or_404(django.contrib.auth.models.User, username=request.POST["player_b_1"]) player_b_2 = get_object_or_404(django.contrib.auth.models.User, username=request.POST["player_b_2"]) goals_a = int(request.POST["goals_a"]) goals_b = int(request.POST["goals_b"]) seconds = float(request.POST["seconds"]) finished = request.POST.get("finished") == "on" timestamp = datetime.datetime.strptime(request.POST["timestamp"], "%Y-%m-%d %H:%M:%S") except KeyError as error: raise JSONRequestException(3, error.args[0]) except ValueError as error: raise JSONRequestException(5, error.args[0]) if not match: if player_a_1 == player_a_2 and player_b_1 != player_b_2 or player_a_1 != player_a_2 and player_b_1 == player_b_2: raise JSONRequestException(3000, _("Matches with three players can't be processed.")) if player_a_1 == player_a_2 == player_b_1 == player_b_2: raise JSONRequestException(3001, _("All players are the same person.")) models.Match.objects.filter(finished=False, reporter=request.user).delete() else: if match.finished: raise JSONRequestException(3003, _("A finished match can't be edited anymore.")) player_a_1 = match.player_a_1 player_a_2 = match.player_a_2 player_b_1 = match.player_b_1 player_b_2 = match.player_b_2 try: if finished and models.KickerNumber.objects.latest().timestamp > timestamp: raise JSONRequestException(3002, _("This match is older than the most recent kicker numbers.")) except models.KickerNumber.DoesNotExist: pass if match: match.player_a_1 = player_a_1 match.player_a_2 = player_a_2 match.player_b_1 = player_b_1 match.player_b_2 = player_b_2 match.goals_a = goals_a match.goals_b = goals_b match.timestamp = timestamp match.finished = finished match.seconds = seconds match.save() else: match = models.Match.objects.create( player_a_1=player_a_1, player_a_2=player_a_2, player_b_1=player_b_1, player_b_2=player_b_2, goals_a=goals_a, goals_b=goals_b, timestamp=timestamp, finished=finished, seconds=seconds, reporter=request.user) if match.finished: if seconds <= 0: raise JSONRequestException(5, _("Seconds must be positive.")) match_result = MatchResult(match) match_result.add_kicker_numbers() match_result.add_stock_values() else: match.seconds = max(1, match.seconds) match_result = MatchResult(match) return respond_in_json((match.pk, match_result.expected_goal_difference, match_result.estimated_win_team_1))
def advanced_search(request): """View for searching for samples, sample series, physical processes, and results. The visibility rules of the search results are the same as for the sample search. Additionally, you can only see sample series you are the currently responsible person of or that are in one of your topics. A POST request on this URL will add samples to the “My Samples” list. *All* search parameters are in the query string, so if you just want to search, this is a GET requets. Therefore, this view has two submit buttons. :param request: the current HTTP Request object :type request: HttpRequest :return: the HTTP response object :rtype: HttpResponse """ model_list = [model for model in jb_common.search.get_all_searchable_models() if hasattr(model, "get_absolute_url")] search_tree = None results, add_forms = [], [] too_many_results = False root_form = jb_common.search.SearchModelForm(model_list, request.GET) search_performed = False no_permission_message = None _search_parameters_hash = hashlib.sha1(json.dumps(sorted(dict((key, value) for key, value in request.GET.items() if not "__" in key and key != "_search_parameters_hash").items())).encode("utf-8")).hexdigest() column_groups_form = columns_form = table = switch_row_forms = old_data_form = None if root_form.is_valid() and root_form.cleaned_data["_model"]: search_tree = get_all_models()[root_form.cleaned_data["_model"]].get_search_tree_node() parse_tree = root_form.cleaned_data["_model"] == root_form.cleaned_data["_old_model"] search_tree.parse_data(request.GET if parse_tree else None, "") if search_tree.is_valid(): if search_tree.model_class == models.Sample: base_query = utils.restricted_samples_query(request.user) elif search_tree.model_class == models.SampleSeries: base_query = models.SampleSeries.objects.filter( Q(topic__confidential=False) | Q(topic__members=request.user) | Q(currently_responsible_person=request.user)).distinct() else: base_query = None results, too_many_results = jb_common.search.get_search_results(search_tree, max_results, base_query) if search_tree.model_class == models.Sample: if request.method == "POST": sample_ids = set(int_or_zero(key[2:].partition("-")[0]) for key, value in request.POST.items() if value == "on") samples = base_query.in_bulk(sample_ids).values() request.user.my_samples.add(*samples) my_samples = request.user.my_samples.all() add_forms = [AddToMySamplesForm(prefix="0-" + str(sample.pk)) if sample not in my_samples else None for sample in results] else: add_forms = len(results) * [None] if results and root_form.cleaned_data["_search_parameters_hash"] == _search_parameters_hash: data_node = data_tree.DataNode(_("search results")) for result in results: insert = False if isinstance(result, models.PhysicalProcess) \ and permissions.has_permission_to_view_physical_process(request.user, result): insert = True elif isinstance(result, models.Result) \ and permissions.has_permission_to_view_result_process(request.user, result): insert = True elif isinstance(result, models.Sample) \ and permissions.has_permission_to_fully_view_sample(request.user, result): insert = True elif isinstance(result, models.SampleSeries) \ and permissions.has_permission_to_view_sample_series(request.user, result): insert = True if insert: data_node.children.append(result.get_data_for_table_export()) if len(data_node.children) == 0: no_permission_message = _("You don't have the permission to see any content of the search results.") else: export_result = utils.table_export(request, data_node, "") if isinstance(export_result, tuple): column_groups_form, columns_form, table, switch_row_forms, old_data_form = export_result elif isinstance(export_result, HttpResponse): return export_result search_performed = True root_form = jb_common.search.SearchModelForm( model_list, initial={"_old_model": root_form.cleaned_data["_model"], "_model": root_form.cleaned_data["_model"], "_search_parameters_hash": _search_parameters_hash}) else: root_form = jb_common.search.SearchModelForm(model_list) root_form.fields["_model"].label = "" content_dict = {"title": capfirst(_("advanced search")), "search_root": root_form, "search_tree": search_tree, "results": list(zip(results, add_forms)), "search_performed": search_performed, "something_to_add": any(add_forms), "too_many_results": too_many_results, "max_results": max_results, "column_groups": column_groups_form, "columns": columns_form, "old_data": old_data_form, "rows": list(zip(table, switch_row_forms)) if table else None, "no_permission_message": no_permission_message} return render(request, "samples/advanced_search.html", content_dict)