diff --git a/src/InSillyCloWeb/assemblies/forms.py b/src/InSillyCloWeb/assemblies/forms.py index 28224af3257c487db045c2a47351179792c11e16..98ebeb33b5eb53e70877751e65b0930e23160b9b 100644 --- a/src/InSillyCloWeb/assemblies/forms.py +++ b/src/InSillyCloWeb/assemblies/forms.py @@ -1,3 +1,4 @@ +import insillyclo.main from crispy_forms import layout from crispy_forms.helper import FormHelper from django import forms @@ -5,7 +6,7 @@ from django.forms import modelformset_factory from django.utils.safestring import mark_safe from django.utils.translation import gettext as _ -from assemblies.models import Assembly, InputPart +from assemblies.models import Assembly, InputPart, SimulatorJob SEP_CHOICES = ( (".", "Dot"), @@ -54,6 +55,31 @@ class SimulatorDataForm(forms.Form): ) +class PCRModelForm(forms.ModelForm): + class Meta: + model = SimulatorJob + fields = ('pcr_pairs_str',) + + helper = FormHelper() + helper.form_tag = False + + primers_file = forms.FileField( + required=False, + label=_('Primers file'), + help_text=_('A CSV file where the header is \"primerId;sequence\".\nNote that the separator is \";\".'), + ) + + def save(self, commit=True): + instance: SimulatorJob = super().save(commit=commit) + if not commit or self.cleaned_data['primers_file'] is None: + return instance + output_fp = instance.job_dir / insillyclo.main.DEFAULT_CONCENTRATIONS_FILENAME + with open(output_fp, 'wb') as fh: + for chunk in self.cleaned_data['primers_file'].chunks(): + fh.write(chunk) + return instance + + class AssemblyForm(forms.ModelForm): class Meta: model = Assembly diff --git a/src/InSillyCloWeb/assemblies/urls.py b/src/InSillyCloWeb/assemblies/urls.py index 19009a2781aac39b25f9c3362be25c42cdeee920..ea702e2330cdc9932429155e93ea729ea9998a76 100644 --- a/src/InSillyCloWeb/assemblies/urls.py +++ b/src/InSillyCloWeb/assemblies/urls.py @@ -68,6 +68,7 @@ urlpatterns = [ path('assembly-simulator/create/<str:step>/', simulator_wizard, name='simulator-create-step'), path('assembly-simulator/create/', simulator_wizard, name='simulator-create'), path('assembly-simulator/<slug:uuid>/', views.JobSimulatorResult.as_view(), name='simulator-detail'), + path('assembly-simulator-job/<slug:uuid>/pcr/', views.JobPCREdit.as_view(), name='simulator-pcr-edit'), path('assembly/<int:pk>/download/', views.AssemblyDetailDownloadView.as_view(), name='assembly-download'), path('assembly/<int:pk>/delete/', views.AssemblyDeleteView.as_view(), name='assembly-delete'), path('fragment', views.show_fragment, name='fragment'), diff --git a/src/InSillyCloWeb/assemblies/views.py b/src/InSillyCloWeb/assemblies/views.py index c680c2613e2bed6c6b34d69243272cf0f5b298e2..3789e53cc8856e209c99d717ea66348ddf0b3c8f 100644 --- a/src/InSillyCloWeb/assemblies/views.py +++ b/src/InSillyCloWeb/assemblies/views.py @@ -7,7 +7,7 @@ from django.http import HttpResponse from django.shortcuts import render, redirect from django.urls import reverse_lazy from django.utils.translation import gettext_lazy as _ -from django.views.generic import ListView, DetailView, View, DeleteView +from django.views.generic import ListView, DetailView, View, DeleteView, UpdateView from django.views.generic.detail import SingleObjectMixin from . import mixins @@ -114,3 +114,23 @@ class JobSimulatorResult(DetailView): model = models.SimulatorJob slug_field = 'uuid' slug_url_kwarg = 'uuid' + + +class JobPCREdit( + UpdateView, +): + model = models.SimulatorJob + form_class = forms.PCRModelForm + slug_field = 'uuid' + slug_url_kwarg = 'uuid' + success_url = reverse_lazy("assemblies:home") + template_name = "assemblies/form_host.html" + + def form_valid(self, form): + self.object.run_simulator() + return super().form_valid(form) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["title"] = _("PCR primers to use for gel simulation") + return context