From 542e559ed12a7b147e508dcfe6707c266375d30f Mon Sep 17 00:00:00 2001 From: Ross Date: Mon, 18 Jan 2021 13:40:28 +0000 Subject: [PATCH] more rapid merging/fixing --- anatomy/migrations/0019_auto_20210118_1339.py | 20 ++ rad/settings.py | 1 + rapids/admin.py | 4 +- rapids/forms.py | 2 +- rapids/migrations/0001_initial.py | 122 ++++++++++ rapids/models.py | 213 ++++++------------ rapids/templates/rapids/base.html | 4 +- 7 files changed, 216 insertions(+), 150 deletions(-) create mode 100644 anatomy/migrations/0019_auto_20210118_1339.py create mode 100644 rapids/migrations/0001_initial.py diff --git a/anatomy/migrations/0019_auto_20210118_1339.py b/anatomy/migrations/0019_auto_20210118_1339.py new file mode 100644 index 00000000..779db910 --- /dev/null +++ b/anatomy/migrations/0019_auto_20210118_1339.py @@ -0,0 +1,20 @@ +# Generated by Django 3.1.2 on 2021-01-18 13:39 + +import anatomy.models +import django.core.files.storage +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('anatomy', '0018_auto_20210112_1726'), + ] + + operations = [ + migrations.AlterField( + model_name='anatomyquestion', + name='image', + field=models.ImageField(storage=django.core.files.storage.FileSystemStorage(base_url='/media/anatomy/', location='/home/ross/sites/rad/media//anatomy/'), upload_to=anatomy.models.image_directory_path), + ), + ] diff --git a/rad/settings.py b/rad/settings.py index 9b4aff1b..bb1647df 100644 --- a/rad/settings.py +++ b/rad/settings.py @@ -32,6 +32,7 @@ ALLOWED_HOSTS = ["localhost", "127.0.0.1", "161.35.163.87", "penracourses.org.uk INSTALLED_APPS = [ 'anatomy', 'physics', + 'rapids', "reversion", "django_tables2", "django_filters", diff --git a/rapids/admin.py b/rapids/admin.py index 2a2cd8b5..a00dba5e 100755 --- a/rapids/admin.py +++ b/rapids/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin from .models import Rapid, RapidImage, Examination, Site, Abnormality, Region, Note, RapidCreationDefault -import tagulous.admin +#import tagulous.admin from django.forms import ModelForm @@ -30,7 +30,7 @@ class RapidAdminForm(ModelForm): fields = [ "normal", "abnormality", "region", "laterality", "examination", - "condition", "sign", "site", "feedback", "author" + "site", "feedback", "author" ] widgets = { diff --git a/rapids/forms.py b/rapids/forms.py index 85c8278a..afcc2863 100755 --- a/rapids/forms.py +++ b/rapids/forms.py @@ -82,7 +82,7 @@ class RapidForm(ModelForm): #fields = '__all__' fields = [ "normal", "abnormality", "region", "laterality", "examination", - "condition", "sign", "site", "feedback" + "site", "feedback" ] #fields = ['question', 'feedback', 'subspecialty', 'references'] widgets = { diff --git a/rapids/migrations/0001_initial.py b/rapids/migrations/0001_initial.py new file mode 100644 index 00000000..6f3b1cc7 --- /dev/null +++ b/rapids/migrations/0001_initial.py @@ -0,0 +1,122 @@ +# Generated by Django 3.1.2 on 2021-01-18 13:39 + +from django.conf import settings +import django.core.files.storage +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import rapids.models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Abnormality', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(help_text='Primary abnormality on the film(s)', max_length=200, unique=True)), + ], + options={ + 'ordering': ('name',), + }, + ), + migrations.CreateModel( + name='Examination', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('examination', models.CharField(max_length=200)), + ], + options={ + 'ordering': ('examination',), + }, + ), + migrations.CreateModel( + name='Rapid', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('question', models.TextField(blank=True, null=True)), + ('feedback', models.TextField(blank=True, null=True)), + ('normal', models.BooleanField(default=False, help_text='Tick if true')), + ('laterality', models.CharField(choices=[('NONE', 'None'), ('LEFT', 'Left'), ('RIGHT', 'Right'), ('BILAT', 'Bilateral')], default='NONE', help_text='Applies to the answer, not the examination', max_length=20)), + ('verified', models.BooleanField(default=False)), + ('created_date', models.DateTimeField(default=django.utils.timezone.now)), + ('published_date', models.DateTimeField(blank=True, null=True)), + ('scrapped', models.BooleanField(default=False, help_text='Question has been scrapped and will not be shown')), + ('abnormality', models.ManyToManyField(blank=True, help_text='The abnormality (laterality and region independent)', to='rapids.Abnormality')), + ('author', models.ManyToManyField(blank=True, help_text='Author of question', related_name='rapid_authored_questions', to=settings.AUTH_USER_MODEL)), + ('examination', models.ManyToManyField(help_text='Name of the (primary) examination', to='rapids.Examination')), + ], + ), + migrations.CreateModel( + name='Region', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(blank=True, help_text='Region of the abnormality (not including lateralitiy)', max_length=200, unique=True)), + ], + options={ + 'ordering': ('name',), + }, + ), + migrations.CreateModel( + name='Site', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('site', models.CharField(max_length=200)), + ('initials', models.CharField(max_length=200)), + ], + ), + migrations.CreateModel( + name='RapidImage', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('image', models.ImageField(storage=django.core.files.storage.FileSystemStorage(base_url='/media/rapids/', location='/home/ross/sites/rad/media//rapids/'), upload_to=rapids.models.image_directory_path)), + ('feedback_image', models.BooleanField(default=False)), + ('rapid', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='images', to='rapids.rapid')), + ], + ), + migrations.CreateModel( + name='RapidCreationDefault', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('author', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='rapid_default', to=settings.AUTH_USER_MODEL)), + ('site', models.ManyToManyField(blank=True, default=1, help_text='Default site to use when creating a new rapid', to='rapids.Site')), + ], + ), + migrations.AddField( + model_name='rapid', + name='region', + field=models.ManyToManyField(blank=True, help_text='Region of the abnormality (laterality independent)', to='rapids.Region'), + ), + migrations.AddField( + model_name='rapid', + name='site', + field=models.ManyToManyField(blank=True, default=1, help_text='If we know the source of the image (should possibly be removed?)', to='rapids.Site'), + ), + migrations.CreateModel( + name='Note', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('note', models.TextField()), + ('created_on', models.DateTimeField(auto_now_add=True)), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='rapid_notes', to=settings.AUTH_USER_MODEL)), + ('rapid', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='rapid_notes', to='rapids.rapid')), + ], + ), + migrations.CreateModel( + name='Answer', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('answer', models.TextField(max_length=500)), + ('answer_compare', models.TextField(max_length=500)), + ('status', models.CharField(choices=[('', 'Unmarked'), ('0', 'Incorrect'), ('1', 'Half mark'), ('2', 'Correct')], default='', max_length=1)), + ('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='rapids.rapid')), + ], + ), + ] diff --git a/rapids/models.py b/rapids/models.py index ddd997d0..0a07d1da 100644 --- a/rapids/models.py +++ b/rapids/models.py @@ -24,12 +24,6 @@ def image_directory_path(instance, filename): return u"picture/{0}".format(filename) -class AnswerStrings(models.Model): - text = models.CharField(max_length=255, unique=True) - - def __str__(self): - return self.text - class Abnormality(models.Model): name = models.CharField(max_length=200, @@ -80,7 +74,7 @@ class Site(models.Model): class Answer(models.Model): question = models.ForeignKey( - Rapid, related_name="answers", on_delete=models.CASCADE + "Rapid", related_name="answers", on_delete=models.CASCADE ) answer = models.TextField(max_length=500) answer_compare = models.TextField(max_length=500) @@ -148,15 +142,15 @@ class Rapid(models.Model): choices=LATERALITY_CHOICES, default=NONE, help_text="Applies to the answer, not the examination") - condition = tagulous.models.TagField( - to=Condition, - blank=True, - help_text= - "Associated condition. Will allow searching / filtering and tips / hints to be displayed. Conditions with spaces must be enclosed in quotes \"...\"" - ) - - sign = tagulous.models.TagField( - to=Sign, blank=True, help_text='Radiological signs in the question') +# condition = tagulous.models.TagField( +# to=Condition, +# blank=True, +# help_text= +# "Associated condition. Will allow searching / filtering and tips / hints to be displayed. Conditions with spaces must be enclosed in quotes \"...\"" +# ) +# +# sign = tagulous.models.TagField( +# to=Sign, blank=True, help_text='Radiological signs in the question') DEFAULT_SITE_ID = 1 site = models.ManyToManyField( @@ -206,134 +200,6 @@ class Rapid(models.Model): lat = self.laterality return "{} / {} {}".format(exams, lat, n) - -class RapidImage(models.Model): - rapid = models.ForeignKey(Rapid, - related_name="images", - on_delete=models.CASCADE) - image = models.ImageField(upload_to=image_directory_path, storage=image_storage) - - feedback_image = models.BooleanField(default=False) - - def image_tag(self): - if self.image: - return mark_safe( - 'Click and hold to zoom' - .format(settings.MEDIA_URL, self.image)) - else: - return "" - - image_tag.short_description = 'Image' - - -class Note(models.Model): - rapid = models.ForeignKey(Rapid, - related_name="rapid_notes", - on_delete=models.CASCADE, - null=True) - author = models.ForeignKey(User, - related_name="rapid_notes", - on_delete=models.CASCADE) - note = models.TextField() - created_on = models.DateTimeField(auto_now_add=True) - - def get_absolute_url(self): - self.pk = self.rapid_id - return reverse('rapids:rapid_detail', kwargs={'pk': self.pk}) - - def __str__(self): - return "{} [{}] {}".format(self.rapid, self.author, self.created_on) - - -class RapidCreationDefault(models.Model): - author = models.OneToOneField(User, - related_name="rapid_default", - on_delete=models.CASCADE) - - site = models.ManyToManyField( - Site, - blank=True, - default=1, - help_text="Default site to use when creating a new rapid") - - def get_absolute_url(self): - return reverse('rapids:rapid_create') - - -class AnatomyQuestion(models.Model): - # author = models.ForeignKey('auth.User', on_delete=models.CASCADE) - # image = models.ImageField() - # feedback = models.TextField(null=True) - question_type = models.ForeignKey( - QuestionType, on_delete=models.SET_NULL, null=True - ) - - image = models.ImageField(upload_to=image_directory_path, storage=image_storage) - - image_annotations = models.TextField( - blank=True, - help_text="Stores a JSON representation of annotations to be applied by cornerstonetools", - ) - - description = models.CharField( - max_length=400, - help_text="Short description of the image e.g. 'Sagittal CT Chest, Abdomen & Pelvis', will be displayed as the title.", - ) - - examination = models.ForeignKey( - Examination, on_delete=models.SET_NULL, null=True, blank=True - ) - modality = models.ForeignKey( - Modality, - on_delete=models.SET_NULL, - null=True, - help_text="Modality of the image", - ) - region = models.ForeignKey( - Region, - on_delete=models.SET_NULL, - null=True, - blank=True, - help_text="Region the image covers", - ) - body_part = models.ForeignKey( - BodyPart, on_delete=models.SET_NULL, null=True, blank=True - ) - structure = models.ForeignKey( - Structure, on_delete=models.SET_NULL, null=True, blank=True - ) - created_date = models.DateTimeField(default=timezone.now) - - open_access = models.BooleanField( - help_text="If an question should be freely available to browse", default=True - ) - - author = models.ManyToManyField( - settings.AUTH_USER_MODEL, - blank=True, - help_text="Author(s) of question", - related_name="anatomy_authored_questions", - ) - - def __str__(self): - # Get first answer - return "{} [{}, {}]".format( - self.GetPrimaryAnswer(), self.modality, self.structure - ) - # Get associated exams - e = self.exams.all().values_list("name", flat=True) - exams = ", ".join(e) - - if a is None: - return "({})".format(exams) - else: - return "{} ({}) [{}, {}]".format( - a.answer, exams, self.modality, self.structure - ) - - def get_absolute_url(self): - return reverse("anatomy:question_detail", kwargs={"pk": self.pk}) - def GetPrimaryAnswer(self): if len(self.answers.all()) > 0: return self.answers.all().first().answer @@ -386,4 +252,61 @@ class AnatomyQuestion(models.Model): ) marked_answers = correct_answers | half_mark_answers | incorrect_answers - return marked_answers \ No newline at end of file + return marked_answers + + +class RapidImage(models.Model): + rapid = models.ForeignKey(Rapid, + related_name="images", + on_delete=models.CASCADE) + image = models.ImageField(upload_to=image_directory_path, storage=image_storage) + + feedback_image = models.BooleanField(default=False) + + def image_tag(self): + if self.image: + return mark_safe( + 'Click and hold to zoom' + .format(settings.MEDIA_URL, self.image)) + else: + return "" + + image_tag.short_description = 'Image' + + +class Note(models.Model): + rapid = models.ForeignKey(Rapid, + related_name="rapid_notes", + on_delete=models.CASCADE, + null=True) + #author = models.ForeignKey(User, + author = models.ForeignKey( settings.AUTH_USER_MODEL, + related_name="rapid_notes", + on_delete=models.CASCADE) + note = models.TextField() + created_on = models.DateTimeField(auto_now_add=True) + + def get_absolute_url(self): + self.pk = self.rapid_id + return reverse('rapids:rapid_detail', kwargs={'pk': self.pk}) + + def __str__(self): + return "{} [{}] {}".format(self.rapid, self.author, self.created_on) + + +class RapidCreationDefault(models.Model): + #author = models.OneToOneField(User, + author = models.OneToOneField( + settings.AUTH_USER_MODEL, + related_name="rapid_default", + on_delete=models.CASCADE) + + site = models.ManyToManyField( + Site, + blank=True, + default=1, + help_text="Default site to use when creating a new rapid") + + def get_absolute_url(self): + return reverse('rapids:rapid_create') + diff --git a/rapids/templates/rapids/base.html b/rapids/templates/rapids/base.html index e762e551..e8ad97c7 100755 --- a/rapids/templates/rapids/base.html +++ b/rapids/templates/rapids/base.html @@ -9,10 +9,10 @@ - + {% comment %} - + {% endcomment %}