Compare commits
77
Commits
cd5cbdd1a5
...
297f8619b4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
297f8619b4 | ||
|
|
98a874f805 | ||
|
|
5759271751 | ||
|
|
a0b38f541a | ||
|
|
f6d7bd594a | ||
|
|
06f1e7852d | ||
|
|
48cba9353e | ||
|
|
fcd77514eb | ||
|
|
7a9b3177d7 | ||
|
|
a4e66696bd | ||
|
|
cc2cbde691 | ||
|
|
d4eda9fdfb | ||
|
|
9ae1874073 | ||
|
|
c3a735fa52 | ||
|
|
4aa4db5d01 | ||
|
|
f3c8fb5847 | ||
|
|
32b861f213 | ||
|
|
5e33d5f869 | ||
|
|
a435d82f52 | ||
|
|
671c6f9ca3 | ||
|
|
6ab1355919 | ||
|
|
522fa6bcb0 | ||
|
|
8ec7662015 | ||
|
|
2b679b6149 | ||
|
|
9b334085cd | ||
|
|
33414e9575 | ||
|
|
ce531e7030 | ||
|
|
2520fa7879 | ||
|
|
15ab98b682 | ||
|
|
c3e36bfb12 | ||
|
|
b36fa370f1 | ||
|
|
fdc0de29d3 | ||
|
|
bce3469676 | ||
|
|
f268f040e2 | ||
|
|
dd300afd63 | ||
|
|
e6469e70f0 | ||
|
|
9a5088c03a | ||
|
|
c799f106d7 | ||
|
|
15b6233802 | ||
|
|
f458dc1306 | ||
|
|
6b5c3f8914 | ||
|
|
1ade42d7ba | ||
|
|
100945478b | ||
|
|
abdba22cdf | ||
|
|
656f1658f8 | ||
|
|
09951286e2 | ||
|
|
dc195effc6 | ||
|
|
4e5c1c213d | ||
|
|
c9bbb5de50 | ||
|
|
be8f00566a | ||
|
|
6c1fd3ae2f | ||
|
|
154494e4b0 | ||
|
|
5ca1d5b44e | ||
|
|
c99fb5a3d6 | ||
|
|
5fbd4cd35e | ||
|
|
d1ba8c87dc | ||
|
|
e0f0c7619a | ||
|
|
cbe7257fe8 | ||
|
|
56cc23a8f2 | ||
|
|
4eb421bc33 | ||
|
|
796ec1a072 | ||
|
|
43c984d5aa | ||
|
|
d8c36b81d7 | ||
|
|
ff00047110 | ||
|
|
fef378a2ac | ||
|
|
afdc8e95c7 | ||
|
|
e0723d4d3a | ||
|
|
ac558b9ea2 | ||
|
|
ae670c738b | ||
|
|
4345f46615 | ||
|
|
56eb5f8230 | ||
|
|
4dc9fdcb8b | ||
|
|
8cd8e9226c | ||
|
|
664e29937d | ||
|
|
d05752b2dc | ||
|
|
7aa78c2807 | ||
|
|
525373f393 |
+2
-2
@@ -1,5 +1,5 @@
|
||||
# pull official base image
|
||||
FROM python:3.11.1-slim
|
||||
FROM python:3.11.3-slim
|
||||
|
||||
# set work directory
|
||||
WORKDIR /usr/src/rad
|
||||
@@ -13,7 +13,7 @@ ENV PYTHONUNBUFFERED 1
|
||||
# python3 python3-dev gcc \
|
||||
# gfortran musl-dev \
|
||||
# libffi-dev openssl-dev
|
||||
RUN apt-get update && apt-get -y install postgresql postgresql-contrib git
|
||||
RUN apt-get update && apt-get -y install postgresql postgresql-contrib git libcairo2-dev pkg-config gcc
|
||||
|
||||
|
||||
# install dependencies
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# Current target
|
||||
- User management
|
||||
- SQUASH MIGRATIONS
|
||||
|
||||
|
||||
# Ongoing
|
||||
@@ -13,4 +14,8 @@
|
||||
|
||||
# Future
|
||||
- Clean up user results / score pages
|
||||
- Remove external javascript dependencies
|
||||
- Remove external javascript dependencies
|
||||
|
||||
- Viva cases
|
||||
|
||||
- Update rapids for new style
|
||||
+3
-4
@@ -4,9 +4,9 @@ from .models import (
|
||||
#Examination,
|
||||
QuestionType,
|
||||
Answer,
|
||||
CidUserAnswer,
|
||||
UserAnswer,
|
||||
Exam,
|
||||
Modality,
|
||||
#Modality,
|
||||
Region,
|
||||
BodyPart,
|
||||
Structure,
|
||||
@@ -54,9 +54,8 @@ class ExamAdmin(VersionAdmin, admin.ModelAdmin):
|
||||
admin.site.register(AnatomyQuestion, AnatomyAdmin)
|
||||
#admin.site.register(Examination)
|
||||
admin.site.register(QuestionType)
|
||||
admin.site.register(CidUserAnswer)
|
||||
admin.site.register(UserAnswer)
|
||||
admin.site.register(Exam, ExamAdmin)
|
||||
admin.site.register(Modality)
|
||||
admin.site.register(Region)
|
||||
admin.site.register(BodyPart)
|
||||
admin.site.register(Structure)
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import django_filters
|
||||
|
||||
from .models import AnatomyQuestion, CidUserAnswer, Exam
|
||||
from .models import AnatomyQuestion, UserAnswer, Exam
|
||||
|
||||
#from generic.filters import UserAnswerFilter
|
||||
from django.contrib.auth.models import User
|
||||
@@ -48,7 +48,7 @@ class AnatomyQuestionFilter(django_filters.FilterSet):
|
||||
|
||||
class AnatomyUserAnswerFilter(django_filters.FilterSet):
|
||||
class Meta:
|
||||
model= CidUserAnswer
|
||||
model= UserAnswer
|
||||
fields = (
|
||||
"cid",
|
||||
"user",
|
||||
|
||||
+2
-2
@@ -12,7 +12,7 @@ from generic.forms import ExamAuthorFormMixin, ExamFormMixin
|
||||
|
||||
from .models import (
|
||||
Answer,
|
||||
CidUserAnswer,
|
||||
UserAnswer,
|
||||
AnatomyQuestion,
|
||||
# Examination,
|
||||
BodyPart,
|
||||
@@ -32,7 +32,7 @@ from dal import autocomplete
|
||||
|
||||
class AnatomyAnswerForm(ModelForm):
|
||||
class Meta:
|
||||
model = CidUserAnswer
|
||||
model = UserAnswer
|
||||
fields = ("answer",)
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
# Generated by Django 3.1.2 on 2020-10-16 19:07
|
||||
# Generated by Django 4.1.4 on 2023-06-12 10:07
|
||||
|
||||
import anatomy.models
|
||||
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
|
||||
@@ -21,9 +20,26 @@ class Migration(migrations.Migration):
|
||||
name='AnatomyQuestion',
|
||||
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='http://161.35.163.87//media/anatomy/', location='/home/ross/scripts/sites/rad/media//anatomy/'), upload_to=anatomy.models.image_directory_path)),
|
||||
('description', models.CharField(help_text="Short description of the image e.g. 'Sagittal CT Chest, Abdomen & Pelvis', will be displayed as the title.", max_length=400)),
|
||||
('authors_only', models.BooleanField(default=False, help_text='If true only question authors will be able to view.')),
|
||||
('created_date', models.DateTimeField(default=django.utils.timezone.now)),
|
||||
('open_access', models.BooleanField(default=True, help_text='If a question should be freely available to browse')),
|
||||
('feedback', models.TextField(blank=True, help_text='Question Feedback', null=True)),
|
||||
('image', models.ImageField(help_text="The image to use for the question. Ideally use use unmarked images and annotate (arrow) them on the test system. If you wish to reuse an image that is already uploaded 'clone' the question that contains it.", upload_to=anatomy.models.image_directory_path)),
|
||||
('image_annotations', models.TextField(blank=True, help_text='Stores a JSON representation of annotations to be applied by cornerstonetools')),
|
||||
('description', models.CharField(help_text="Short description of the image e.g. 'Sagittal CT Chest, Abdomen & Pelvis', will be displayed as the title.", max_length=400)),
|
||||
],
|
||||
options={
|
||||
'permissions': (),
|
||||
},
|
||||
),
|
||||
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)),
|
||||
('proposed', models.BooleanField(default=False)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
@@ -37,16 +53,32 @@ class Migration(migrations.Migration):
|
||||
name='Exam',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=200)),
|
||||
('exam_questions', models.ManyToManyField(related_name='exams', to='anatomy.AnatomyQuestion')),
|
||||
],
|
||||
),
|
||||
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)),
|
||||
('name', models.CharField(help_text='Name of the exam', max_length=200)),
|
||||
('active', models.BooleanField(default=False, help_text='If an exam should be available to take')),
|
||||
('exam_mode', models.BooleanField(default=False, help_text='If an exam should be taken in exam mode (users results will be submited to the server for marking)')),
|
||||
('include_history', models.BooleanField(default=False, help_text='If an exam should include history when taking')),
|
||||
('publish_results', models.BooleanField(default=False, help_text='If an exams results should be available')),
|
||||
('recreate_json', models.BooleanField(default=False, help_text='If the json cache needs updating')),
|
||||
('json_creation_time', models.DateTimeField(blank=True, default=None, null=True)),
|
||||
('exam_json_id', models.IntegerField(default=1, help_text='auto incrementing field when json recreated')),
|
||||
('archive', models.BooleanField(default=False, help_text='Archived exams will remain on the test system but will not be displayed by default')),
|
||||
('open_access', models.BooleanField(default=False, help_text='If the exam is freely accessible (to view and edit on the test system)')),
|
||||
('authors_only', models.BooleanField(default=False, help_text='If true only exam authors will be able to view.')),
|
||||
('stats_mean', models.FloatField(default=0)),
|
||||
('stats_mode', models.CharField(default=0, max_length=25)),
|
||||
('stats_median', models.FloatField(default=0)),
|
||||
('stats_candidates', models.FloatField(default=0)),
|
||||
('stats_min', models.FloatField(default=0)),
|
||||
('stats_max', models.FloatField(default=0)),
|
||||
('stats_max_possible', models.FloatField(default=0)),
|
||||
('user_scores', models.JSONField(default=dict)),
|
||||
('exam_results_emailed', models.DateTimeField(default=None, null=True)),
|
||||
('time_limit', models.IntegerField(default=5400, help_text='Exam time limit (in seconds)')),
|
||||
('author', models.ManyToManyField(blank=True, help_text='Author of exam', related_name='anatomy_exam_author', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Modality',
|
||||
@@ -62,86 +94,37 @@ class Migration(migrations.Migration):
|
||||
('text', models.CharField(max_length=400)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Region',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('region', models.CharField(max_length=200)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Structure',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('bodypart', models.CharField(max_length=200)),
|
||||
('structure', models.CharField(max_length=200, unique=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='UserAnswer',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('answer', models.CharField(blank=True, max_length=500)),
|
||||
('cid', models.IntegerField(blank=True, null=True)),
|
||||
('flagged', models.BooleanField(default=False)),
|
||||
('created', models.DateTimeField(auto_now_add=True)),
|
||||
('updated', models.DateTimeField(auto_now=True)),
|
||||
('exam', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='exam', to='anatomy.exam')),
|
||||
('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user_answers', to='anatomy.anatomyquestion')),
|
||||
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='IncorrectAnswers',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('answer', models.CharField(max_length=500)),
|
||||
('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='incorrect_answers', to='anatomy.anatomyquestion')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='HalfMarkAnswers',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('answer', models.CharField(max_length=500)),
|
||||
('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='half_mark_answers', to='anatomy.anatomyquestion')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='CidUserAnswer',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('answer', models.CharField(blank=True, max_length=500)),
|
||||
('cid', models.IntegerField(blank=True, null=True)),
|
||||
('cid', models.BigIntegerField(blank=True, help_text='Candidate ID (limitied by BigIntegerField size)', null=True)),
|
||||
('created', models.DateTimeField(auto_now_add=True)),
|
||||
('updated', models.DateTimeField(auto_now=True)),
|
||||
('answer', models.TextField(blank=True, max_length=500)),
|
||||
('answer_compare', models.TextField(blank=True, max_length=500)),
|
||||
('score', models.CharField(blank=True, choices=[('', 'Unmarked'), ('0', 'Incorrect'), ('1', 'Half mark'), ('2', 'Correct')], default='', max_length=1)),
|
||||
('exam', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cid_user_answers', to='anatomy.exam')),
|
||||
('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='cid_user_answers', to='anatomy.anatomyquestion')),
|
||||
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_anatomy_user_answers', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Answers',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('answer', models.CharField(max_length=500)),
|
||||
('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='anatomy.anatomyquestion')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='anatomyquestion',
|
||||
name='body_part',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='anatomy.bodypart'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='anatomyquestion',
|
||||
name='examination',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='anatomy.examination'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='anatomyquestion',
|
||||
name='modality',
|
||||
field=models.ForeignKey(help_text='Modality of the image', null=True, on_delete=django.db.models.deletion.SET_NULL, to='anatomy.modality'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='anatomyquestion',
|
||||
name='question_type',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='anatomy.questiontype'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='anatomyquestion',
|
||||
name='structure',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='anatomy.structure'),
|
||||
options={
|
||||
'ordering': ['cid'],
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.1.2 on 2020-10-16 19:10
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='active',
|
||||
field=models.BooleanField(default=True, help_text='If an exam should be available'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,85 @@
|
||||
# Generated by Django 4.1.4 on 2023-06-12 10:07
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import sortedm2m.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('generic', '0001_initial'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('anatomy', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='cid_user_groups',
|
||||
field=models.ManyToManyField(blank=True, help_text='These groups define which candidates are able to be added to the exams/collection.', related_name='anatomy_cid_user_groups', to='generic.cidusergroup'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='exam_questions',
|
||||
field=sortedm2m.fields.SortedManyToManyField(blank='true', help_text=None, related_name='exams', to='anatomy.anatomyquestion'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='user_user_groups',
|
||||
field=models.ManyToManyField(blank=True, help_text='These groups define which candidates are able to be added to the exams/collection.', related_name='anatomy_user_user_groups', to='generic.userusergroup'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='valid_cid_users',
|
||||
field=models.ManyToManyField(blank=True, related_name='anatomy_exams', to='generic.ciduser'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='valid_user_users',
|
||||
field=models.ManyToManyField(blank=True, related_name='user_anatomy_exams', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='answer',
|
||||
name='question',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='anatomy.anatomyquestion'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='anatomyquestion',
|
||||
name='author',
|
||||
field=models.ManyToManyField(blank=True, help_text='Author(s) of question', related_name='anatomy_authored_questions', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='anatomyquestion',
|
||||
name='body_part',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='anatomy.bodypart'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='anatomyquestion',
|
||||
name='examination',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='generic.examination'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='anatomyquestion',
|
||||
name='modality',
|
||||
field=models.ForeignKey(help_text='Modality of the image', null=True, on_delete=django.db.models.deletion.SET_NULL, to='anatomy.modality'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='anatomyquestion',
|
||||
name='question_type',
|
||||
field=models.ForeignKey(default=1, null=True, on_delete=django.db.models.deletion.SET_NULL, to='anatomy.questiontype'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='anatomyquestion',
|
||||
name='region',
|
||||
field=models.ForeignKey(blank=True, help_text='Region the image covers', null=True, on_delete=django.db.models.deletion.SET_NULL, to='anatomy.region'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='anatomyquestion',
|
||||
name='structure',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='anatomy.structure'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,47 @@
|
||||
# Generated by Django 4.1.4 on 2023-06-19 10:51
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("longs", "0002_alter_longseries_modality"),
|
||||
("atlas", "0003_alter_series_modality"),
|
||||
("generic", "0002_modality_examination_modality"),
|
||||
("anatomy", "0002_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
# migrations.DeleteModel(
|
||||
# name='Modality',
|
||||
# ),
|
||||
migrations.SeparateDatabaseAndState(
|
||||
state_operations=[
|
||||
migrations.DeleteModel(
|
||||
name="Modality",
|
||||
),
|
||||
],
|
||||
database_operations=[
|
||||
migrations.AlterModelTable(
|
||||
name="Modality",
|
||||
table="generic_modality",
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.SeparateDatabaseAndState(
|
||||
state_operations=[
|
||||
migrations.AlterField(
|
||||
model_name="anatomyquestion",
|
||||
name="modality",
|
||||
field=models.ForeignKey(
|
||||
help_text="Modality of the image",
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
to="generic.modality",
|
||||
),
|
||||
),
|
||||
],
|
||||
database_operations=[],
|
||||
),
|
||||
]
|
||||
@@ -1,40 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2020-11-19 19:41
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0002_exam_active'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Answer',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('answer', models.CharField(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='anatomy.anatomyquestion')),
|
||||
],
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='halfmarkanswers',
|
||||
name='question',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='incorrectanswers',
|
||||
name='question',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='Answers',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='HalfMarkAnswers',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='IncorrectAnswers',
|
||||
),
|
||||
]
|
||||
@@ -1,25 +0,0 @@
|
||||
# Generated by Django 3.1.2 on 2020-11-23 16:19
|
||||
|
||||
import anatomy.models
|
||||
import django.core.files.storage
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0003_auto_20201119_1941'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='recreate_json',
|
||||
field=models.BooleanField(default=False, help_text='If the json cache needs updating'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='anatomyquestion',
|
||||
name='image',
|
||||
field=models.ImageField(storage=django.core.files.storage.FileSystemStorage(base_url='http://161.35.163.87//media/anatomy/', location='/home/ross/sites/rad/media//anatomy/'), upload_to=anatomy.models.image_directory_path),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,43 @@
|
||||
# Generated by Django 4.1.4 on 2023-07-24 09:24
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0003_alter_anatomyquestion_modality_delete_modality'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='candidates_only',
|
||||
field=models.BooleanField(default=True, help_text='If the exam/collection is only available to candidates who have been added'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='exam',
|
||||
name='active',
|
||||
field=models.BooleanField(default=False, help_text='If an exam/collection should be available to take'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='exam',
|
||||
name='archive',
|
||||
field=models.BooleanField(default=False, help_text='Archived exams/collections will remain on the test system but will not be displayed by default'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='exam',
|
||||
name='name',
|
||||
field=models.CharField(help_text='Name of the exam/collection', max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='exam',
|
||||
name='open_access',
|
||||
field=models.BooleanField(default=False, help_text='If the exam/collection is freely accessible (to view and edit on the test system)'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='exam',
|
||||
name='publish_results',
|
||||
field=models.BooleanField(default=False, help_text='If an exam/collections results should be available'),
|
||||
),
|
||||
]
|
||||
@@ -1,39 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2020-11-26 17:30
|
||||
|
||||
import anatomy.models
|
||||
import django.core.files.storage
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0004_auto_20201123_1619'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='structure',
|
||||
old_name='bodypart',
|
||||
new_name='structure',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='exam',
|
||||
name='recreate_json',
|
||||
),
|
||||
#migrations.AddField(
|
||||
# model_name='anatomyquestion',
|
||||
# name='open_access',
|
||||
# field=models.BooleanField(default=True, help_text='If an question should be freely available to browse'),
|
||||
#),
|
||||
migrations.AlterField(
|
||||
model_name='anatomyquestion',
|
||||
name='image',
|
||||
field=models.ImageField(storage=django.core.files.storage.FileSystemStorage(base_url='http://161.35.163.87//media/anatomy/', location='/home/ross/scripts/sites/rad/media//anatomy/'), upload_to=anatomy.models.image_directory_path),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='exam',
|
||||
name='exam_questions',
|
||||
field=models.ManyToManyField(blank='true', related_name='exams', to='anatomy.AnatomyQuestion'),
|
||||
),
|
||||
]
|
||||
@@ -1,25 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2020-11-29 09:55
|
||||
|
||||
from django.db import migrations, models
|
||||
import sortedm2m.fields
|
||||
from sortedm2m.operations import AlterSortedManyToManyField
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0005_auto_20201126_1730'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
#migrations.AddField(
|
||||
# model_name='anatomyquestion',
|
||||
# name='open_access',
|
||||
# field=models.BooleanField(default=True, help_text='If an question should be freely available to browse'),
|
||||
#),
|
||||
AlterSortedManyToManyField(
|
||||
model_name='exam',
|
||||
name='exam_questions',
|
||||
field=sortedm2m.fields.SortedManyToManyField(blank='true', help_text=None, related_name='exams', to='anatomy.AnatomyQuestion'),
|
||||
),
|
||||
]
|
||||
@@ -1,23 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2020-12-01 23:58
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0006_auto_20201129_0955'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
#migrations.AddField(
|
||||
#model_name='anatomyquestion',
|
||||
#name='open_access',
|
||||
#field=models.BooleanField(default=True, help_text='If an question should be freely available to browse'),
|
||||
#),
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='recreate_json',
|
||||
field=models.BooleanField(default=False, help_text='If the json cache needs updating'),
|
||||
),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2020-12-03 09:29
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0007_auto_20201201_2358'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='anatomyquestion',
|
||||
name='open_access',
|
||||
field=models.BooleanField(default=True, help_text='If an question should be freely available to browse'),
|
||||
),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2020-12-06 11:11
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0008_anatomyquestion_open_access'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='anatomyquestion',
|
||||
name='image_annotations',
|
||||
field=models.TextField(blank=True, help_text='Stores a JSON representation of annotations to be applied by cornerstonetools'),
|
||||
),
|
||||
]
|
||||
@@ -1,26 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2020-12-06 17:16
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0009_anatomyquestion_image_annotations'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Region',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('region', models.CharField(max_length=200)),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='anatomyquestion',
|
||||
name='region',
|
||||
field=models.ForeignKey(blank=True, help_text='Region the image covers', null=True, on_delete=django.db.models.deletion.SET_NULL, to='anatomy.region'),
|
||||
),
|
||||
]
|
||||
@@ -1,20 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2020-12-06 18:12
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('anatomy', '0010_auto_20201206_1716'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='anatomyquestion',
|
||||
name='author',
|
||||
field=models.ManyToManyField(blank=True, help_text='Author(s) of question', related_name='anatomy_authored_questions', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2020-12-10 23:11
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0011_anatomyquestion_author'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='publish_results',
|
||||
field=models.BooleanField(default=True, help_text='If an exams results should be available'),
|
||||
),
|
||||
]
|
||||
@@ -1,35 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2020-12-27 12:00
|
||||
|
||||
import anatomy.models
|
||||
import django.core.files.storage
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0012_exam_publish_results'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='anatomyquestion',
|
||||
name='image',
|
||||
field=models.ImageField(storage=django.core.files.storage.FileSystemStorage(base_url='http://penracourses.org.uk//media/anatomy/', location='/home/ross/scripts/sites/rad/media//anatomy/'), upload_to=anatomy.models.image_directory_path),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='answer',
|
||||
name='answer',
|
||||
field=models.TextField(max_length=500),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ciduseranswer',
|
||||
name='answer',
|
||||
field=models.TextField(blank=True, max_length=500),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='useranswer',
|
||||
name='answer',
|
||||
field=models.TextField(blank=True, max_length=500),
|
||||
),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2020-12-28 10:17
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0013_auto_20201227_1200'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='time_limit',
|
||||
field=models.IntegerField(default=False, help_text='Exam time limit (in seconds)'),
|
||||
),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2020-12-28 22:35
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0014_exam_time_limit'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='exam',
|
||||
name='time_limit',
|
||||
field=models.IntegerField(default=5400, help_text='Exam time limit (in seconds)'),
|
||||
),
|
||||
]
|
||||
@@ -1,25 +0,0 @@
|
||||
# Generated by Django 3.1.2 on 2021-01-04 13:10
|
||||
|
||||
import anatomy.models
|
||||
import django.core.files.storage
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0015_auto_20201228_2235'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='anatomyquestion',
|
||||
name='image',
|
||||
field=models.ImageField(storage=django.core.files.storage.FileSystemStorage(base_url='http://penracourses.org.uk//media/anatomy/', location='/home/ross/sites/rad/media//anatomy/'), upload_to=anatomy.models.image_directory_path),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='useranswer',
|
||||
name='cid',
|
||||
field=models.BigIntegerField(blank=True, null=True),
|
||||
),
|
||||
]
|
||||
@@ -1,23 +0,0 @@
|
||||
# Generated by Django 3.1.2 on 2021-01-04 13:55
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0016_auto_20210104_1310'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='ciduseranswer',
|
||||
name='cid',
|
||||
field=models.BigIntegerField(blank=True, help_text='Candidate ID (limitied by BigIntegerField size)', null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='useranswer',
|
||||
name='cid',
|
||||
field=models.BigIntegerField(blank=True, help_text='Candidate ID (limitied by BigIntegerField size)', null=True),
|
||||
),
|
||||
]
|
||||
@@ -1,34 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2021-01-12 17:26
|
||||
|
||||
import anatomy.models
|
||||
import django.core.files.storage
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0017_auto_20210104_1355'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='answer',
|
||||
name='answer_compare',
|
||||
field=models.TextField(default='temp', max_length=500),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ciduseranswer',
|
||||
name='answer_compare',
|
||||
field=models.TextField(blank=True, max_length=500),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='anatomyquestion',
|
||||
name='image',
|
||||
field=models.ImageField(storage=django.core.files.storage.FileSystemStorage(base_url='/media/anatomy/', location='/home/ross/scripts/sites/rad/media//anatomy/'), upload_to=anatomy.models.image_directory_path),
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='UserAnswer',
|
||||
),
|
||||
]
|
||||
@@ -1,20 +0,0 @@
|
||||
# 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,20 +0,0 @@
|
||||
# Generated by Django 3.1.2 on 2021-01-18 14:02
|
||||
|
||||
import anatomy.models
|
||||
import django.core.files.storage
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0019_auto_20210118_1339'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='anatomyquestion',
|
||||
name='image',
|
||||
field=models.ImageField(storage=django.core.files.storage.FileSystemStorage(base_url='http://penracourses.org.uk//media/anatomy/', location='/home/ross/sites/rad/media//anatomy/'), upload_to=anatomy.models.image_directory_path),
|
||||
),
|
||||
]
|
||||
@@ -1,20 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2021-01-20 22:06
|
||||
|
||||
import anatomy.models
|
||||
import django.core.files.storage
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0020_auto_20210118_1402'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='anatomyquestion',
|
||||
name='image',
|
||||
field=models.ImageField(storage=django.core.files.storage.FileSystemStorage(base_url='http://penracourses.org.uk//media/anatomy/', location='/home/ross/scripts/sites/rad/media//anatomy/'), upload_to=anatomy.models.image_directory_path),
|
||||
),
|
||||
]
|
||||
@@ -1,20 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2021-01-21 18:06
|
||||
|
||||
import anatomy.models
|
||||
import django.core.files.storage
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0021_auto_20210120_2206'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='anatomyquestion',
|
||||
name='image',
|
||||
field=models.ImageField(storage=django.core.files.storage.FileSystemStorage(base_url='/media/anatomy/', location='/home/ross/scripts/sites/rad/media//anatomy/'), upload_to=anatomy.models.image_directory_path),
|
||||
),
|
||||
]
|
||||
@@ -1,20 +0,0 @@
|
||||
# Generated by Django 3.1.5 on 2021-01-25 15:34
|
||||
|
||||
import anatomy.models
|
||||
import django.core.files.storage
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0022_auto_20210121_1806'),
|
||||
]
|
||||
|
||||
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,20 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2021-01-30 15:15
|
||||
|
||||
import anatomy.models
|
||||
import django.core.files.storage
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0023_auto_20210125_1534'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='anatomyquestion',
|
||||
name='image',
|
||||
field=models.ImageField(storage=django.core.files.storage.FileSystemStorage(base_url='/media/anatomy/', location='/home/ross/scripts/sites/rad/media//anatomy/'), upload_to=anatomy.models.image_directory_path),
|
||||
),
|
||||
]
|
||||
@@ -1,23 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2021-02-05 11:06
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('generic', '0007_site'),
|
||||
('anatomy', '0024_auto_20210130_1515'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='anatomyquestion',
|
||||
name='examination',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='generic.examination'),
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='Examination',
|
||||
),
|
||||
]
|
||||
@@ -1,17 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2021-02-05 11:09
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0025_auto_20210205_1106'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='anatomyquestion',
|
||||
name='examination',
|
||||
),
|
||||
]
|
||||
@@ -1,20 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2021-02-05 11:10
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('generic', '0007_site'),
|
||||
('anatomy', '0026_remove_anatomyquestion_examination'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='anatomyquestion',
|
||||
name='examination',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='generic.examination'),
|
||||
),
|
||||
]
|
||||
@@ -1,24 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2021-02-06 09:05
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0027_anatomyquestion_examination'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='anatomyquestion',
|
||||
name='open_access',
|
||||
field=models.BooleanField(default=True, help_text='If a question should be freely available to browse'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='anatomyquestion',
|
||||
name='question_type',
|
||||
field=models.ForeignKey(default=1, null=True, on_delete=django.db.models.deletion.SET_NULL, to='anatomy.questiontype'),
|
||||
),
|
||||
]
|
||||
@@ -1,20 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2021-02-09 22:39
|
||||
|
||||
import anatomy.models
|
||||
import django.core.files.storage
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0028_auto_20210206_0905'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='anatomyquestion',
|
||||
name='image',
|
||||
field=models.ImageField(storage=django.core.files.storage.FileSystemStorage(base_url='/media/anatomy/', location='/home/ross/rad/media//anatomy/'), upload_to=anatomy.models.image_directory_path),
|
||||
),
|
||||
]
|
||||
@@ -1,20 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2021-02-14 20:28
|
||||
|
||||
import anatomy.models
|
||||
import django.core.files.storage
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0029_auto_20210209_2239'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='anatomyquestion',
|
||||
name='image',
|
||||
field=models.ImageField(storage=django.core.files.storage.FileSystemStorage(base_url='/media/anatomy/', location='/home/ross/scripts/sites/rad/media//anatomy/'), upload_to=anatomy.models.image_directory_path),
|
||||
),
|
||||
]
|
||||
@@ -1,20 +0,0 @@
|
||||
# Generated by Django 3.1.5 on 2021-02-15 10:43
|
||||
|
||||
import anatomy.models
|
||||
import django.core.files.storage
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0030_auto_20210214_2028'),
|
||||
]
|
||||
|
||||
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,20 +0,0 @@
|
||||
# Generated by Django 3.1.5 on 2021-02-15 11:44
|
||||
|
||||
import anatomy.models
|
||||
import django.core.files.storage
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0031_auto_20210215_1043'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='anatomyquestion',
|
||||
name='image',
|
||||
field=models.ImageField(storage=django.core.files.storage.FileSystemStorage(base_url='/media/anatomy/', location='/home/django/rad/media//anatomy/'), upload_to=anatomy.models.image_directory_path),
|
||||
),
|
||||
]
|
||||
@@ -1,20 +0,0 @@
|
||||
# Generated by Django 3.1.5 on 2021-02-15 11:47
|
||||
|
||||
import anatomy.models
|
||||
import django.core.files.storage
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0032_auto_20210215_1144'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='anatomyquestion',
|
||||
name='image',
|
||||
field=models.ImageField(storage=django.core.files.storage.FileSystemStorage(base_url='/media//', location='/home/django/rad/media//'), upload_to=anatomy.models.image_directory_path),
|
||||
),
|
||||
]
|
||||
@@ -1,19 +0,0 @@
|
||||
# Generated by Django 3.1.5 on 2021-02-15 12:00
|
||||
|
||||
import anatomy.models
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0033_auto_20210215_1147'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='anatomyquestion',
|
||||
name='image',
|
||||
field=models.ImageField(upload_to=anatomy.models.image_directory_path),
|
||||
),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2021-03-09 15:27
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0034_auto_20210215_1200'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='json_creation_time',
|
||||
field=models.DateTimeField(blank=True, default=None, null=True),
|
||||
),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2021-03-19 11:17
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0035_exam_json_creation_time'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='exam_mode',
|
||||
field=models.BooleanField(default=True, help_text='If an exam should be take in exam_mode'),
|
||||
),
|
||||
]
|
||||
@@ -1,35 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2021-04-22 11:43
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('anatomy', '0036_exam_exam_mode'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='author',
|
||||
field=models.ManyToManyField(blank=True, help_text='Author of exam', related_name='anatomy_exam_author', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='exam',
|
||||
name='active',
|
||||
field=models.BooleanField(default=False, help_text='If an exam should be available'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='exam',
|
||||
name='exam_mode',
|
||||
field=models.BooleanField(default=True, help_text='If an exam should be taken in exam mode'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='exam',
|
||||
name='publish_results',
|
||||
field=models.BooleanField(default=False, help_text='If an exams results should be available'),
|
||||
),
|
||||
]
|
||||
@@ -1,17 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2021-04-29 19:04
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0037_auto_20210422_1143'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='anatomyquestion',
|
||||
options={'permissions': ()},
|
||||
),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2021-05-03 11:45
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0038_auto_20210429_1904'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='answer',
|
||||
name='proposed',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.2.4 on 2021-07-06 19:02
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0039_answer_proposed'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='exam',
|
||||
name='exam_mode',
|
||||
field=models.BooleanField(default=False, help_text='If an exam should be taken in exam mode (users results will be submited to the server for marking)'),
|
||||
),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.2.4 on 2021-07-09 11:35
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0040_alter_exam_exam_mode'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='exam',
|
||||
name='name',
|
||||
field=models.CharField(help_text='Name of the exam', max_length=200),
|
||||
),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.2.4 on 2021-08-01 08:18
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0041_alter_exam_name'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='json_creation_id',
|
||||
field=models.IntegerField(default=1, help_text='auto incrementing field when json recreated'),
|
||||
),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.2.4 on 2021-08-01 08:47
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0042_exam_json_creation_id'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='exam',
|
||||
old_name='json_creation_id',
|
||||
new_name='exam_json_id',
|
||||
),
|
||||
]
|
||||
@@ -1,23 +0,0 @@
|
||||
# Generated by Django 3.2.6 on 2021-08-16 12:06
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0043_rename_json_creation_id_exam_exam_json_id'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='archive',
|
||||
field=models.BooleanField(default=False, help_text='Archived exams will remain on the test system but will not be displayed by default'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='exam',
|
||||
name='active',
|
||||
field=models.BooleanField(default=False, help_text='If an exam should be available to take'),
|
||||
),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.2.8 on 2021-10-17 17:03
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0044_auto_20210816_1306'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='open_access',
|
||||
field=models.BooleanField(default=False, help_text='If the exam is freely accessible'),
|
||||
),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.2.8 on 2021-10-17 17:13
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0045_exam_open_access'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='exam',
|
||||
name='open_access',
|
||||
field=models.BooleanField(default=False, help_text='If the exam is freely accessible (to view and edit on the test system)'),
|
||||
),
|
||||
]
|
||||
@@ -1,28 +0,0 @@
|
||||
# Generated by Django 3.2.8 on 2021-10-22 19:38
|
||||
|
||||
import anatomy.models
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0046_alter_exam_open_access'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='structure',
|
||||
name='id',
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='anatomyquestion',
|
||||
name='image',
|
||||
field=models.ImageField(help_text="The image to use for the question. Ideally use use unmarked images and annotate (arrow) them on the test system. If you wish to reuse an image that is already uploaded 'clone' the question that contains it.As a preference", upload_to=anatomy.models.image_directory_path),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='structure',
|
||||
name='structure',
|
||||
field=models.CharField(max_length=200, primary_key=True, serialize=False),
|
||||
),
|
||||
]
|
||||
@@ -1,25 +0,0 @@
|
||||
# Generated by Django 3.2.8 on 2021-10-25 10:02
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0047_auto_20211022_2038'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Structure2',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('structure', models.CharField(max_length=200, unique=True)),
|
||||
],
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='anatomyquestion',
|
||||
name='structure',
|
||||
field=models.CharField(max_length=255, null=True),
|
||||
),
|
||||
]
|
||||
@@ -1,16 +0,0 @@
|
||||
# Generated by Django 3.2.8 on 2021-10-25 10:07
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0048_auto_20211025_1102'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.DeleteModel(
|
||||
name='Structure',
|
||||
),
|
||||
]
|
||||
@@ -1,17 +0,0 @@
|
||||
# Generated by Django 3.2.8 on 2021-10-25 10:08
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0049_delete_structure'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameModel(
|
||||
old_name='Structure2',
|
||||
new_name='Structure',
|
||||
),
|
||||
]
|
||||
@@ -1,19 +0,0 @@
|
||||
# Generated by Django 3.2.8 on 2021-10-25 10:08
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0050_rename_structure2_structure'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='anatomyquestion',
|
||||
name='structure',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='anatomy.structure'),
|
||||
),
|
||||
]
|
||||
@@ -1,17 +0,0 @@
|
||||
# Generated by Django 3.2.8 on 2021-10-25 10:15
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0051_alter_anatomyquestion_structure'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='anatomyquestion',
|
||||
name='structure',
|
||||
),
|
||||
]
|
||||
@@ -1,19 +0,0 @@
|
||||
# Generated by Django 3.2.8 on 2021-10-25 10:17
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0052_remove_anatomyquestion_structure'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='anatomyquestion',
|
||||
name='structure',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='anatomy.structure'),
|
||||
),
|
||||
]
|
||||
@@ -1,19 +0,0 @@
|
||||
# Generated by Django 3.2.8 on 2021-12-11 22:12
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('generic', '0015_ciduser_ciduserexam'),
|
||||
('anatomy', '0053_anatomyquestion_structure'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='valid_users',
|
||||
field=models.ManyToManyField(blank=True, related_name='anatomy_exams', to='generic.CidUser'),
|
||||
),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.2.8 on 2021-12-15 18:35
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0054_exam_valid_users'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='ciduseranswer',
|
||||
name='score',
|
||||
field=models.CharField(choices=[('', 'Unmarked'), ('0', 'Incorrect'), ('1', 'Half mark'), ('2', 'Correct')], default='', max_length=1),
|
||||
),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.2.8 on 2021-12-15 20:02
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0055_ciduseranswer_score'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='ciduseranswer',
|
||||
name='score',
|
||||
field=models.CharField(blank=True, choices=[('', 'Unmarked'), ('0', 'Incorrect'), ('1', 'Half mark'), ('2', 'Correct')], default='', max_length=1),
|
||||
),
|
||||
]
|
||||
@@ -1,53 +0,0 @@
|
||||
# Generated by Django 3.2.8 on 2021-12-15 20:36
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0056_alter_ciduseranswer_score'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='stats_candidates',
|
||||
field=models.FloatField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='stats_graph',
|
||||
field=models.TextField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='stats_max',
|
||||
field=models.FloatField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='stats_max_possible',
|
||||
field=models.FloatField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='stats_mean',
|
||||
field=models.FloatField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='stats_median',
|
||||
field=models.FloatField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='stats_min',
|
||||
field=models.FloatField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='stats_mode',
|
||||
field=models.CharField(default=0, max_length=25),
|
||||
),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.2.10 on 2021-12-31 10:44
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0057_auto_20211215_2036'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='user_scores',
|
||||
field=models.JSONField(default=dict),
|
||||
),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.2.10 on 2022-04-04 21:56
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0058_exam_user_scores'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='include_history',
|
||||
field=models.BooleanField(default=False, help_text='If an exam should include history when taking'),
|
||||
),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.2.13 on 2022-05-03 17:48
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0059_exam_include_history'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='authors_only',
|
||||
field=models.BooleanField(default=False, help_text='If true only exam authors will be able to view.'),
|
||||
),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.2.13 on 2022-05-20 10:45
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0060_exam_authors_only'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='exam',
|
||||
old_name='valid_users',
|
||||
new_name='valid_cid_users',
|
||||
),
|
||||
]
|
||||
@@ -1,20 +0,0 @@
|
||||
# Generated by Django 3.2.13 on 2022-05-20 12:42
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('anatomy', '0061_rename_valid_users_exam_valid_cid_users'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='valid_user_users',
|
||||
field=models.ManyToManyField(blank=True, related_name='user_anatomy_exams', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
@@ -1,21 +0,0 @@
|
||||
# Generated by Django 3.2.13 on 2022-05-20 19:51
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('anatomy', '0062_exam_valid_user_users'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='ciduseranswer',
|
||||
name='user',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_anatomy_user_answers', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
@@ -1,24 +0,0 @@
|
||||
# Generated by Django 3.2.13 on 2022-05-21 09:20
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('generic', '0032_userprofile_registration_number'),
|
||||
('anatomy', '0063_ciduseranswer_user'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='cid_user_groups',
|
||||
field=models.ManyToManyField(blank=True, help_text='These groups define which candidates are able to be added to the exams/collection.', related_name='anatomy_cid_user_groups', to='generic.CidUserGroup'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='user_user_groups',
|
||||
field=models.ManyToManyField(blank=True, help_text='These groups define which candidates are able to be added to the exams/collection.', related_name='anatomy_user_user_groups', to='generic.UserUserGroup'),
|
||||
),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.2.13 on 2022-06-26 15:12
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0064_auto_20220521_1020'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='exam',
|
||||
name='exam_results_emailed',
|
||||
field=models.DateTimeField(default=None, null=True),
|
||||
),
|
||||
]
|
||||
@@ -1,17 +0,0 @@
|
||||
# Generated by Django 3.2.13 on 2022-06-30 20:45
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0065_exam_exam_results_emailed'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='exam',
|
||||
name='stats_graph',
|
||||
),
|
||||
]
|
||||
@@ -1,19 +0,0 @@
|
||||
# Generated by Django 3.2.13 on 2022-11-14 09:44
|
||||
|
||||
import anatomy.models
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0066_remove_exam_stats_graph'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='anatomyquestion',
|
||||
name='image',
|
||||
field=models.ImageField(help_text="The image to use for the question. Ideally use use unmarked images and annotate (arrow) them on the test system. If you wish to reuse an image that is already uploaded 'clone' the question that contains it.", upload_to=anatomy.models.image_directory_path),
|
||||
),
|
||||
]
|
||||
+14
-28
@@ -16,7 +16,7 @@ from sortedm2m.fields import SortedManyToManyField
|
||||
|
||||
import string
|
||||
|
||||
from generic.models import CidUser, CidUserGroup, ExamUserStatus, Examination, ExamBase, QuestionNote, UserUserGroup
|
||||
from generic.models import CidUser, CidUserGroup, ExamUserStatus, Examination, ExamBase, QuestionBase, QuestionNote, UserAnswerBase, UserUserGroup, Modality
|
||||
|
||||
from collections import defaultdict
|
||||
from helpers.images import image_as_base64
|
||||
@@ -57,11 +57,12 @@ class Region(models.Model):
|
||||
return self.region
|
||||
|
||||
|
||||
class Modality(models.Model):
|
||||
modality = models.CharField(max_length=200)
|
||||
|
||||
def __str__(self):
|
||||
return self.modality
|
||||
## TODO: ??? Move to generic app
|
||||
#class Modality(models.Model):
|
||||
# modality = models.CharField(max_length=200)
|
||||
#
|
||||
# def __str__(self):
|
||||
# return self.modality
|
||||
|
||||
|
||||
class QuestionType(models.Model):
|
||||
@@ -72,7 +73,7 @@ class QuestionType(models.Model):
|
||||
|
||||
|
||||
@reversion.register
|
||||
class AnatomyQuestion(models.Model):
|
||||
class AnatomyQuestion(QuestionBase):
|
||||
question_type = models.ForeignKey(
|
||||
QuestionType, on_delete=models.SET_NULL, null=True, default=1
|
||||
)
|
||||
@@ -114,11 +115,6 @@ class AnatomyQuestion(models.Model):
|
||||
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 a question should be freely available to browse", default=True
|
||||
)
|
||||
|
||||
author = models.ManyToManyField(
|
||||
settings.AUTH_USER_MODEL,
|
||||
@@ -127,8 +123,6 @@ class AnatomyQuestion(models.Model):
|
||||
related_name="anatomy_authored_questions",
|
||||
)
|
||||
|
||||
notes = GenericRelation(QuestionNote)
|
||||
|
||||
class Meta:
|
||||
permissions = ()
|
||||
|
||||
@@ -152,6 +146,9 @@ class AnatomyQuestion(models.Model):
|
||||
a.answer, exams, self.modality, self.structure
|
||||
)
|
||||
|
||||
def get_link(self):
|
||||
return format_html("<a href='{}'>{}</a>", self.get_absolute_url(), self)
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse("anatomy:question_detail", kwargs={"pk": self.pk})
|
||||
|
||||
@@ -467,8 +464,9 @@ class Exam(ExamBase):
|
||||
|
||||
|
||||
@reversion.register
|
||||
class CidUserAnswer(models.Model):
|
||||
class UserAnswer(UserAnswerBase):
|
||||
"""User answers by candidate"""
|
||||
app_name = "anatomy"
|
||||
|
||||
question = models.ForeignKey(
|
||||
AnatomyQuestion, related_name="cid_user_answers", on_delete=models.CASCADE
|
||||
@@ -477,12 +475,6 @@ class CidUserAnswer(models.Model):
|
||||
|
||||
answer_compare = models.TextField(max_length=500, blank=True)
|
||||
|
||||
cid = models.BigIntegerField(
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text="Candidate ID (limitied by BigIntegerField size)",
|
||||
)
|
||||
|
||||
user = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, null=True, related_name="user_anatomy_user_answers"
|
||||
)
|
||||
@@ -492,9 +484,6 @@ class CidUserAnswer(models.Model):
|
||||
Exam, related_name="cid_user_answers", on_delete=models.CASCADE, null=True
|
||||
)
|
||||
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
updated = models.DateTimeField(auto_now=True)
|
||||
|
||||
score = models.CharField(
|
||||
max_length=1,
|
||||
choices=Answer.MarkOptions.choices,
|
||||
@@ -513,7 +502,7 @@ class CidUserAnswer(models.Model):
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
self.clean()
|
||||
return super(CidUserAnswer, self).save(*args, **kwargs)
|
||||
return super(UserAnswer, self).save(*args, **kwargs)
|
||||
|
||||
def clean(self):
|
||||
if self.answer:
|
||||
@@ -524,9 +513,6 @@ class CidUserAnswer(models.Model):
|
||||
|
||||
self.answer_compare = s
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse("anatomy:user_answer_view", kwargs={"pk": self.pk})
|
||||
|
||||
# def get_compare_string(self):
|
||||
# # strip here should be unneccasry (providing clean is now working)
|
||||
# s = self.answer.lower().strip()
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
+5
-13
@@ -1,7 +1,9 @@
|
||||
import django_tables2 as tables
|
||||
from django_tables2.utils import A
|
||||
|
||||
from .models import AnatomyQuestion, CidUserAnswer
|
||||
from generic.tables import SingleImageColumn
|
||||
|
||||
from .models import AnatomyQuestion, UserAnswer
|
||||
|
||||
from django.utils.html import format_html
|
||||
|
||||
@@ -11,16 +13,6 @@ from easy_thumbnails.exceptions import InvalidImageFormatError
|
||||
|
||||
#from generic.tables import UserAnswerTable
|
||||
|
||||
|
||||
class ImageColumn(tables.Column):
|
||||
def render(self, value):
|
||||
try:
|
||||
thumbnailer = get_thumbnailer(value)
|
||||
return format_html('<img src="/media/{}" />', thumbnailer["exam-list"])
|
||||
except InvalidImageFormatError:
|
||||
return format_html('<span title="{}">Invalid image url<span>', value)
|
||||
|
||||
|
||||
class AnatomyQuestionTable(tables.Table):
|
||||
edit = tables.LinkColumn(
|
||||
"anatomy:anatomy_question_update", text="Edit", args=[A("pk")], orderable=False
|
||||
@@ -28,7 +20,7 @@ class AnatomyQuestionTable(tables.Table):
|
||||
view = tables.LinkColumn(
|
||||
"anatomy:question_detail", text="View", args=[A("pk")], orderable=False
|
||||
)
|
||||
image = ImageColumn("image", orderable=False)
|
||||
image = SingleImageColumn("image", orderable=False)
|
||||
# clone = tables.LinkColumn('anatomy:anatomy_question_clone',
|
||||
# text='Clone',
|
||||
# args=[A('pk')],
|
||||
@@ -74,7 +66,7 @@ class AnatomyUserAnswerTable(tables.Table):
|
||||
args=[A('pk')],
|
||||
orderable=False)
|
||||
class Meta:
|
||||
model = CidUserAnswer
|
||||
model = UserAnswer
|
||||
template_name = "django_tables2/bootstrap4.html"
|
||||
fields = (
|
||||
"cid",
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
Answer: {{ciduseranswer.answer}}<br />
|
||||
Score: {{ciduseranswer.get_answer_score}}<br />
|
||||
<a href="{% url 'anatomy:user_answer_delete' ciduseranswer.id %}">Delete answer</a>
|
||||
<a href="{% url 'admin:anatomy_ciduseranswer_change' ciduseranswer.id %}">Admin Edit</a>
|
||||
<a href="{% url 'admin:anatomy_useranswer_change' ciduseranswer.id %}">Admin Edit</a>
|
||||
{% endblock content %}
|
||||
|
||||
+7
-7
@@ -41,7 +41,7 @@ from .forms import (
|
||||
from .models import (
|
||||
AnatomyQuestion,
|
||||
BodyPart,
|
||||
CidUserAnswer,
|
||||
UserAnswer,
|
||||
# Examination,
|
||||
Structure,
|
||||
Exam,
|
||||
@@ -384,7 +384,7 @@ def exam_scores_refresh(request, pk):
|
||||
|
||||
questions = exam.exam_questions.all()
|
||||
|
||||
cids = CidUserAnswer.objects.filter(question__in=questions, exam__id=pk)
|
||||
cids = UserAnswer.objects.filter(question__in=questions, exam__id=pk)
|
||||
|
||||
# Force a score update
|
||||
for c in cids:
|
||||
@@ -733,16 +733,16 @@ def question_save_annotation(request, pk):
|
||||
|
||||
|
||||
GenericExamViews = ExamViews(
|
||||
Exam, AnatomyQuestion, Answer, CidUserAnswer, "anatomy", "anatomy"
|
||||
Exam, AnatomyQuestion, Answer, UserAnswer, "anatomy", "anatomy"
|
||||
)
|
||||
|
||||
|
||||
class UserAnswerView(SuperuserRequiredMixin, DetailView):
|
||||
model = CidUserAnswer
|
||||
model = UserAnswer
|
||||
|
||||
|
||||
class UserAnswerTableView(SuperuserRequiredMixin, SingleTableMixin, FilterView):
|
||||
model = CidUserAnswer
|
||||
model = UserAnswer
|
||||
table_class = AnatomyUserAnswerTable
|
||||
template_name = "anatomy/user_answer_question_view.html"
|
||||
|
||||
@@ -750,7 +750,7 @@ class UserAnswerTableView(SuperuserRequiredMixin, SingleTableMixin, FilterView):
|
||||
|
||||
|
||||
class UserAnswerDelete(SuperuserRequiredMixin, DeleteView):
|
||||
model = CidUserAnswer
|
||||
model = UserAnswer
|
||||
template_name = "user_answer_delete.html"
|
||||
success_url = reverse_lazy("anatomy:user_answer_table_view")
|
||||
|
||||
@@ -797,7 +797,7 @@ class ExamAuthorUpdate(RevisionMixin, LoginRequiredMixin, AuthorRequiredMixin, U
|
||||
|
||||
|
||||
|
||||
GenericViews = GenericViewBase("anatomy", AnatomyQuestion, CidUserAnswer, Exam)
|
||||
GenericViews = GenericViewBase("anatomy", AnatomyQuestion, UserAnswer, Exam)
|
||||
|
||||
|
||||
class ExamClone(ExamCloneMixin, ExamCreate):
|
||||
|
||||
@@ -13,6 +13,7 @@ from .models import (
|
||||
Structure,
|
||||
PathologicalProcess,
|
||||
Presentation,
|
||||
UncategorisedDicom,
|
||||
)
|
||||
|
||||
from django.forms import ModelForm
|
||||
@@ -38,6 +39,7 @@ admin.site.register(Differential)
|
||||
admin.site.register(PathologicalProcess)
|
||||
admin.site.register(Presentation)
|
||||
admin.site.register(CaseDetail)
|
||||
admin.site.register(UncategorisedDicom)
|
||||
|
||||
|
||||
class DifferentialInline(admin.TabularInline):
|
||||
|
||||
+201
@@ -0,0 +1,201 @@
|
||||
from collections import defaultdict
|
||||
from typing import List
|
||||
from django.shortcuts import get_object_or_404
|
||||
from ninja import ModelSchema, Router, Schema, Field
|
||||
|
||||
# from .decorators import user_is_author_or_rapid_checker
|
||||
from django.core.exceptions import PermissionDenied
|
||||
|
||||
from generic.decorators import check_user_in_group
|
||||
from generic.constants import Group
|
||||
|
||||
from ninja.security import django_auth
|
||||
|
||||
from ninja import NinjaAPI, File
|
||||
from ninja.files import UploadedFile
|
||||
|
||||
from generic.models import Modality
|
||||
|
||||
from .models import Case, DuplicateDicom, Series, SeriesImage, UncategorisedDicom
|
||||
|
||||
|
||||
router = Router()
|
||||
|
||||
|
||||
class SeriesSchema(ModelSchema):
|
||||
case_id: List[int] = []
|
||||
|
||||
class Config:
|
||||
model = Series
|
||||
model_fields = [
|
||||
"id",
|
||||
"modality",
|
||||
"examination",
|
||||
"series_instance_uid",
|
||||
"author",
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def resolve_case_id(obj):
|
||||
return [i.id for i in obj.case.all()]
|
||||
|
||||
|
||||
class CaseSchema(ModelSchema):
|
||||
class Config:
|
||||
model = Case
|
||||
model_fields = ["id", "title"]
|
||||
|
||||
|
||||
@router.post("/upload_dicom", auth=django_auth)
|
||||
def upload_dicom(request, files: List[UploadedFile] = File(...)):
|
||||
uploaded = []
|
||||
duplicate = []
|
||||
for file in files:
|
||||
# data = file.read()
|
||||
try:
|
||||
ud = UncategorisedDicom(image=file, user=request.user)
|
||||
|
||||
ud.save()
|
||||
|
||||
uploaded.append((file.name, ud.image_md5_hash))
|
||||
except DuplicateDicom:
|
||||
print(ud.check_for_duplicates(ud.image_md5_hash))
|
||||
duplicate.append((file.name, ud.image_md5_hash))
|
||||
pass
|
||||
|
||||
return {"uploaded": uploaded, "duplicates": duplicate}
|
||||
|
||||
|
||||
@router.get("/clear_dicoms", auth=django_auth)
|
||||
def clear_dicoms(request):
|
||||
dicoms = UncategorisedDicom.objects.filter(user=request.user)
|
||||
|
||||
dicoms.delete()
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@router.get("/uncategorised_dicoms", auth=django_auth)
|
||||
def uncategorised_dicoms(request):
|
||||
dicoms = UncategorisedDicom.objects.filter(user=request.user)
|
||||
|
||||
data = defaultdict(list)
|
||||
for d in dicoms:
|
||||
tags = d.get_basic_dicom_tags()
|
||||
|
||||
data[tags["SeriesInstanceUID"]].append(tags)
|
||||
data["image_hash"].append(d.image_md5_hash)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def import_dicoms_helper(request, case_id: int | None = None):
|
||||
dicoms = UncategorisedDicom.objects.filter(user=request.user)
|
||||
|
||||
data = defaultdict(list)
|
||||
for d in dicoms:
|
||||
tags = d.get_basic_dicom_tags()
|
||||
|
||||
data[tags["SeriesInstanceUID"]].append((d, tags))
|
||||
|
||||
series_list = []
|
||||
for series_uid in data:
|
||||
modality = get_object_or_404(Modality, short_code=tags["Modality"])
|
||||
tags = data[series_uid][0][1]
|
||||
|
||||
# Check if series with the id already exists (in which case we just add to htat)
|
||||
try:
|
||||
series = Series.objects.get(series_instance_uid=tags["SeriesInstanceUID"])
|
||||
except Series.DoesNotExist:
|
||||
series = Series(
|
||||
modality=modality,
|
||||
description=tags["SeriesDescription"],
|
||||
series_instance_uid=tags["SeriesInstanceUID"],
|
||||
)
|
||||
series.save()
|
||||
|
||||
# We might only want to add the author during creation....
|
||||
series.author.add(request.user)
|
||||
|
||||
if case_id is not None:
|
||||
series.case.add(case_id)
|
||||
|
||||
for dicom, dicom_tags in data[series_uid]:
|
||||
series_image = SeriesImage(
|
||||
image=dicom.image,
|
||||
series=series,
|
||||
is_dicom=True,
|
||||
image_md5_hash=dicom.image_md5_hash,
|
||||
)
|
||||
series_image.save()
|
||||
# dicom.image.delete()
|
||||
|
||||
dicom.delete()
|
||||
series_list.append(series)
|
||||
|
||||
return series_list
|
||||
|
||||
|
||||
@router.get("/import_dicoms", auth=django_auth, response=List[SeriesSchema])
|
||||
def import_dicoms(request):
|
||||
return import_dicoms_helper(request)
|
||||
|
||||
|
||||
@router.get("/import_dicoms/{case_id}", auth=django_auth, response=List[SeriesSchema])
|
||||
def import_dicoms_case(request, case_id: int):
|
||||
return import_dicoms_helper(request, case_id=case_id)
|
||||
|
||||
|
||||
@router.get("/orphan_series", auth=django_auth, response=List[SeriesSchema])
|
||||
def orphan_series(request):
|
||||
# print(request.user.series.filter(case=None))
|
||||
return request.user.series.filter(case=None)
|
||||
|
||||
|
||||
@router.get("/series_remove_duplicate_images", auth=django_auth)
|
||||
def series_remove_duplicate_images(request, series_id: int):
|
||||
series = get_object_or_404(Series, pk=series_id)
|
||||
|
||||
img_ids = set()
|
||||
dupes = set()
|
||||
for series_image in series.images.all():
|
||||
if series_image.image_md5_hash in img_ids:
|
||||
dupes.add(series_image.id)
|
||||
img_ids.add(series_image.image_md5_hash)
|
||||
|
||||
if dupes:
|
||||
SeriesImage.objects.filter(id__in=dupes).delete()
|
||||
|
||||
return len(dupes)
|
||||
|
||||
|
||||
@router.get("/get_cases_user", auth=django_auth, response=List[CaseSchema])
|
||||
def get_cases_user(request):
|
||||
print("HELLO")
|
||||
return Case.objects.filter(author=request.user)
|
||||
|
||||
|
||||
@router.get("/check_image_hash/{hash}", auth=django_auth)
|
||||
def check_image_hash(request, hash: str):
|
||||
try:
|
||||
print(hash)
|
||||
series_image = SeriesImage.objects.get(image_md5_hash=hash)
|
||||
data = {
|
||||
"status": "success",
|
||||
"id": series_image.pk,
|
||||
"url": series_image.series.get_absolute_url(),
|
||||
}
|
||||
return data
|
||||
except SeriesImage.DoesNotExist:
|
||||
data = {"status": "success", "id": False}
|
||||
return data
|
||||
|
||||
@router.get("/generate_image_hash/{id}", auth=django_auth)
|
||||
def generate_image_hash(request, id: int):
|
||||
series_image = SeriesImage.objects.get(pk=id)
|
||||
|
||||
series_image.image_md5_hash = ""
|
||||
|
||||
series_image.save()
|
||||
|
||||
print(series_image)
|
||||
+44
-4
@@ -1,7 +1,9 @@
|
||||
from django import forms
|
||||
from django.contrib.admin import widgets
|
||||
from django.forms import (
|
||||
BaseInlineFormSet,
|
||||
Form,
|
||||
HiddenInput,
|
||||
ModelForm,
|
||||
ModelMultipleChoiceField,
|
||||
ModelChoiceField,
|
||||
@@ -9,6 +11,7 @@ from django.forms import (
|
||||
CharField,
|
||||
ValidationError,
|
||||
modelformset_factory,
|
||||
CheckboxSelectMultiple
|
||||
)
|
||||
from django.forms import inlineformset_factory
|
||||
from django.shortcuts import get_object_or_404
|
||||
@@ -20,11 +23,15 @@ from atlas.models import (
|
||||
CidReportAnswer,
|
||||
Differential,
|
||||
Finding,
|
||||
SelfReview,
|
||||
Series,
|
||||
SeriesImage,
|
||||
SeriesFinding,
|
||||
Condition,
|
||||
Structure,
|
||||
Subspecialty,
|
||||
UncategorisedDicom,
|
||||
UserReportAnswer,
|
||||
)
|
||||
|
||||
from anatomy.models import Modality
|
||||
@@ -315,6 +322,8 @@ class CaseForm(ModelForm):
|
||||
"presentation": autocomplete.ModelSelect2Multiple(
|
||||
url="atlas:presentation-autocomplete"
|
||||
),
|
||||
"subspecialty": CheckboxSelectMultiple(),
|
||||
"pathological_process": CheckboxSelectMultiple()
|
||||
}
|
||||
|
||||
def save(self, commit=True):
|
||||
@@ -435,10 +444,8 @@ SeriesImageFormSet = inlineformset_factory(
|
||||
max_num=2000,
|
||||
)
|
||||
|
||||
|
||||
class CidReportAnswerForm(ModelForm):
|
||||
class BaseReportAnswerForm(ModelForm):
|
||||
class Meta:
|
||||
model = CidReportAnswer
|
||||
fields = ["answer"]
|
||||
|
||||
widgets = {
|
||||
@@ -455,9 +462,16 @@ class CidReportAnswerForm(ModelForm):
|
||||
# }
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(CidReportAnswerForm, self).__init__(*args, **kwargs)
|
||||
super(BaseReportAnswerForm, self).__init__(*args, **kwargs)
|
||||
self.fields["answer"].required = False
|
||||
|
||||
class CidReportAnswerForm(BaseReportAnswerForm):
|
||||
class Meta(BaseReportAnswerForm.Meta):
|
||||
model = CidReportAnswer
|
||||
|
||||
class UserReportAnswerForm(BaseReportAnswerForm):
|
||||
class Meta(BaseReportAnswerForm.Meta):
|
||||
model = UserReportAnswer
|
||||
|
||||
class CidReportAnswerMarkForm(ModelForm):
|
||||
class Meta:
|
||||
@@ -560,3 +574,29 @@ class AddCollectionToCaseForm(Form):
|
||||
raise ValidationError("Invalid collection")
|
||||
|
||||
return collection_set
|
||||
|
||||
|
||||
class SelfReviewForm(ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = SelfReview
|
||||
fields = ["user_exam", "case", "comments", "findings", "interpretation"]
|
||||
widgets = {"user_exam": HiddenInput(), "case": HiddenInput()}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if "user_exam_id" in kwargs:
|
||||
user_exam_id = kwargs.pop("user_exam_id")
|
||||
if "case_id" in kwargs:
|
||||
case_id = kwargs.pop("case_id")
|
||||
|
||||
ModelForm.__init__(self, *args, **kwargs)
|
||||
super(SelfReviewForm, self).__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class UncategorisedDicomForm(ModelForm):
|
||||
class Meta:
|
||||
model = UncategorisedDicom
|
||||
fields = ["image"]#, "user"]
|
||||
|
||||
|
||||
#UncategorisedDicomFormset = formset_factory(UncategorisedDicomForm)
|
||||
@@ -1,12 +1,11 @@
|
||||
# Generated by Django 3.2.8 on 2021-11-23 19:28
|
||||
# Generated by Django 4.1.4 on 2023-06-12 10:07
|
||||
|
||||
import atlas.models
|
||||
from django.conf import settings
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
import sortedm2m.fields
|
||||
import tagulous.models.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
@@ -14,24 +13,157 @@ class Migration(migrations.Migration):
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('anatomy', '0053_anatomyquestion_structure'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('generic', '0014_alter_questionnote_note'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Case',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('title', models.CharField(default='', help_text='Title of the case', max_length=255)),
|
||||
('description', models.TextField(blank=True, help_text='Description of the case')),
|
||||
('history', models.TextField(blank=True, help_text='A (brief) summary of the relevant history', null=True)),
|
||||
('discussion', models.TextField(blank=True, null=True)),
|
||||
('report', models.TextField(blank=True, help_text='A model (sample) report for the case.', null=True)),
|
||||
('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')),
|
||||
('open_access', models.BooleanField(default=True, help_text='If a case should be freely available to browse')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='CaseCollection',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=255, unique=True)),
|
||||
('publish_results', models.BooleanField(default=False, help_text='If a collection should published')),
|
||||
('active', models.BooleanField(default=True, help_text='If a collection should be available')),
|
||||
('show_title_pre', models.BooleanField(default=False, help_text='Show the title of the cases (pre exam)')),
|
||||
('show_history_pre', models.BooleanField(default=False, help_text='Show the history of the cases (pre exam)')),
|
||||
('show_description_pre', models.BooleanField(default=False, help_text='Show the description of the cases (pre exam)')),
|
||||
('show_discussion_pre', models.BooleanField(default=False, help_text='Show the case discussion (pre exam)')),
|
||||
('show_report_pre', models.BooleanField(default=False, help_text='Show the case report (pre exam)')),
|
||||
('show_title_post', models.BooleanField(default=False, help_text='Show the title of the cases (post exam)')),
|
||||
('show_history_post', models.BooleanField(default=False, help_text='Show the history of the cases (post exam)')),
|
||||
('show_description_post', models.BooleanField(default=False, help_text='Show the description of the cases (post exam)')),
|
||||
('show_discussion_post', models.BooleanField(default=False, help_text='Show the case discussion (post exam)')),
|
||||
('show_report_post', models.BooleanField(default=False, help_text='Show the case report (post exam)')),
|
||||
('archive', models.BooleanField(default=False)),
|
||||
('exam_mode', models.BooleanField(default=False)),
|
||||
('open_access', models.BooleanField(default=False, help_text='If the exam is freely accessible (to view and edit on the test system)')),
|
||||
('collection_type', models.CharField(choices=[('REV', 'Review'), ('REP', 'Report')], default='REP', max_length=3)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='CaseDetail',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('sort_order', models.IntegerField(default=1000)),
|
||||
],
|
||||
options={
|
||||
'ordering': ('sort_order',),
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='CidReportAnswer',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('answer', models.TextField(blank=True)),
|
||||
('feedback', models.TextField(blank=True)),
|
||||
('created', models.DateTimeField(auto_now_add=True)),
|
||||
('updated', models.DateTimeField(auto_now=True)),
|
||||
('score', models.IntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(10), django.core.validators.MinValueValidator(0)])),
|
||||
('cid', models.BigIntegerField(help_text='Candidate ID')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Condition',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=255, unique=True)),
|
||||
('primary', models.BooleanField(default='True')),
|
||||
],
|
||||
bases=(atlas.models.SynMixin, models.Model),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Differential',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('text', models.TextField(blank=True, null=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Finding',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=255, unique=True)),
|
||||
('primary', models.BooleanField(default='True')),
|
||||
],
|
||||
bases=(atlas.models.SynMixin, models.Model),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='PathologicalProcess',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=255)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Presentation',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=255)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Series',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('description', models.TextField(blank=True, help_text='Description of stack, for admin organisation, will not be visible when taking')),
|
||||
('open_access', models.BooleanField(default=True, help_text='If a question should be freely available to browse')),
|
||||
('open_access', models.BooleanField(default=True, help_text='If a series should be freely available to browse')),
|
||||
('author', models.ManyToManyField(blank=True, related_name='series', to=settings.AUTH_USER_MODEL)),
|
||||
('contrast', models.ForeignKey(blank=True, help_text='MRI / CT contrast', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='atlas_series_contrast', to='generic.contrast')),
|
||||
('examination', models.ForeignKey(help_text='Name of the examination', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='atlas_series_examination', to='generic.examination')),
|
||||
('modality', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='atlas_series_modality', to='anatomy.modality')),
|
||||
('plane', models.ForeignKey(blank=True, help_text='Plane of the examination', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='atlas_series_plane', to='generic.plane')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Subspecialty',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=255)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='UserReportAnswer',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('answer', models.TextField(blank=True)),
|
||||
('feedback', models.TextField(blank=True)),
|
||||
('created', models.DateTimeField(auto_now_add=True)),
|
||||
('updated', models.DateTimeField(auto_now=True)),
|
||||
('score', models.IntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(10), django.core.validators.MinValueValidator(0)])),
|
||||
('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='atlas.casedetail')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Structure',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=255, unique=True)),
|
||||
('primary', models.BooleanField(default='True')),
|
||||
('synonym', models.ManyToManyField(blank=True, to='atlas.structure')),
|
||||
],
|
||||
bases=(atlas.models.SynMixin, models.Model),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SeriesImage',
|
||||
@@ -47,22 +179,15 @@ class Migration(migrations.Migration):
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Case',
|
||||
name='SeriesFinding',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('description', models.TextField(blank=True, help_text='Description of the case, for admin organisation, will not be visible when taking')),
|
||||
('history', models.TextField(blank=True, null=True)),
|
||||
('findings', models.TextField(blank=True, null=True)),
|
||||
('subpecialty', models.CharField(choices=[('BR', 'Breast'), ('CA', 'Cardiac'), ('GI', 'Gastrointestinal and hepatobiliary'), ('HN', 'Head and Neck'), ('MS', 'Musculoskeletal'), ('NE', 'Neuroradiology'), ('OG', 'Obstectric and Gynaecological'), ('PA', 'Paediatric'), ('UR', 'Uroradiology'), ('VA', 'Vascular'), ('HA', 'Haemotology and Oncology')], max_length=2)),
|
||||
('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')),
|
||||
('open_access', models.BooleanField(default=True, help_text='If a question should be freely available to browse')),
|
||||
('author', models.ManyToManyField(blank=True, help_text='Author of question', related_name='atlas_authored_questions', to=settings.AUTH_USER_MODEL)),
|
||||
('condition', tagulous.models.fields.TagField(_set_tag_meta=True, blank=True, help_text='Associated condition. Will allow searching / filtering and tips / hints to be displayed. Conditions with spaces must be enclosed in quotes "..."', to='generic.Condition')),
|
||||
('series', sortedm2m.fields.SortedManyToManyField(help_text=None, related_name='atlas', to='atlas.Series')),
|
||||
('sign', tagulous.models.fields.TagField(_set_tag_meta=True, blank=True, help_text='Radiological signs in the question', to='generic.Sign')),
|
||||
('description', models.TextField(blank=True, help_text='Findings on the series / stack', null=True)),
|
||||
('annotation_json', models.TextField(blank=True, null=True)),
|
||||
('viewport_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')),
|
||||
('structures', models.ManyToManyField(blank=True, to='atlas.structure')),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
# Generated by Django 3.2.8 on 2021-11-23 22:40
|
||||
|
||||
from django.db import migrations, models
|
||||
import sortedm2m.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('atlas', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='case',
|
||||
name='title',
|
||||
field=models.CharField(default='', help_text='Title of the case', max_length=255),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='case',
|
||||
name='series',
|
||||
field=sortedm2m.fields.SortedManyToManyField(help_text=None, related_name='case', to='atlas.Series'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,156 @@
|
||||
# Generated by Django 4.1.4 on 2023-06-12 10:07
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import sortedm2m.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('generic', '0001_initial'),
|
||||
('anatomy', '0002_initial'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('atlas', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='series',
|
||||
name='contrast',
|
||||
field=models.ForeignKey(blank=True, help_text='MRI / CT contrast', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='atlas_series_contrast', to='generic.contrast'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='series',
|
||||
name='examination',
|
||||
field=models.ForeignKey(help_text='Name of the examination', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='atlas_series_examination', to='generic.examination'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='series',
|
||||
name='modality',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='atlas_series_modality', to='anatomy.modality'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='series',
|
||||
name='plane',
|
||||
field=models.ForeignKey(blank=True, help_text='Plane of the examination', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='atlas_series_plane', to='generic.plane'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='presentation',
|
||||
name='subspecialty',
|
||||
field=models.ManyToManyField(blank=True, to='atlas.subspecialty'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='finding',
|
||||
name='synonym',
|
||||
field=models.ManyToManyField(blank=True, to='atlas.finding'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='differential',
|
||||
name='case',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='differentialcase', to='atlas.case'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='differential',
|
||||
name='condition',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='atlas.condition'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='condition',
|
||||
name='parent',
|
||||
field=models.ManyToManyField(blank=True, to='atlas.condition'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='condition',
|
||||
name='subspecialty',
|
||||
field=models.ManyToManyField(blank=True, to='atlas.subspecialty'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='condition',
|
||||
name='synonym',
|
||||
field=models.ManyToManyField(blank=True, to='atlas.condition'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='cidreportanswer',
|
||||
name='question',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='atlas.casedetail'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='casedetail',
|
||||
name='case',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='atlas.case'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='casedetail',
|
||||
name='collection',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='atlas.casecollection'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='casecollection',
|
||||
name='author',
|
||||
field=models.ManyToManyField(blank=True, help_text='Author of the collection', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='casecollection',
|
||||
name='cases',
|
||||
field=models.ManyToManyField(through='atlas.CaseDetail', to='atlas.case'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='casecollection',
|
||||
name='cid_user_groups',
|
||||
field=models.ManyToManyField(blank=True, help_text='These groups define which candidates are able to be added to the exams/collection.', to='generic.cidusergroup'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='casecollection',
|
||||
name='valid_cid_users',
|
||||
field=models.ManyToManyField(blank=True, related_name='casecollection_exams', to='generic.ciduser'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='case',
|
||||
name='author',
|
||||
field=models.ManyToManyField(blank=True, help_text='Author of the case', related_name='atlas_authored_cases', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='case',
|
||||
name='condition',
|
||||
field=models.ManyToManyField(blank=True, to='atlas.condition'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='case',
|
||||
name='differential',
|
||||
field=models.ManyToManyField(related_name='casedifferential', through='atlas.Differential', to='atlas.condition'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='case',
|
||||
name='editor',
|
||||
field=models.ManyToManyField(blank=True, related_name='atlas_edited_cases', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='case',
|
||||
name='pathological_process',
|
||||
field=models.ManyToManyField(blank=True, to='atlas.pathologicalprocess'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='case',
|
||||
name='presentation',
|
||||
field=models.ManyToManyField(blank=True, to='atlas.presentation'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='case',
|
||||
name='previous_case',
|
||||
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='next_case', to='atlas.case'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='case',
|
||||
name='series',
|
||||
field=sortedm2m.fields.SortedManyToManyField(help_text=None, related_name='case', to='atlas.series'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='case',
|
||||
name='subspecialty',
|
||||
field=models.ManyToManyField(blank=True, to='atlas.subspecialty'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,29 @@
|
||||
# Generated by Django 4.1.4 on 2023-06-19 10:51
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("generic", "0002_modality_examination_modality"),
|
||||
("atlas", "0002_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.SeparateDatabaseAndState(
|
||||
state_operations=[
|
||||
migrations.AlterField(
|
||||
model_name="series",
|
||||
name="modality",
|
||||
field=models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name="atlas_series_modality",
|
||||
to="generic.modality",
|
||||
),
|
||||
),
|
||||
],
|
||||
database_operations=[],
|
||||
)
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.2.8 on 2021-11-24 18:47
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('atlas', '0002_auto_20211123_2240'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='case',
|
||||
old_name='subpecialty',
|
||||
new_name='subspecialty',
|
||||
),
|
||||
]
|
||||
@@ -1,26 +0,0 @@
|
||||
# Generated by Django 3.2.8 on 2021-11-25 22:16
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('atlas', '0003_rename_subpecialty_case_subspecialty'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Condition',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=255)),
|
||||
('synonym', models.ManyToManyField(blank=True, related_name='_atlas_condition_synonym_+', to='atlas.Condition')),
|
||||
],
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='case',
|
||||
name='condition',
|
||||
field=models.ManyToManyField(blank=True, to='atlas.Condition'),
|
||||
),
|
||||
]
|
||||
+4
-4
@@ -1,4 +1,4 @@
|
||||
# Generated by Django 3.2.10 on 2022-04-01 22:15
|
||||
# Generated by Django 4.1.4 on 2023-07-03 12:52
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
@@ -6,13 +6,13 @@ from django.db import migrations, models
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('atlas', '0034_auto_20220401_2235'),
|
||||
('atlas', '0003_alter_series_modality'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='casecollection',
|
||||
name='show_history',
|
||||
field=models.BooleanField(default=False, help_text='Show the history of the cases'),
|
||||
name='self_review',
|
||||
field=models.BooleanField(default=False, help_text='If true allows users self complete and review cases in a self directed way.'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,36 @@
|
||||
# Generated by Django 4.1.4 on 2023-07-24 09:06
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('generic', '0006_alter_ciduserexam_completed'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('atlas', '0004_casecollection_self_review'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='casecollection',
|
||||
name='user_user_groups',
|
||||
field=models.ManyToManyField(blank=True, help_text='These groups define which candidates are able to be added to the exams/collection.', related_name='casecollection_user_user_groups', to='generic.userusergroup'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='casecollection',
|
||||
name='valid_user_users',
|
||||
field=models.ManyToManyField(blank=True, related_name='user_casecollection_exams', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='casecollection',
|
||||
name='author',
|
||||
field=models.ManyToManyField(blank=True, help_text='Author of the collection', related_name='casecollection_authored_cases', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='casecollection',
|
||||
name='cid_user_groups',
|
||||
field=models.ManyToManyField(blank=True, help_text='These groups define which candidates are able to be added to the exams/collection.', related_name='casecollection_cid_user_groups', to='generic.cidusergroup'),
|
||||
),
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.2.8 on 2021-11-25 22:32
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('atlas', '0004_auto_20211125_2216'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='condition',
|
||||
name='primary_name',
|
||||
field=models.BooleanField(default='True'),
|
||||
),
|
||||
]
|
||||
@@ -1,34 +0,0 @@
|
||||
# Generated by Django 3.2.4 on 2021-11-28 14:48
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('atlas', '0005_condition_primary_name'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Subspecialty',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=255)),
|
||||
],
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='case',
|
||||
name='subspecialty',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='condition',
|
||||
name='subspecialty',
|
||||
field=models.ManyToManyField(blank=True, to='atlas.Subspecialty'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='case',
|
||||
name='subspecialty',
|
||||
field=models.ManyToManyField(blank=True, to='atlas.Subspecialty'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,43 @@
|
||||
# Generated by Django 4.1.4 on 2023-07-24 09:24
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('atlas', '0005_casecollection_user_user_groups_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='casecollection',
|
||||
name='candidates_only',
|
||||
field=models.BooleanField(default=True, help_text='If the exam/collection is only available to candidates who have been added'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='casecollection',
|
||||
name='active',
|
||||
field=models.BooleanField(default=False, help_text='If an exam/collection should be available to take'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='casecollection',
|
||||
name='archive',
|
||||
field=models.BooleanField(default=False, help_text='Archived exams/collections will remain on the test system but will not be displayed by default'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='casecollection',
|
||||
name='name',
|
||||
field=models.CharField(help_text='Name of the exam/collection', max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='casecollection',
|
||||
name='open_access',
|
||||
field=models.BooleanField(default=False, help_text='If the exam/collection is freely accessible (to view and edit on the test system)'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='casecollection',
|
||||
name='publish_results',
|
||||
field=models.BooleanField(default=False, help_text='If an exam/collections results should be available'),
|
||||
),
|
||||
]
|
||||
@@ -1,87 +0,0 @@
|
||||
# Generated by Django 3.2.4 on 2021-11-28 16:22
|
||||
|
||||
import atlas.models
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("atlas", "0006_auto_20211128_1448"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
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",
|
||||
),
|
||||
),
|
||||
],
|
||||
bases=(atlas.models.SynMixin, models.Model),
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="case",
|
||||
name="findings",
|
||||
),
|
||||
migrations.AlterField(
|
||||
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"),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="SeriesFindings",
|
||||
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",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,29 @@
|
||||
# Generated by Django 4.1.4 on 2023-07-24 11:42
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('generic', '0008_delete_selfreview'),
|
||||
('atlas', '0006_casecollection_candidates_only_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='SelfReview',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('comments', models.TextField(blank=True, null=True)),
|
||||
('findings', models.IntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(5), django.core.validators.MinValueValidator(1)])),
|
||||
('interpretation', models.IntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(5), django.core.validators.MinValueValidator(1)])),
|
||||
('review_date', models.DateTimeField(auto_now_add=True)),
|
||||
('review_update_date', models.DateTimeField(auto_now=True)),
|
||||
('case', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='atlas.case')),
|
||||
('user_exam', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='generic.ciduserexam')),
|
||||
],
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,22 @@
|
||||
# Generated by Django 4.1.4 on 2023-08-07 08:14
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('atlas', '0007_selfreview'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='case',
|
||||
name='scrapped',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='case',
|
||||
name='archive',
|
||||
field=models.BooleanField(default=False, help_text='Case has been archived, this will remain on the system but will not be shown'),
|
||||
),
|
||||
]
|
||||
@@ -1,17 +0,0 @@
|
||||
# Generated by Django 3.2.8 on 2021-11-29 19:10
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('atlas', '0007_auto_20211128_1622'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameModel(
|
||||
old_name='SeriesFindings',
|
||||
new_name='SeriesFinding',
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.1.4 on 2023-08-07 21:00
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('atlas', '0008_remove_case_scrapped_case_archive'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='series',
|
||||
old_name='description',
|
||||
new_name='info',
|
||||
),
|
||||
]
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user