def clean_samples(self): sample_names = self.cleaned_data["samples"].split(",") valid_names = [] invalid_names = [] for name in sample_names: name = name.strip() if name: if utils.sample_name_format(name) == "old": if name in valid_names: raise ValidationError(_("The name {name} appears more than once.").format(name=name)) valid_names.append(name) else: invalid_names.append(name) if invalid_names: error_message = ungettext( "The name {invalid_names} is not valid.", "The names {invalid_names} are not valid.", len(invalid_names)).format(invalid_names=format_enumeration(invalid_names)) raise ValidationError(error_message) if not valid_names: raise ValidationError(self.fields["samples"].error_messages["required"]) existing_names = [name for name in valid_names if utils.does_sample_exist(name)] if existing_names: # This opens a small security hole because people can find out that # confidential samples are existing. However, such samples mostly # have non-oldstyle names anyway. error_message = ungettext( "The name {existing_names} is already existing.", "The names {existing_names} are already existing.", len(existing_names)).format(existing_names=format_enumeration(existing_names)) raise ValidationError(error_message) return valid_names
def clean_new_name(self): new_name = self.cleaned_data["new_name"] sample_name_format, match = utils.sample_name_format( new_name, with_match_object=True) if not sample_name_format: raise ValidationError(_("The sample name has an invalid format.")) elif not new_name.startswith(self.parent_name): if sample_name_format not in self.possible_new_name_formats: error_message = _( "The new sample name must start with the parent sample's name." ) if self.possible_new_name_formats: further_error_message = ungettext( " Alternatively, it must be a valid “{sample_formats}” name.", " Alternatively, it must be a valid name of one of these types: " "{sample_formats}", len(self.possible_new_name_formats)) further_error_message = further_error_message.format( sample_formats=format_enumeration( utils.verbose_sample_name_format(name_format) for name_format in self.possible_new_name_formats)) error_message += further_error_message raise ValidationError(error_message) utils.check_sample_name(match, self.user) if utils.does_sample_exist(new_name): raise ValidationError(_("Name does already exist in database.")) return new_name
def clean_new_name(self): if "sample" in self.cleaned_data: new_name = self.cleaned_data["new_name"] if new_name != self.cleaned_data["sample"].name and utils.does_sample_exist(new_name): raise ValidationError(_("This sample name exists already.")) elif utils.sample_name_format(new_name) == "provisional": raise ValidationError(_("You must get rid of the provisional sample name.")) return new_name
def __init__(self, user, parent_name, *args, **kwargs): super(NewNameForm, self).__init__(*args, **kwargs) self.parent_name = parent_name parent_name_format = utils.sample_name_format(parent_name) if parent_name_format: self.possible_new_name_formats = settings.SAMPLE_NAME_FORMATS[parent_name_format].get("possible_renames", set()) else: self.possible_new_name_formats = set() self.user = user
def add_sample(request): """Adds a new sample to the database. It is added without processes. This view can only be used by admin accounts. :param request: the current HTTP Request object; it must contain the sample data in the POST data. :return: The primary key of the created sample. ``False`` if something went wrong. It may return a 404 if the topic or the currently responsible person wasn't found. :rtype: HttpResponse """ try: name = request.POST["name"] current_location = request.POST["current_location"] currently_responsible_person = request.POST["currently_responsible_person"] purpose = request.POST.get("purpose", "") tags = request.POST.get("tags", "") topic = request.POST.get("topic") except KeyError as error: raise JSONRequestException(3, "'{}' parameter missing.".format(error.args[0])) if len(name) > 30: raise JSONRequestException(5, "The sample name is too long.") name_format = utils.sample_name_format(name) if name_format is None or \ not request.user.is_superuser and \ name_format not in settings.SAMPLE_NAME_FORMATS["provisional"].get("possible_renames", set()): raise JSONRequestException(5, "The sample name is invalid.") eligible_users = django.contrib.auth.models.User.objects.filter(is_active=True, jb_user_details__department__isnull=False) try: currently_responsible_person = eligible_users.get(pk=utils.convert_id_to_int(currently_responsible_person)) except django.contrib.auth.models.User.DoesNotExist: raise Http404("Currently reponsible user not found.") if topic: all_topics = Topic.objects.all() if request.user.is_superuser else \ Topic.objects.filter(Q(confidential=False) | Q(members=request.user)) try: topic = all_topics.get(pk=utils.convert_id_to_int(topic)) except Topic.DoesNotExist: raise Http404("Topic not found") try: sample = models.Sample.objects.create(name=name, current_location=current_location, currently_responsible_person=currently_responsible_person, purpose=purpose, tags=tags, topic=topic) # They will be shadowed anyway. Nevertheless, this action is an # emergency measure. Probably the samples the aliases point to should # be merged with the sample but this can't be decided automatically. models.SampleAlias.objects.filter(name=name).delete() except IntegrityError as error: error_message = "The sample with this data could not be added." if request.user.is_superuser: error_message += " {}".format(error) raise JSONRequestException(5, error_message) sample.watchers.add(request.user) return respond_in_json(sample.pk)
def __init__(self, user, parent_name, *args, **kwargs): super(NewNameForm, self).__init__(*args, **kwargs) self.parent_name = parent_name parent_name_format = utils.sample_name_format(parent_name) if parent_name_format: self.possible_new_name_formats = settings.SAMPLE_NAME_FORMATS[ parent_name_format].get("possible_renames", set()) else: self.possible_new_name_formats = set() self.user = user
def clean_name(self): new_name = self.prefix_ + self.cleaned_data["name"] name_format, match = utils.sample_name_format(new_name, with_match_object=True) if name_format not in self.possible_new_name_formats: error_message = ungettext("New name must be a valid “{sample_formats}” name.", "New name must be a valid name of one of these types: {sample_formats}", len(self.possible_new_name_formats)) error_message = error_message.format(sample_formats=format_enumeration( utils.verbose_sample_name_format(name_format) for name_format in self.possible_new_name_formats)) raise ValidationError(error_message) utils.check_sample_name(match, self.user) if utils.does_sample_exist(new_name): raise ValidationError(_("This sample name exists already.")) return new_name
def clean(self): cleaned_data = super(OriginalDataForm, self).clean() if "new_name" in cleaned_data: new_name = cleaned_data["new_name"] sample = cleaned_data.get("sample") if sample: old_sample_name_format = utils.sample_name_format(sample.name) if old_sample_name_format not in utils.get_renamable_name_formats(): if not new_name.startswith(sample.name): self.add_error("new_name", _("The new name must begin with the old name.")) elif sample and sample.name != new_name: if not new_name.startswith(self.deposition_number): self.add_error("new_name", _("The new name must begin with the deposition number.")) return cleaned_data
def clean_name(self): new_name = self.prefix_ + self.cleaned_data["name"] name_format, match = utils.sample_name_format(new_name, with_match_object=True) if name_format not in self.possible_new_name_formats: error_message = ungettext("New name must be a valid “{sample_formats}” name.", "New name must be a valid name of one of these types: {sample_formats}", len(self.possible_new_name_formats)) error_message = error_message.format(sample_formats=format_enumeration( utils.verbose_sample_name_format(name_format) for name_format in self.possible_new_name_formats)) raise ValidationError(error_message) utils.check_sample_name(match, self.user) if utils.does_sample_exist(new_name): raise ValidationError(_("This sample name exists already.")) return new_name
def new_name(sample): try: return new_names[sample.id] except KeyError: if utils.sample_name_format(sample.name) in utils.get_renamable_name_formats(): name_postfix = "" try: sample_positions = json.loads(deposition.sample_positions) except AttributeError: pass else: if sample_positions and sample_positions.get(str(sample.id)): name_postfix = "-{0}".format(sample_positions[str(sample.id)]) return deposition.number + name_postfix else: return sample.name
def __init__(self, user, prefix_, sample, *args, **kwargs): """ :param user: The user that requests the renaming. :param prefix_: The prefix to be used. If, for some reason, there is no prefix available, give an empty string. Validation will then fail, however, it would fail for the whole page anyway without a prefix. :param sample: The sample to be renamed. :type user: django.contrib.auth.models.User :type prefix_: str :type sample: samples.models.Sample """ super(NewNameForm, self).__init__(*args, **kwargs) self.prefix_ = prefix_ old_name_format = utils.sample_name_format(sample.name) if old_name_format: self.possible_new_name_formats = settings.SAMPLE_NAME_FORMATS[old_name_format].get("possible_renames", set()) else: self.possible_new_name_formats = set() self.user = user
def clean_new_name(self): new_name = self.cleaned_data["new_name"] sample_name_format, match = utils.sample_name_format(new_name, with_match_object=True) if not sample_name_format: raise ValidationError(_("The sample name has an invalid format.")) elif not new_name.startswith(self.parent_name): if sample_name_format not in self.possible_new_name_formats: error_message = _("The new sample name must start with the parent sample's name.") if self.possible_new_name_formats: further_error_message = ungettext(" Alternatively, it must be a valid “{sample_formats}” name.", " Alternatively, it must be a valid name of one of these types: " "{sample_formats}", len(self.possible_new_name_formats)) further_error_message = further_error_message.format(sample_formats=format_enumeration( utils.verbose_sample_name_format(name_format) for name_format in self.possible_new_name_formats)) error_message += further_error_message raise ValidationError(error_message) utils.check_sample_name(match, self.user) if utils.does_sample_exist(new_name): raise ValidationError(_("Name does already exist in database.")) return new_name
def __init__(self, user, prefix_, sample, *args, **kwargs): """ :param user: The user that requests the renaming. :param prefix_: The prefix to be used. If, for some reason, there is no prefix available, give an empty string. Validation will then fail, however, it would fail for the whole page anyway without a prefix. :param sample: The sample to be renamed. :type user: django.contrib.auth.models.User :type prefix_: str :type sample: samples.models.Sample """ super(NewNameForm, self).__init__(*args, **kwargs) self.prefix_ = prefix_ old_name_format = utils.sample_name_format(sample.name) if old_name_format: self.possible_new_name_formats = settings.SAMPLE_NAME_FORMATS[old_name_format].get("possible_renames", set()) else: self.possible_new_name_formats = set() self.user = user
def clean_samples(self): sample_names = self.cleaned_data["samples"].split(",") valid_names = [] invalid_names = [] for name in sample_names: name = name.strip() if name: if utils.sample_name_format(name) == "old": if name in valid_names: raise ValidationError( _("The name {name} appears more than once."). format(name=name)) valid_names.append(name) else: invalid_names.append(name) if invalid_names: error_message = ungettext( "The name {invalid_names} is not valid.", "The names {invalid_names} are not valid.", len(invalid_names)).format( invalid_names=format_enumeration(invalid_names)) raise ValidationError(error_message) if not valid_names: raise ValidationError( self.fields["samples"].error_messages["required"]) existing_names = [ name for name in valid_names if utils.does_sample_exist(name) ] if existing_names: # This opens a small security hole because people can find out that # confidential samples are existing. However, such samples mostly # have non-oldstyle names anyway. error_message = ungettext( "The name {existing_names} is already existing.", "The names {existing_names} are already existing.", len(existing_names)).format( existing_names=format_enumeration(existing_names)) raise ValidationError(error_message) return valid_names
def clean_new_name(self): new_name = self.cleaned_data["new_name"] sample_name_format = utils.sample_name_format(new_name) if not sample_name_format: raise ValidationError(_("The sample name has an invalid format.")) return new_name
def edit_depositions(request, deposition_number, form_set, institute_model, edit_url, rename_conservatively=False): """This function is the central view for editing, creating, and duplicating for any deposition. The edit functions in the deposition views are wrapper functions who provides this function with the specific informations. If `deposition_number` is ``None``, a new depositon is created (possibly by duplicating another one). :param request: the HTTP request object :param deposition_number: the number (=name) or the deposition :param form_set: the related formset object for the deposition :param institute_model: the related Database model :param edit_url: the location of the edit template :param rename_conservatively: If ``True``, rename only provisional and cleaning process names. This is used by the Large Sputter deposition. See the ``new_names`` parameter in `samples.views.split_after_deposition.forms_from_database` for how this is achieved :type request: QueryDict :type deposition_number: unicode or NoneType :type form_set: FormSet :type institute_model: `samples.models.Deposition` :type edit_url: unicode :type rename_conservatively: bool :return: the HTTP response object :rtype: HttpResponse """ permissions.assert_can_add_edit_physical_process(request.user, form_set.deposition, institute_model) if request.method == "POST": form_set.from_post_data(request.POST) deposition = form_set.save_to_database() if deposition: if form_set.remove_from_my_samples_form and \ form_set.remove_from_my_samples_form.cleaned_data["remove_from_my_samples"]: utils.remove_samples_from_my_samples(deposition.samples.all(), form_set.user) next_view = next_view_kwargs = None query_string = "" newly_finished = deposition.finished and ( not form_set.deposition or getattr(form_set, "unfinished", False)) if newly_finished: rename = False new_names = {} if rename_conservatively: for sample in deposition.samples.all(): name_format = utils.sample_name_format(sample.name) if name_format == "provisional" or name_format == "old" and sample.name[ 2] in ["N", "V"]: rename = True elif name_format == "old": new_names[sample.id] = sample.name else: rename = True if rename: next_view = "samples.views.split_after_deposition.split_and_rename_after_deposition" next_view_kwargs = {"deposition_number": deposition.number} query_string = urllib.parse.urlencode([ ("new-name-{0}".format(id_), new_name) for id_, new_name in new_names.items() ]) elif not deposition.finished: next_view, __, next_view_kwargs = django.core.urlresolvers.resolve( request.path) next_view_kwargs["deposition_number"] = deposition.number if deposition_number: message = _("Deposition {number} was successfully changed in the database."). \ format(number=deposition.number) json_response = True else: message = _( "Deposition {number} was successfully added to the database." ).format(number=deposition.number) json_response = deposition.pk return utils.successful_response(request, message, next_view, next_view_kwargs or {}, query_string, forced=next_view is not None, json_response=json_response) else: messages.error( request, _("The deposition was not saved due to incorrect or missing data." )) else: form_set.from_database(request.GET) institute_model_name = capitalize_first_letter( institute_model._meta.verbose_name) title = _("Edit {name} “{number}”").format(name=institute_model_name, number=deposition_number) if deposition_number \ else _("Add {name}").format(name=institute_model._meta.verbose_name) title = capitalize_first_letter(title) context_dict = {"title": title} context_dict.update(form_set.get_context_dict()) return render(request, edit_url, context_dict)
def bulk_rename(request): """View for bulk-renaming samples that have had a provisional name so far. If the user doesn't have initials yet, he is redirected to his preferences page. :param request: the current HTTP Request object :type request: HttpRequest :return: the HTTP response object :rtype: HttpResponse """ # FixMe: Get rid of the "numbers" parameter. I think it is only used in # the remote client. if "numbers" in request.GET: numbers_list = request.GET.get("numbers", "") samples = [get_object_or_404(models.Sample, name="*" + number.zfill(5)) for number in numbers_list.split(",")] elif "ids" in request.GET: ids = request.GET["ids"].split(",") samples = [get_object_or_404(models.Sample, pk=utils.convert_id_to_int(id_)) for id_ in ids] if not all(utils.sample_name_format(sample.name) in utils.get_renamable_name_formats() for sample in samples): raise Http404("Some given samples cannot be renamed.") else: samples = None if not samples: raise Http404("No samples given.") for sample in samples: permissions.assert_can_edit_sample(request.user, sample) available_prefixes = find_prefixes(request.user) if not available_prefixes and any("{user_initials}" in format_ for format_ in settings.NAME_PREFIX_TEMPLATES) \ and not models.Initials.objects.filter(user=request.user).exists(): query_string = "initials_mandatory=True&next=" + django.utils.http.urlquote_plus( request.path + "?" + request.META["QUERY_STRING"], safe="/") messages.info(request, _("You may change the sample names, but you must choose initials first.")) return utils.successful_response(request, view="samples.views.user_details.edit_preferences", kwargs={"login_name": request.user.username}, query_string=query_string, forced=True) single_prefix = available_prefixes[0][1] if len(available_prefixes) == 1 else None if request.method == "POST": if single_prefix: prefixes_form = None prefix = single_prefix elif available_prefixes: prefixes_form = PrefixesForm(available_prefixes, request.POST) prefix = prefixes_form.cleaned_data["prefix"] if prefixes_form.is_valid() else "" else: prefixes_form = None prefix = "" if prefix == "*": prefix = "" new_name_forms = [NewNameForm(request.user, prefix, sample, request.POST, prefix=str(sample.pk)) for sample in samples] all_valid = prefixes_form is None or prefixes_form.is_valid() all_valid = all([new_name_form.is_valid() for new_name_form in new_name_forms]) and all_valid referentially_valid = is_referentially_valid(samples, new_name_forms) if all_valid and referentially_valid: for sample, new_name_form in zip(samples, new_name_forms): if not sample.name.startswith("*"): models.SampleAlias(name=sample.name, sample=sample).save() sample.name = new_name_form.cleaned_data["name"] sample.save() return utils.successful_response(request, _("Successfully renamed the samples.")) else: prefixes_form = PrefixesForm(available_prefixes, initial={"prefix": available_prefixes[0][0]}) \ if available_prefixes else None new_name_forms = [NewNameForm(request.user, "", sample, prefix=str(sample.pk)) for sample in samples] return render(request, "samples/bulk_rename.html", {"title": _("Rename samples"), "prefixes": prefixes_form, "single_prefix": single_prefix, "samples": list(zip(samples, new_name_forms))})
def bulk_rename(request): """View for bulk-renaming samples that have had a provisional name so far. If the user doesn't have initials yet, he is redirected to his preferences page. :param request: the current HTTP Request object :type request: HttpRequest :return: the HTTP response object :rtype: HttpResponse """ # FixMe: Get rid of the "numbers" parameter. I think it is only used in # the remote client. if "numbers" in request.GET: numbers_list = request.GET.get("numbers", "") samples = [get_object_or_404(models.Sample, name="*" + number.zfill(5)) for number in numbers_list.split(",")] elif "ids" in request.GET: ids = request.GET["ids"].split(",") samples = [get_object_or_404(models.Sample, pk=utils.convert_id_to_int(id_)) for id_ in ids] if not all(utils.sample_name_format(sample.name) in utils.get_renamable_name_formats() for sample in samples): raise Http404("Some given samples cannot be renamed.") else: samples = None if not samples: raise Http404("No samples given.") for sample in samples: permissions.assert_can_edit_sample(request.user, sample) available_prefixes = find_prefixes(request.user) if not available_prefixes and any("{user_initials}" in format_ for format_ in settings.NAME_PREFIX_TEMPLATES) \ and not models.Initials.objects.filter(user=request.user).exists(): query_string = "initials_mandatory=True&next=" + django.utils.http.urlquote_plus( request.path + "?" + request.META["QUERY_STRING"], safe="/") messages.info(request, _("You may change the sample names, but you must choose initials first.")) return utils.successful_response(request, view="samples.views.user_details.edit_preferences", kwargs={"login_name": request.user.username}, query_string=query_string, forced=True) single_prefix = available_prefixes[0][1] if len(available_prefixes) == 1 else None if request.method == "POST": if single_prefix: prefixes_form = None prefix = single_prefix elif available_prefixes: prefixes_form = PrefixesForm(available_prefixes, request.POST) prefix = prefixes_form.cleaned_data["prefix"] if prefixes_form.is_valid() else "" else: prefixes_form = None prefix = "" if prefix == "*": prefix = "" new_name_forms = [NewNameForm(request.user, prefix, sample, request.POST, prefix=str(sample.pk)) for sample in samples] all_valid = prefixes_form is None or prefixes_form.is_valid() all_valid = all([new_name_form.is_valid() for new_name_form in new_name_forms]) and all_valid referentially_valid = is_referentially_valid(samples, new_name_forms) if all_valid and referentially_valid: for sample, new_name_form in zip(samples, new_name_forms): if not sample.name.startswith("*"): models.SampleAlias(name=sample.name, sample=sample).save() sample.name = new_name_form.cleaned_data["name"] sample.save() return utils.successful_response(request, _("Successfully renamed the samples.")) else: prefixes_form = PrefixesForm(available_prefixes, initial={"prefix": available_prefixes[0][0]}) \ if available_prefixes else None new_name_forms = [NewNameForm(request.user, "", sample, prefix=str(sample.pk)) for sample in samples] return render(request, "samples/bulk_rename.html", {"title": _("Rename samples"), "prefixes": prefixes_form, "single_prefix": single_prefix, "samples": list(zip(samples, new_name_forms))})
def add_sample(request): """Adds a new sample to the database. It is added without processes. This view can only be used by admin accounts. :param request: the current HTTP Request object; it must contain the sample data in the POST data. :return: The primary key of the created sample. ``False`` if something went wrong. It may return a 404 if the topic or the currently responsible person wasn't found. :rtype: HttpResponse """ try: name = request.POST["name"] current_location = request.POST["current_location"] currently_responsible_person = request.POST[ "currently_responsible_person"] purpose = request.POST.get("purpose", "") tags = request.POST.get("tags", "") topic = request.POST.get("topic") except KeyError as error: raise JSONRequestException( 3, "'{}' parameter missing.".format(error.args[0])) if len(name) > 30: raise JSONRequestException(5, "The sample name is too long.") name_format = utils.sample_name_format(name) if name_format is None or \ not request.user.is_staff and name_format not in settings.SAMPLE_NAME_FORMATS["provisional"].get("possible_renames", set()): raise JSONRequestException(5, "The sample name is invalid.") eligible_users = django.contrib.auth.models.User.objects.filter( is_active=True, jb_user_details__department__isnull=False) try: currently_responsible_person = eligible_users.get( pk=utils.convert_id_to_int(currently_responsible_person)) except django.contrib.auth.models.User.DoesNotExist: raise Http404("Currently reponsible user not found.") if topic: all_topics = Topic.objects.all() if request.user.is_staff else \ Topic.objects.filter(Q(confidential=False) | Q(members=request.user)) try: topic = all_topics.get(pk=utils.convert_id_to_int(topic)) except Topic.DoesNotExist: raise Http404("Topic not found") try: sample = models.Sample.objects.create( name=name, current_location=current_location, currently_responsible_person=currently_responsible_person, purpose=purpose, tags=tags, topic=topic) # They will be shadowed anyway. Nevertheless, this action is an # emergency measure. Probably the samples the aliases point to should # be merged with the sample but this can't be decided automatically. models.SampleAlias.objects.filter(name=name).delete() except IntegrityError as error: error_message = "The sample with this data could not be added." if request.user.is_staff: error_message += " {}".format(error) raise JSONRequestException(5, error_message) sample.watchers.add(request.user) return respond_in_json(sample.pk)
def is_referentially_valid(original_data_forms, new_name_form_lists, deposition): """Test whether all forms are consistent with each other and with the database. For example, no sample name must occur twice, and the sample names must not exist within the database already. :param original_data_forms: all old samples and pieces numbers :param new_name_form_lists: new names for all pieces :param deposition: the deposition after which the split takes place :type original_data_forms: list of `OriginalDataForm` :type new_name_form_lists: list of `NewNameForm` :type deposition: `samples.models.Deposition` :return: whether all forms are consistent with each other and the database :rtype: bool """ referentially_valid = True samples = list(deposition.samples.all()) more_than_one_piece = len(original_data_forms) > 1 new_names = set() original_samples = set() for original_data_form in original_data_forms: if original_data_form.is_valid(): original_sample = original_data_form.cleaned_data["sample"] if original_sample in original_samples: original_data_form.add_error("sample", _("Sample {sample} occurs multiple times.").format(sample=original_sample)) referentially_valid = False original_samples.add(original_sample) if original_sample not in samples: original_data_form.add_error("sample", _("Sample {sample} doesn't belong to this deposition.").format(sample=original_sample)) referentially_valid = False new_name = original_data_form.cleaned_data["new_name"] if new_name in new_names: original_data_form.add_error("new_name", _("This sample name has been used already on this page.")) referentially_valid = False new_names.add(new_name) if more_than_one_piece and new_name == deposition.number: original_data_form.add_error("new_name", _("Since there is more than one piece, the new name " "must not be exactly the deposition's name.")) referentially_valid = False if all(original_data_form.is_valid() for original_data_form in original_data_forms): assert len(original_samples) <= len(samples) if len(original_samples) < len(samples): original_data_form.add_error(None, _("At least one sample of the original deposition is missing.")) referentially_valid = False for new_name_forms, original_data_form in zip(new_name_form_lists, original_data_forms): if original_data_form.is_valid(): original_sample = original_data_form.cleaned_data["sample"] if deposition != original_sample.processes.exclude(content_type=ContentType.objects. get_for_model(models.Result)) \ .order_by("-timestamp")[0].actual_instance and original_data_form.cleaned_data["number_of_pieces"] > 1: original_data_form.add_error("sample", _("The sample can't be split, because the deposition is not the latest process.")) referentially_valid = False else: for new_name_form in new_name_forms: if new_name_form.is_valid(): new_name = new_name_form.cleaned_data["new_name"] if original_data_form.cleaned_data["number_of_pieces"] == 1: if new_name != original_data_form.cleaned_data["new_name"]: new_name_form.add_error("new_name", _("If you don't split, you can't rename the single piece.")) referentially_valid = False else: if new_name in new_names: new_name_form.add_error("new_name", _("This sample name has been used already on this page.")) referentially_valid = False new_names.add(new_name) if utils.sample_name_format(new_name) in utils.get_renamable_name_formats() and \ not new_name.startswith(original_data_form.cleaned_data["new_name"]): new_name_form.add_error("new_name", _("If you choose a deposition-style name, it must begin " "with the parent's new name.")) referentially_valid = False if utils.does_sample_exist(new_name): new_name_form.add_error("new_name", _("This sample name exists already.")) referentially_valid = False return referentially_valid