more rapid merging/fixing

This commit is contained in:
Ross
2021-01-18 13:40:28 +00:00
parent 508934f94c
commit 542e559ed1
7 changed files with 216 additions and 150 deletions
@@ -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),
),
]
+1
View File
@@ -32,6 +32,7 @@ ALLOWED_HOSTS = ["localhost", "127.0.0.1", "161.35.163.87", "penracourses.org.uk
INSTALLED_APPS = [ INSTALLED_APPS = [
'anatomy', 'anatomy',
'physics', 'physics',
'rapids',
"reversion", "reversion",
"django_tables2", "django_tables2",
"django_filters", "django_filters",
+2 -2
View File
@@ -1,6 +1,6 @@
from django.contrib import admin from django.contrib import admin
from .models import Rapid, RapidImage, Examination, Site, Abnormality, Region, Note, RapidCreationDefault from .models import Rapid, RapidImage, Examination, Site, Abnormality, Region, Note, RapidCreationDefault
import tagulous.admin #import tagulous.admin
from django.forms import ModelForm from django.forms import ModelForm
@@ -30,7 +30,7 @@ class RapidAdminForm(ModelForm):
fields = [ fields = [
"normal", "abnormality", "region", "laterality", "examination", "normal", "abnormality", "region", "laterality", "examination",
"condition", "sign", "site", "feedback", "author" "site", "feedback", "author"
] ]
widgets = { widgets = {
+1 -1
View File
@@ -82,7 +82,7 @@ class RapidForm(ModelForm):
#fields = '__all__' #fields = '__all__'
fields = [ fields = [
"normal", "abnormality", "region", "laterality", "examination", "normal", "abnormality", "region", "laterality", "examination",
"condition", "sign", "site", "feedback" "site", "feedback"
] ]
#fields = ['question', 'feedback', 'subspecialty', 'references'] #fields = ['question', 'feedback', 'subspecialty', 'references']
widgets = { widgets = {
+122
View File
@@ -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')),
],
),
]
+67 -144
View File
@@ -24,12 +24,6 @@ def image_directory_path(instance, filename):
return u"picture/{0}".format(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): class Abnormality(models.Model):
name = models.CharField(max_length=200, name = models.CharField(max_length=200,
@@ -80,7 +74,7 @@ class Site(models.Model):
class Answer(models.Model): class Answer(models.Model):
question = models.ForeignKey( 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 = models.TextField(max_length=500)
answer_compare = models.TextField(max_length=500) answer_compare = models.TextField(max_length=500)
@@ -148,15 +142,15 @@ class Rapid(models.Model):
choices=LATERALITY_CHOICES, choices=LATERALITY_CHOICES,
default=NONE, default=NONE,
help_text="Applies to the answer, not the examination") help_text="Applies to the answer, not the examination")
condition = tagulous.models.TagField( # condition = tagulous.models.TagField(
to=Condition, # to=Condition,
blank=True, # blank=True,
help_text= # help_text=
"Associated condition. Will allow searching / filtering and tips / hints to be displayed. Conditions with spaces must be enclosed in quotes \"...\"" # "Associated condition. Will allow searching / filtering and tips / hints to be displayed. Conditions with spaces must be enclosed in quotes \"...\""
) # )
#
sign = tagulous.models.TagField( # sign = tagulous.models.TagField(
to=Sign, blank=True, help_text='Radiological signs in the question') # to=Sign, blank=True, help_text='Radiological signs in the question')
DEFAULT_SITE_ID = 1 DEFAULT_SITE_ID = 1
site = models.ManyToManyField( site = models.ManyToManyField(
@@ -206,134 +200,6 @@ class Rapid(models.Model):
lat = self.laterality lat = self.laterality
return "{} / {} {}".format(exams, lat, n) 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(
'<img src="{}{}" class="admin-rapid-image" /><span class="admin-rapid-image-info">Click and hold to zoom<span>'
.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): def GetPrimaryAnswer(self):
if len(self.answers.all()) > 0: if len(self.answers.all()) > 0:
return self.answers.all().first().answer return self.answers.all().first().answer
@@ -387,3 +253,60 @@ class AnatomyQuestion(models.Model):
marked_answers = correct_answers | half_mark_answers | incorrect_answers marked_answers = correct_answers | half_mark_answers | incorrect_answers
return marked_answers 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(
'<img src="{}{}" class="admin-rapid-image" /><span class="admin-rapid-image-info">Click and hold to zoom<span>'
.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')
+2 -2
View File
@@ -9,10 +9,10 @@
<link rel="stylesheet" href="{% static 'tagulous/lib/select2-3/select2.css' %}"> <link rel="stylesheet" href="{% static 'tagulous/lib/select2-3/select2.css' %}">
<link rel="stylesheet" href="{% static 'css/sbas.css' %}"> <link rel="stylesheet" href="{% static 'css/sbas.css' %}">
<script src="{% static 'tagulous/lib/jquery.js' %}"></script> {% comment %} <script src="{% static 'tagulous/lib/jquery.js' %}"></script>
<script src="{% static 'tagulous/lib/select2-3/select2.min.js' %}"></script> <script src="{% static 'tagulous/lib/select2-3/select2.min.js' %}"></script>
<script src="{% static 'tagulous/tagulous.js' %}"></script> <script src="{% static 'tagulous/tagulous.js' %}"></script>
<script src="{% static 'tagulous/adaptor/select2-3.js' %}"></script> <script src="{% static 'tagulous/adaptor/select2-3.js' %}"></script> {% endcomment %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="{% static 'js/dwv/i18next.min.js' %}"></script> <script type="text/javascript" src="{% static 'js/dwv/i18next.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/dwv/dwv.min.js' %}"></script> <script type="text/javascript" src="{% static 'js/dwv/dwv.min.js' %}"></script>