diff --git a/atlas/admin.py b/atlas/admin.py index 8a20b028..c48bf68c 100755 --- a/atlas/admin.py +++ b/atlas/admin.py @@ -1,5 +1,13 @@ from django.contrib import admin -from .models import Case, Series, SeriesImage, Condition, Subspecialty, Finding, SeriesFindings +from .models import ( + Case, + Series, + SeriesImage, + Condition, + Subspecialty, + Finding, + SeriesFinding, +) import tagulous.admin @@ -20,7 +28,7 @@ admin.site.register(SeriesImage) admin.site.register(Condition) admin.site.register(Subspecialty) admin.site.register(Finding) -admin.site.register(SeriesFindings) +admin.site.register(SeriesFinding) class AtlasAdminForm(ModelForm): @@ -31,7 +39,7 @@ class AtlasAdminForm(ModelForm): "description", "history", "sign", - #"findings", + # "findings", "author", "series", ] @@ -40,8 +48,8 @@ class AtlasAdminForm(ModelForm): # "normal": RadioSelect( # choices=[(True, 'Yes'), # (False, 'No')]) - #"findings": TinyMCE(attrs={"cols": 80, "rows": 30}), - #"mark_scheme": TinyMCE(attrs={"cols": 80, "rows": 30}), + # "findings": TinyMCE(attrs={"cols": 80, "rows": 30}), + # "mark_scheme": TinyMCE(attrs={"cols": 80, "rows": 30}), } diff --git a/atlas/forms.py b/atlas/forms.py index 50382b35..27ca6338 100755 --- a/atlas/forms.py +++ b/atlas/forms.py @@ -8,12 +8,7 @@ from django.forms import ( ) from django.forms import inlineformset_factory -from atlas.models import ( - Case, - Series, - SeriesImage, - SeriesFindings -) +from atlas.models import Case, Series, SeriesImage, SeriesFinding from anatomy.models import Modality @@ -33,9 +28,9 @@ class ExaminationForm(ModelForm): fields = ["examination"] -class SeriesFindingsForm(ModelForm): +class SeriesFindingForm(ModelForm): class Meta: - model = SeriesFindings + model = SeriesFinding exclude = ["series", "annotation_json"] def __init__(self, *args, **kwargs): @@ -47,10 +42,11 @@ class SeriesFindingsForm(ModelForm): # a list of primary key for the selected data. initial["series"] = kwargs.pop("series_id") - super(SeriesFindingsForm, self).__init__(*args, **kwargs) + super(SeriesFindingForm, self).__init__(*args, **kwargs) ModelForm.__init__(self, *args, **kwargs) + class SeriesForm(ModelForm): class Media: # Django also includes a few javascript files necessary @@ -163,9 +159,9 @@ class CaseForm(ModelForm): "subspecialty", "description", "history", - #"findings", + # "findings", "condition", - #"sign", + # "sign", "open_access", ] # fields = ['question', 'findings', 'subspecialty', 'references'] @@ -173,8 +169,8 @@ class CaseForm(ModelForm): # "normal": RadioSelect( # choices=[(True, 'Yes'), # (False, 'No')]) - #"findings": TinyMCE(attrs={"cols": 80, "rows": 20}), - #"mark_scheme": TinyMCE(attrs={"cols": 80, "rows": 30}), + # "findings": TinyMCE(attrs={"cols": 80, "rows": 20}), + # "mark_scheme": TinyMCE(attrs={"cols": 80, "rows": 30}), "description": Textarea(attrs={"cols": 80, "rows": 5}), "history": Textarea(attrs={"cols": 80, "rows": 5}), } diff --git a/atlas/migrations/0007_auto_20211128_1622.py b/atlas/migrations/0007_auto_20211128_1622.py index 5305a9e1..681878bf 100644 --- a/atlas/migrations/0007_auto_20211128_1622.py +++ b/atlas/migrations/0007_auto_20211128_1622.py @@ -8,42 +8,80 @@ import django.db.models.deletion class Migration(migrations.Migration): dependencies = [ - ('atlas', '0006_auto_20211128_1448'), + ("atlas", "0006_auto_20211128_1448"), ] operations = [ migrations.CreateModel( - name='Finding', + name="Finding", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=255)), - ('primary_name', models.BooleanField(default='True')), - ('synonym', models.ManyToManyField(blank=True, related_name='_atlas_finding_synonym_+', to='atlas.Finding')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=255)), + ("primary_name", models.BooleanField(default="True")), + ( + "synonym", + models.ManyToManyField( + blank=True, + related_name="_atlas_finding_synonym_+", + to="atlas.Finding", + ), + ), ], bases=(atlas.models.SynMixin, models.Model), ), migrations.RemoveField( - model_name='case', - name='findings', + model_name="case", + name="findings", ), migrations.AlterField( - model_name='case', - name='description', - field=models.TextField(blank=True, help_text='Description of the case'), + model_name="case", + name="description", + field=models.TextField(blank=True, help_text="Description of the case"), ), migrations.AlterField( - model_name='series', - name='description', - field=models.TextField(blank=True, help_text='Description of stack'), + model_name="series", + name="description", + field=models.TextField(blank=True, help_text="Description of stack"), ), migrations.CreateModel( - name='SeriesFindings', + name="SeriesFinding", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('description', models.TextField(blank=True, help_text='Findings on the series / stack', null=True)), - ('annotation_json', models.TextField(blank=True, null=True)), - ('findings', models.ManyToManyField(blank=True, to='atlas.Finding')), - ('series', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='findings', to='atlas.series')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "description", + models.TextField( + blank=True, + help_text="Findings on the series / stack", + null=True, + ), + ), + ("annotation_json", models.TextField(blank=True, null=True)), + ("findings", models.ManyToManyField(blank=True, to="atlas.Finding")), + ( + "series", + models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="findings", + to="atlas.series", + ), + ), ], ), ] diff --git a/atlas/models.py b/atlas/models.py index 88513a22..89dfe52f 100644 --- a/atlas/models.py +++ b/atlas/models.py @@ -73,8 +73,9 @@ def findMiddle(input_list): return input_list[int(middle)] return (input_list[int(middle)], input_list[int(middle - 1)]) + class SynMixin(object): - #class Meta: + # class Meta: # abstract = True def __str__(self) -> str: @@ -94,6 +95,7 @@ class Finding(SynMixin, models.Model): primary_name = models.BooleanField(default="True") + class Condition(SynMixin, models.Model): name = models.CharField(max_length=255) @@ -103,15 +105,17 @@ class Condition(SynMixin, models.Model): subspecialty = models.ManyToManyField("subspecialty", blank=True) + class Subspecialty(models.Model): name = models.CharField(max_length=255) def __str__(self) -> str: return self.name + @reversion.register class Case(models.Model): - #class SubspecialtyChoices(models.TextChoices): + # class SubspecialtyChoices(models.TextChoices): # BREAST = "BR", _("Breast") # CARDIAC = "CA", _("Cardiac") # GASTRO = "GI", _("Gastrointestinal and hepatobiliary") @@ -134,9 +138,9 @@ class Case(models.Model): history = models.TextField(null=True, blank=True) - #findings = models.TextField(null=True, blank=True) + # findings = models.TextField(null=True, blank=True) - #subspecialty = models.CharField(max_length=2, choices=SubspecialtyChoices.choices) + # subspecialty = models.CharField(max_length=2, choices=SubspecialtyChoices.choices) subspecialty = models.ManyToManyField(Subspecialty, blank=True) condition = models.ManyToManyField(Condition, blank=True) @@ -205,18 +209,22 @@ class SeriesImage(models.Model): info = "File is not a dicom." return info -class SeriesFindings(models.Model): + +class SeriesFinding(models.Model): series = models.ForeignKey( "Series", related_name="findings", on_delete=models.SET_NULL, null=True ) - description = models.TextField(null=True, blank=True, help_text="Findings on the series / stack") + description = models.TextField( + null=True, blank=True, help_text="Findings on the series / stack" + ) findings = models.ManyToManyField(Finding, blank=True) annotation_json = models.TextField(null=True, blank=True) def __str__(self) -> str: return f"{self.series.id}/{self.description}" + @reversion.register class Series(models.Model): modality = models.ForeignKey( @@ -259,7 +267,7 @@ class Series(models.Model): related_name="series", ) - #findings = models.TextField(null=True, blank=True, help_text="Findings on the series / stack") + # findings = models.TextField(null=True, blank=True, help_text="Findings on the series / stack") open_access = models.BooleanField( help_text="If a question should be freely available to browse", default=True diff --git a/atlas/views.py b/atlas/views.py index 73a00e81..3a0d1af4 100755 --- a/atlas/views.py +++ b/atlas/views.py @@ -30,7 +30,7 @@ from .forms import ( SeriesImageFormSet, SeriesFormSet, ExaminationForm, - SeriesFindingsForm + SeriesFindingForm, ) from .models import ( Case, @@ -38,8 +38,8 @@ from .models import ( Examination, Finding, Subspecialty, - SeriesFindings, - SeriesImage + SeriesFinding, + SeriesImage, ) from .tables import AtlasTable, SeriesTable from .filters import AtlasFilter, SeriesFilter @@ -117,11 +117,14 @@ def series_detail(request, pk): # if request.user not in atlas.author.all(): # raise PermissionDenied - series_finding_form = SeriesFindingsForm(series_id=series.id) - + series_finding_form = SeriesFindingForm(series_id=series.id) # logging.debug(atlas.subspecialty.first().name.all()) - return render(request, "atlas/series.html", {"series": series, "series_finding_form": series_finding_form}) + return render( + request, + "atlas/series.html", + {"series": series, "series_finding_form": series_finding_form}, + ) @login_required @@ -516,28 +519,28 @@ class SeriesImagesZipView(SuperuserRequiredMixin, BaseZipView): return [i.image.file for i in series.images.all()] + def create_series_findings(request): - #posts = Post.objects.all() + # posts = Post.objects.all() response_data = {} - if request.POST.get('action') == 'post': - series_id = request.POST.get('series') - findings_ids = json.loads(request.POST.get('findings')) - description = request.POST.get('description') - annotation_json = json.loads(request.POST.get('annotation_json')) + if request.POST.get("action") == "post": + series_id = request.POST.get("series") + findings_ids = json.loads(request.POST.get("findings")) + description = request.POST.get("description") + annotation_json = json.loads(request.POST.get("annotation_json")) series = Series.objects.get(pk=series_id) findings = Finding.objects.filter(pk__in=findings_ids) - - sf = SeriesFindings.objects.create( - series = series, - description = description, - annotation_json = annotation_json, - ) + sf = SeriesFinding.objects.create( + series=series, + description=description, + annotation_json=annotation_json, + ) sf.findings.set(findings) sf.save() - return JsonResponse({"success":True}) + return JsonResponse({"success": True}) return JsonResponse({"success": False}) - return render(request, 'create_post.html', {'posts':posts}) \ No newline at end of file + return render(request, "create_post.html", {"posts": posts})