class MethodForm(SaveFormInitMixin, forms.ModelForm): phase = ModelChoiceField( queryset=None, help_text="Which phase is this evaluation container for?", ) chunked_upload = UploadedAjaxFileList( widget=uploader.AjaxUploadWidget(multifile=False, auto_commit=False), label="Evaluation Method Container", validators=[ ExtensionValidator(allowed_extensions=(".tar", ".tar.gz")) ], help_text=( ".tar.gz archive of the container image produced from the command " "'docker save IMAGE | gzip -c > IMAGE.tar.gz'. See " "https://docs.docker.com/engine/reference/commandline/save/"), ) def __init__(self, *args, user, challenge, **kwargs): super().__init__(*args, **kwargs) self.fields["chunked_upload"].widget.user = user self.fields["phase"].queryset = challenge.phase_set.all() class Meta: model = Method fields = ["phase", "chunked_upload"]
class AlgorithmForm(forms.ModelForm): ipython_notebook = forms.FileField( validators=[MimeTypeValidator(allowed_types=("text/plain", ))], required=False, help_text=( "Please upload an iPython notebook that describes your algorithm"), ) chunked_upload = UploadedAjaxFileList( widget=algorithm_upload_widget, label="Algorithm Image", validators=[ ExtensionValidator(allowed_extensions=(".tar", ".tar.gz")) ], help_text=( ".tar.gz archive of the container image produced from the command " "'docker save IMAGE > IMAGE.tar | gzip'. See " "https://docs.docker.com/engine/reference/commandline/save/"), ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper(self) class Meta: model = Algorithm fields = ( "title", "requires_gpu", "ipython_notebook", "chunked_upload", )
class AlgorithmImageForm(ModelForm): chunked_upload = UploadedAjaxFileList( widget=uploader.AjaxUploadWidget(multifile=False), label="Algorithm Image", validators=[ ExtensionValidator(allowed_extensions=(".tar", ".tar.gz")) ], help_text=( ".tar.gz archive of the container image produced from the command " "'docker save IMAGE | gzip -c > IMAGE.tar.gz'. See " "https://docs.docker.com/engine/reference/commandline/save/"), ) requires_memory_gb = IntegerField( min_value=1, max_value=24, initial=4, help_text= "The maximum system memory required by the algorithm in gigabytes.", ) def __init__(self, *args, user, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper(self) self.fields["chunked_upload"].widget.user = user class Meta: model = AlgorithmImage fields = ("requires_gpu", "requires_memory_gb", "chunked_upload")
class AlgorithmForm(forms.ModelForm): ipython_notebook = forms.FileField( validators=[ MimeTypeValidator(allowed_types=('text/plain',)) ], required=False, help_text=( "Please upload an iPython notebook that describes your algorithm" ), ) chunked_upload = UploadedAjaxFileList( widget=algorithm_upload_widget, label='Algorithm Image', validators=[ ExtensionValidator(allowed_extensions=('.tar',)) ], help_text=( 'Tar archive of the container image produced from the command ' '`docker save IMAGE > IMAGE.tar`. See ' 'https://docs.docker.com/engine/reference/commandline/save/' ), ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper(self) class Meta: model = Algorithm fields = ('ipython_notebook', 'chunked_upload',)
class AlgorithmImageForm(forms.ModelForm): chunked_upload = UploadedAjaxFileList( widget=algorithm_image_upload_widget, label="Algorithm Image", validators=[ ExtensionValidator(allowed_extensions=(".tar", ".tar.gz")) ], help_text=( ".tar.gz archive of the container image produced from the command " "'docker save IMAGE | gzip -c > IMAGE.tar.gz'. See " "https://docs.docker.com/engine/reference/commandline/save/" ), ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper(self) class Meta: model = AlgorithmImage fields = ( "title", "requires_gpu", "description", "logo", "chunked_upload", )
class ImportForm(SaveFormInitMixin, forms.Form): products_file = forms.FileField() companies_file = forms.FileField() images_zip = UploadedAjaxFileList(widget=uploader.AjaxUploadWidget( multifile=False, auto_commit=False), ) def __init__(self, *args, user, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper() self.helper.add_input(Submit("save", "Submit")) self.fields["images_zip"].widget.user = user
def test_form_field_to_python(): form_field = UploadedAjaxFileList() uuid_string = "4dec34db-930f-48be-bb65-d7f8319ff654," + "5d901b2c-7cd1-416e-9952-d30b6a0edcba," + "4a3c5731-0050-4489-8364-282278f7190f" staged_files = form_field.to_python(uuid_string) assert ",".join(str(sf.uuid) for sf in staged_files) == uuid_string with pytest.raises(ValidationError): form_field.to_python("asdfasdfsdafasdf") other_string = uuid_string[10:] with pytest.raises(ValidationError): form_field.to_python(other_string)
class SubmissionForm(forms.ModelForm): chunked_upload = UploadedAjaxFileList( widget=uploader.AjaxUploadWidget(multifile=False), label="Predictions File", validators=[ExtensionValidator(allowed_extensions=(".zip", ".csv"))], ) def __init__( self, *args, user, display_comment_field=False, supplementary_file_choice=Config.OFF, supplementary_file_label="", supplementary_file_help_text="", publication_url_choice=Config.OFF, **kwargs, ): """ Conditionally render the comment field based on the display_comment_field kwarg """ super().__init__(*args, **kwargs) if not display_comment_field: del self.fields["comment"] if supplementary_file_label: self.fields["supplementary_file"].label = supplementary_file_label if supplementary_file_help_text: self.fields[ "supplementary_file"].help_text = supplementary_file_help_text if supplementary_file_choice == Config.REQUIRED: self.fields["supplementary_file"].required = True elif supplementary_file_choice == Config.OFF: del self.fields["supplementary_file"] if publication_url_choice == Config.REQUIRED: self.fields["publication_url"].required = True elif publication_url_choice == Config.OFF: del self.fields["publication_url"] self.helper = FormHelper(self) self.fields["chunked_upload"].widget.user = user class Meta: model = Submission fields = submission_fields
class SubmissionForm(forms.ModelForm): chunked_upload = UploadedAjaxFileList( widget=submission_upload_widget, label='Predictions File', validators=[ExtensionValidator(allowed_extensions=('.zip', '.csv'))], ) def __init__(self, *args, **kwargs): """ Conditionally render the comment field based on the display_comment_field kwarg """ display_comment_field = kwargs.pop('display_comment_field', False) allow_supplementary_file = kwargs.pop( 'allow_supplementary_file', False ) require_supplementary_file = kwargs.pop( 'require_supplementary_file', False ) supplementary_file_label = kwargs.pop('supplementary_file_label', '') supplementary_file_help_text = kwargs.pop( 'supplementary_file_help_text', '' ) super(SubmissionForm, self).__init__(*args, **kwargs) if not display_comment_field: del self.fields['comment'] if supplementary_file_label: self.fields['supplementary_file'].label = supplementary_file_label if supplementary_file_help_text: self.fields[ 'supplementary_file' ].help_text = supplementary_file_help_text if require_supplementary_file: self.fields['supplementary_file'].required = True elif not allow_supplementary_file: del self.fields['supplementary_file'] self.helper = FormHelper(self) class Meta: model = Submission fields = ('comment', 'supplementary_file', 'chunked_upload')
class UploadRawImagesForm(forms.ModelForm): files = UploadedAjaxFileList( widget=uploader.AjaxUploadWidget(multifile=True, auto_commit=False), label="Image files", help_text=IMAGE_UPLOAD_HELP_TEXT, ) def __init__(self, *args, user, linked_task=None, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper() self.helper.add_input(Submit("save", "Submit")) self.fields["files"].widget.user = user self._linked_task = linked_task def clean_files(self): files = self.cleaned_data["files"] if len({f.name for f in files}) != len(files): raise ValidationError("Filenames must be unique.") if sum([f.size for f in files]) > settings.UPLOAD_SESSION_MAX_BYTES: raise ValidationError( "Total size of all files exceeds the upload limit.") return files def save(self, commit=True): instance = super().save(commit=False) # type: RawImageUploadSession # Create links between the created session and all uploaded files uploaded_files = self.cleaned_data[ "files"] # type: List[StagedAjaxFile] raw_files = [ RawImageFile( upload_session=instance, filename=uploaded_file.name, staged_file_id=uploaded_file.uuid, ) for uploaded_file in uploaded_files ] if commit: instance.save() RawImageFile.objects.bulk_create(raw_files) instance.process_images(linked_task=self._linked_task) return instance class Meta: model = RawImageUploadSession fields = ["files"]
class AnnotationSetUpdateLabelsForm(forms.ModelForm): chunked_upload = UploadedAjaxFileList( widget=labels_upload_widget, label="Labels File", validators=[ExtensionValidator(allowed_extensions=(".csv", ))], ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper(self) class Meta: model = AnnotationSet fields = ("chunked_upload", )
class AnnotationSetUpdateLabelsForm(forms.ModelForm): chunked_upload = UploadedAjaxFileList( widget=uploader.AjaxUploadWidget(multifile=False), label="Labels File", validators=[ExtensionValidator(allowed_extensions=(".csv",))], ) def __init__(self, *args, user, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper(self) self.fields["chunked_upload"].widget.user = user class Meta: model = AnnotationSet fields = ("chunked_upload",)
class SubmissionForm(forms.ModelForm): chunked_upload = UploadedAjaxFileList( widget=submission_upload_widget, label="Predictions File", validators=[ExtensionValidator(allowed_extensions=(".zip", ".csv"))], ) def __init__(self, *args, **kwargs): """ Conditionally render the comment field based on the display_comment_field kwarg """ display_comment_field = kwargs.pop("display_comment_field", False) allow_supplementary_file = kwargs.pop("allow_supplementary_file", False) require_supplementary_file = kwargs.pop("require_supplementary_file", False) supplementary_file_label = kwargs.pop("supplementary_file_label", "") supplementary_file_help_text = kwargs.pop( "supplementary_file_help_text", "") super().__init__(*args, **kwargs) if not display_comment_field: del self.fields["comment"] if supplementary_file_label: self.fields["supplementary_file"].label = supplementary_file_label if supplementary_file_help_text: self.fields[ "supplementary_file"].help_text = supplementary_file_help_text if require_supplementary_file: self.fields["supplementary_file"].required = True elif not allow_supplementary_file: del self.fields["supplementary_file"] self.helper = FormHelper(self) class Meta: model = Submission fields = ("comment", "supplementary_file", "chunked_upload")
class MethodForm(forms.ModelForm): chunked_upload = UploadedAjaxFileList( widget=method_upload_widget, label="Evaluation Method Container", validators=[ExtensionValidator(allowed_extensions=(".tar", ))], help_text=( "Tar archive of the container image produced from the command " "`docker save IMAGE > IMAGE.tar`. See " "https://docs.docker.com/engine/reference/commandline/save/"), ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper(self) class Meta: model = Method fields = ["chunked_upload"]
class MethodForm(forms.ModelForm): chunked_upload = UploadedAjaxFileList( widget=uploader.AjaxUploadWidget(multifile=False), label="Evaluation Method Container", validators=[ ExtensionValidator(allowed_extensions=(".tar", ".tar.gz")) ], help_text=( ".tar.gz archive of the container image produced from the command " "'docker save IMAGE | gzip -c > IMAGE.tar.gz'. See " "https://docs.docker.com/engine/reference/commandline/save/"), ) def __init__(self, *args, user, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper(self) self.fields["chunked_upload"].widget.user = user class Meta: model = Method fields = ["chunked_upload"]
def test_form_field_to_python(): form_field = UploadedAjaxFileList() uuid_string = ",".join( ( "4dec34db-930f-48be-bb65-d7f8319ff654", "5d901b2c-7cd1-416e-9952-d30b6a0edcba", "4a3c5731-0050-4489-8364-282278f7190f", ) ) staged_files = form_field.to_python(uuid_string) assert ",".join(str(sf.uuid) for sf in staged_files) == uuid_string with pytest.raises(ValidationError): form_field.to_python("asdfasdfsdafasdf") other_string = uuid_string[10:] with pytest.raises(ValidationError): form_field.to_python(other_string)
class UploadRawImagesForm(forms.ModelForm): files = UploadedAjaxFileList( widget=upload_raw_files_widget, label="Image files", help_text=( 'Upload images for creating a new archive' ), ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper() self.helper.add_input(Submit("save", "Submit")) def save(self, commit=True): instance = super().save(commit=False) # Create links between the created session and all uploaded files uploaded_files = self.cleaned_data[ "files"] # type: List[StagedAjaxFile] raw_files = [ RawImageFile( upload_session=instance, filename=uploaded_file.name, staged_file_id=uploaded_file.uuid, ) for uploaded_file in uploaded_files ] if commit: with transaction.atomic(): instance.save() RawImageFile.objects.bulk_create(raw_files) return instance class Meta: model = RawImageUploadSession fields = ['files']
class UploadForm(forms.Form): title = forms.CharField(label="Blah") something = forms.CharField(label="Blabl") upload_form = UploadedAjaxFileList(widget=test_upload_widget) upload_form2 = UploadedAjaxFileList(widget=test_upload_widget2)
class SubmissionForm(forms.ModelForm): chunked_upload = UploadedAjaxFileList( widget=uploader.AjaxUploadWidget(multifile=False, auto_commit=False), label="Predictions File", validators=[ExtensionValidator(allowed_extensions=(".zip", ".csv"))], ) algorithm = ModelChoiceField( queryset=None, help_text=format_lazy( "Select one of your algorithms to submit as a solution to this " "challenge. If you have not created your algorithm yet you can " "do so <a href={}>on this page</a>.", reverse_lazy("algorithms:create"), ), ) def __init__( self, *args, user, algorithm_submission=False, display_comment_field=False, supplementary_file_choice=Config.OFF, supplementary_file_label="", supplementary_file_help_text="", publication_url_choice=Config.OFF, **kwargs, ): """ Conditionally render the comment field based on the display_comment_field kwarg """ super().__init__(*args, **kwargs) if not display_comment_field: del self.fields["comment"] if supplementary_file_label: self.fields["supplementary_file"].label = supplementary_file_label if supplementary_file_help_text: self.fields[ "supplementary_file"].help_text = supplementary_file_help_text if supplementary_file_choice == Config.REQUIRED: self.fields["supplementary_file"].required = True elif supplementary_file_choice == Config.OFF: del self.fields["supplementary_file"] if publication_url_choice == Config.REQUIRED: self.fields["publication_url"].required = True elif publication_url_choice == Config.OFF: del self.fields["publication_url"] if algorithm_submission: del self.fields["chunked_upload"] self.fields["algorithm"].queryset = get_objects_for_user( user, f"{Algorithm._meta.app_label}.change_{Algorithm._meta.model_name}", Algorithm, ).order_by("title") else: del self.fields["algorithm"] self.fields["chunked_upload"].widget.user = user self.helper = FormHelper(self) self.helper.layout.append(Submit("save", "Save")) def clean_algorithm(self): algorithm = self.cleaned_data["algorithm"] if algorithm.latest_ready_image is None: raise ValidationError( "This algorithm does not have a usable container image. " "Please add one and try again.") return algorithm class Meta: model = Submission fields = submission_fields
class UploadRawImagesForm(forms.ModelForm): files = UploadedAjaxFileList( widget=uploader.AjaxUploadWidget(multifile=True, auto_commit=False), label="Image files", help_text=( "The total size of all files uploaded in a single session " "cannot exceed 10 GB.<br>" "The following file formats are supported: " ".mha, .mhd, .raw, .zraw, .dcm, .nii, .nii.gz, " ".tiff, .png, .jpeg and .jpg.<br>" "The following file formats can be uploaded and will be converted to " "tif: Aperio(.svs), Hamamatsu(.vms, .vmu, .ndpi), Leica(.scn), MIRAX" "(.mrxs) and Ventana(.bif)." ), ) def __init__(self, *args, user, linked_task=None, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper() self.helper.add_input(Submit("save", "Submit")) self.fields["files"].widget.user = user self._linked_task = linked_task def clean_files(self): files = self.cleaned_data["files"] if len({f.name for f in files}) != len(files): raise ValidationError("Filenames must be unique.") if sum([f.size for f in files]) > settings.UPLOAD_SESSION_MAX_BYTES: raise ValidationError( "Total size of all files exceeds the upload limit." ) return files def save(self, commit=True): instance = super().save(commit=False) # type: RawImageUploadSession # Create links between the created session and all uploaded files uploaded_files = self.cleaned_data[ "files" ] # type: List[StagedAjaxFile] raw_files = [ RawImageFile( upload_session=instance, filename=uploaded_file.name, staged_file_id=uploaded_file.uuid, ) for uploaded_file in uploaded_files ] if commit: instance.save() RawImageFile.objects.bulk_create(raw_files) instance.process_images(linked_task=self._linked_task) return instance class Meta: model = RawImageUploadSession fields = ["files"]
def test_form_field_prepare_value_not_implemented(): form_field = UploadedAjaxFileList() assert form_field.prepare_value("") is None
class SubmissionForm(forms.ModelForm): chunked_upload = UploadedAjaxFileList( widget=uploader.AjaxUploadWidget(multifile=False, auto_commit=False), label="Predictions File", validators=[ExtensionValidator(allowed_extensions=(".zip", ".csv"))], ) algorithm = ModelChoiceField( queryset=None, help_text=format_lazy( "Select one of your algorithms to submit as a solution to this " "challenge. If you have not created your algorithm yet you can " "do so <a href={}>on this page</a>.", reverse_lazy("algorithms:create"), ), ) def __init__( self, *args, user, creator_must_be_verified=False, algorithm_submission=False, display_comment_field=False, supplementary_file_choice=Phase.OFF, supplementary_file_label="", supplementary_file_help_text="", publication_url_choice=Phase.OFF, **kwargs, ): """ Conditionally render the comment field based on the display_comment_field kwarg """ super().__init__(*args, **kwargs) self.creator_must_be_verified = creator_must_be_verified if not display_comment_field: del self.fields["comment"] if supplementary_file_label: self.fields["supplementary_file"].label = supplementary_file_label if supplementary_file_help_text: self.fields[ "supplementary_file"].help_text = supplementary_file_help_text if supplementary_file_choice == Phase.REQUIRED: self.fields["supplementary_file"].required = True elif supplementary_file_choice == Phase.OFF: del self.fields["supplementary_file"] if publication_url_choice == Phase.REQUIRED: self.fields["publication_url"].required = True elif publication_url_choice == Phase.OFF: del self.fields["publication_url"] if algorithm_submission: del self.fields["chunked_upload"] self.fields["algorithm"].queryset = get_objects_for_user( user, f"{Algorithm._meta.app_label}.change_{Algorithm._meta.model_name}", Algorithm, ).order_by("title") else: del self.fields["algorithm"] self.fields["chunked_upload"].widget.user = user self.fields["creator"].queryset = get_user_model().objects.filter( pk=user.pk) self.fields["creator"].initial = user self.helper = FormHelper(self) self.helper.layout.append(Submit("save", "Save")) def clean_algorithm(self): algorithm = self.cleaned_data["algorithm"] if algorithm.latest_ready_image is None: raise ValidationError( "This algorithm does not have a usable container image. " "Please add one and try again.") return algorithm def clean_creator(self): creator = self.cleaned_data["creator"] try: user_is_verified = creator.verification.is_verified except ObjectDoesNotExist: user_is_verified = False if self.creator_must_be_verified and not user_is_verified: error_message = format_html( "You must verify your account before you can make a " "submission to this phase. Please " '<a href="{}"> request verification here</a>.', reverse("verifications:create"), ) # Add this to the non-field errors as we use a HiddenInput self.add_error(None, error_message) raise ValidationError(error_message) return creator class Meta: model = Submission fields = submission_fields widgets = {"creator": forms.HiddenInput}