more improvements

This commit is contained in:
Ross
2021-02-04 10:30:56 +00:00
parent b681a27640
commit cd013f2ff3
32 changed files with 247 additions and 324 deletions
+6 -1
View File
@@ -6,6 +6,9 @@ import cv2
import os import os
import glob import glob
from pathlib import Path
def ocr_file(filename): def ocr_file(filename):
# load the example image and convert it to grayscale # load the example image and convert it to grayscale
image = cv2.imread(filename) image = cv2.imread(filename)
@@ -95,6 +98,8 @@ def search_image(file_name):
edit_path = "{}/test/".format(path) edit_path = "{}/test/".format(path)
Path(edit_path).mkdir(parents=True, exist_ok=True)
print(edit_path) print(edit_path)
fn1, fn2 = fn.rsplit(".", 1) fn1, fn2 = fn.rsplit(".", 1)
cv2.imwrite("{}{}_new.{}".format(edit_path, fn1, fn2), img) cv2.imwrite("{}{}_new.{}".format(edit_path, fn1, fn2), img)
@@ -126,7 +131,7 @@ image_list = []
file_types = ("gif", "jpg", "jpeg", "png") file_types = ("gif", "jpg", "jpeg", "png")
for file_type in file_types: for file_type in file_types:
for filename in glob.glob('/Users/ross/media/test/*.{}'.format(file_type)): #assuming gif for filename in glob.glob('/home/ross/scripts/sites/backups/New/media/rapids/*.{}'.format(file_type)): #assuming gif
image_list.append(filename) image_list.append(filename)
for f in image_list: for f in image_list:
+8 -24
View File
@@ -1,5 +1,5 @@
from django.contrib import admin from django.contrib import admin
from .models import Long, LongImage, Examination, Site, Abnormality, Region, Note, LongCreationDefault, Answer, Exam from .models import Long, LongSeries, LongSeriesImage, Examination, Site, Note, LongCreationDefault, Exam
import tagulous.admin import tagulous.admin
@@ -12,23 +12,18 @@ from django.forms.widgets import RadioSelect
admin.site.register(Examination) admin.site.register(Examination)
admin.site.register(Site) admin.site.register(Site)
admin.site.register(Exam) admin.site.register(Exam)
admin.site.register(Abnormality)
admin.site.register(Region)
admin.site.register(Note) admin.site.register(Note)
admin.site.register(LongCreationDefault) admin.site.register(LongCreationDefault)
admin.site.register(Answer) admin.site.register(LongSeries)
admin.site.register(LongSeriesImage)
class LongAnswersInline(admin.TabularInline):
model = Answer
extra = 1
class LongImageInline(admin.TabularInline): class LongImageInline(admin.TabularInline):
model = LongImage model = LongSeries
extra = 1 extra = 1
readonly_fields = [ # readonly_fields = [
"image_tag", # "image_tag",
] # ]
class ExamInline(admin.TabularInline): class ExamInline(admin.TabularInline):
model = Long.exams.through model = Long.exams.through
@@ -40,30 +35,19 @@ class LongAdminForm(ModelForm):
model = Long model = Long
fields = [ fields = [
"normal", "abnormality", "region", "laterality", "examination", "site", "sign", "feedback", "author"
"site", "sign", "condition", "feedback", "author"
] ]
widgets = {
"laterality": RadioSelect(attrs={'style': 'display: inline-flex'}),
}
class LongAdmin(VersionAdmin): class LongAdmin(VersionAdmin):
form = LongAdminForm form = LongAdminForm
filter_horizontal = (
"abnormality",
"region",
#"examination",
)
save_on_top = True save_on_top = True
save_as = True save_as = True
view_on_site = True view_on_site = True
inlines = [ inlines = [
LongImageInline, LongImageInline,
LongAnswersInline,
ExamInline, ExamInline,
] ]
+1 -2
View File
@@ -6,5 +6,4 @@ from .models import Long
class LongFilter(django_filters.FilterSet): class LongFilter(django_filters.FilterSet):
class Meta: class Meta:
model = Long model = Long
fields = ("normal", "abnormality", "region", "examination", fields = ("site", "created_date", "author")
"laterality", "site", "created_date", "author")
+10 -74
View File
@@ -9,14 +9,12 @@ from django.forms import (
from django.forms import inlineformset_factory from django.forms import inlineformset_factory
from longs.models import ( from longs.models import (
Abnormality,
Examination, Examination,
Note, Note,
Long, Long,
LongSeries,
LongSeriesImage,
LongCreationDefault, LongCreationDefault,
LongImage,
Region,
Answer,
CidUserAnswer, CidUserAnswer,
Exam, Exam,
) )
@@ -28,7 +26,7 @@ from django.forms.widgets import RadioSelect, TextInput, Textarea
class LongAnswerForm(ModelForm): class LongAnswerForm(ModelForm):
class Meta: class Meta:
model = CidUserAnswer model = CidUserAnswer
fields = ("answer",) fields = ("answer_observations","answer_interpretation","answer_principle_diagnosis","answer_differential_diagnosis","answer_further_management",)
class MarkLongQuestionForm(Form): class MarkLongQuestionForm(Form):
@@ -50,17 +48,6 @@ class NoteForm(ModelForm):
fields = ["note"] fields = ["note"]
class RegionForm(ModelForm):
class Meta:
model = Region
fields = ["name"]
class AbnormalityForm(ModelForm):
class Meta:
model = Abnormality
fields = ["name"]
class LongCreationDefaultForm(ModelForm): class LongCreationDefaultForm(ModelForm):
class Meta: class Meta:
@@ -85,37 +72,17 @@ class LongForm(ModelForm):
super(LongForm, self).__init__(*args, **kwargs) super(LongForm, self).__init__(*args, **kwargs)
# self.fields['question'].widget.attrs = {'class': 'question-form', 'rows': 10, 'cols': 100} # self.fields['question'].widget.attrs = {'class': 'question-form', 'rows': 10, 'cols': 100}
# self.fields['feedback'].widget.attrs = {'class': 'feedback-form', 'rows': 10, 'cols': 100} # self.fields['feedback'].widget.attrs = {'class': 'feedback-form', 'rows': 10, 'cols': 100}
self.fields["abnormality"] = ModelMultipleChoiceField( #self.fields["examination"] = ModelMultipleChoiceField(
required=False, # queryset=Examination.objects.all(),
queryset=Abnormality.objects.all(), # widget=FilteredSelectMultiple(verbose_name="Examination", is_stacked=False),
widget=FilteredSelectMultiple(verbose_name="Abnormality", is_stacked=False), #)
)
self.fields["region"] = ModelMultipleChoiceField(
required=False,
queryset=Region.objects.all(),
widget=FilteredSelectMultiple(verbose_name="Region", is_stacked=False),
)
self.fields["examination"] = ModelMultipleChoiceField(
queryset=Examination.objects.all(),
widget=FilteredSelectMultiple(verbose_name="Examination", is_stacked=False),
)
self.fields["laterality"] = ChoiceField(
choices=Long.LATERALITY_CHOICES, required=True, widget=RadioSelect()
)
class Meta: class Meta:
model = Long model = Long
# fields = ['due_back'] # fields = ['due_back']
# fields = '__all__' # fields = '__all__'
fields = [ fields = [
"normal", #"examination",
"abnormality",
"region",
"laterality",
"examination",
"site", "site",
"feedback", "feedback",
] ]
@@ -127,43 +94,12 @@ class LongForm(ModelForm):
} }
ImageFormSet = inlineformset_factory( SeriesFormSet = inlineformset_factory(
Long, Long,
LongImage, LongSeries,
fields=["image", "feedback_image"],
exclude=[], exclude=[],
can_delete=True, can_delete=True,
extra=4, extra=4,
max_num=10, max_num=10,
field_classes="testing", field_classes="testing",
) )
AnswerFormSet = inlineformset_factory(
Long,
Answer,
fields=["answer", "status"],
widgets={
"answer": Textarea(
attrs={"required": "true", "minlength": 2, "maxlength": 500, "rows": 3}
)
},
exclude=[],
can_delete=True,
extra=1,
max_num=10,
)
AnswerUpdateFormSet = inlineformset_factory(
Long,
Answer,
fields=["answer", "status"],
widgets={
"answer": Textarea(
attrs={"required": "true", "minlength": 2, "maxlength": 500, "rows": 3}
)
},
exclude=[],
can_delete=True,
extra=0,
max_num=10,
)
+155
View File
@@ -0,0 +1,155 @@
# Generated by Django 3.1.3 on 2021-02-02 19:46
from django.conf import settings
import django.core.files.storage
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
import longs.models
import sortedm2m.fields
import tagulous.models.models
class Migration(migrations.Migration):
initial = True
dependencies = [
('anatomy', '0024_auto_20210130_1515'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Examination',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('examination', models.CharField(max_length=200)),
],
options={
'ordering': ('examination',),
},
),
migrations.CreateModel(
name='Long',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('question', models.TextField(blank=True, null=True)),
('feedback', models.TextField(blank=True, null=True)),
('sign', models.CharField(blank=True, max_length=255)),
('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 an question should be freely available to browse')),
('author', models.ManyToManyField(blank=True, help_text='Author of question', related_name='long_authored_questions', to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='LongSeries',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('examination', models.ForeignKey(help_text='Name of the examination', null=True, on_delete=django.db.models.deletion.SET_NULL, to='longs.examination')),
('long', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='long', to='longs.long')),
('modality', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='series_modality', to='anatomy.modality')),
],
),
migrations.CreateModel(
name='Site',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('site', models.CharField(max_length=200)),
('initials', models.CharField(max_length=200)),
],
),
migrations.CreateModel(
name='Sign',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, unique=True)),
('slug', models.SlugField()),
('count', models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use')),
('protected', models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0')),
],
options={
'ordering': ('name',),
'abstract': False,
'unique_together': {('slug',)},
},
bases=(tagulous.models.models.BaseTagModel, models.Model),
),
migrations.CreateModel(
name='Note',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('note', models.TextField()),
('created_on', models.DateTimeField(auto_now_add=True)),
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='long_notes', to=settings.AUTH_USER_MODEL)),
('long', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='long_notes', to='longs.long')),
],
),
migrations.CreateModel(
name='LongSeriesImage',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('image', models.ImageField(storage=django.core.files.storage.FileSystemStorage(base_url='/media/longs/', location='/home/ross/scripts/sites/rad/media//longs/'), upload_to=longs.models.image_directory_path)),
('position', models.IntegerField(default=0)),
('series', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='series', to='longs.longseries')),
],
),
migrations.CreateModel(
name='LongCreationDefault',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('author', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='long_default', to=settings.AUTH_USER_MODEL)),
('site', models.ManyToManyField(blank=True, default=1, help_text='Default site to use when creating a new long', to='longs.Site')),
],
),
migrations.AddField(
model_name='long',
name='site',
field=models.ManyToManyField(blank=True, default=1, help_text='If we know the source of the image', to='longs.Site'),
),
migrations.CreateModel(
name='Exam',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=200)),
('active', models.BooleanField(default=True, help_text='If an exam should be available')),
('publish_results', models.BooleanField(default=True, help_text='If an exams results should be available')),
('recreate_json', models.BooleanField(default=False, help_text='If the json cache needs updating')),
('time_limit', models.IntegerField(default=2100, help_text='Exam time limit (in seconds). Default is 2100 secondse (35 minutes)')),
('exam_questions', sortedm2m.fields.SortedManyToManyField(blank='true', help_text=None, related_name='exams', to='longs.Long')),
],
),
migrations.CreateModel(
name='Condition',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, unique=True)),
('slug', models.SlugField()),
('count', models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use')),
('protected', models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0')),
],
options={
'ordering': ('name',),
'abstract': False,
'unique_together': {('slug',)},
},
bases=(tagulous.models.models.BaseTagModel, models.Model),
),
migrations.CreateModel(
name='CidUserAnswer',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('normal', models.BooleanField(default=False)),
('answer', models.TextField(blank=True, max_length=500)),
('answer_compare', models.TextField(blank=True, max_length=500)),
('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)),
('exam', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cid_user_answers', to='longs.exam')),
('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='cid_user_answers', to='longs.long')),
],
),
]
+1
View File
@@ -0,0 +1 @@
+43 -177
View File
@@ -1,3 +1,6 @@
from django.db.models.fields.files import ImageField
from django.db.models.fields.related import ForeignKey
from anatomy.models import Modality
from django.db import models from django.db import models
from django.utils import timezone from django.utils import timezone
import tagulous import tagulous
@@ -29,32 +32,6 @@ def image_directory_path(instance, filename):
class Abnormality(models.Model):
name = models.CharField(max_length=200,
unique=True,
help_text="Primary abnormality on the film(s)")
def __str__(self):
return self.name
class Meta:
ordering = ('name', )
class Region(models.Model):
name = models.CharField(
max_length=200,
unique=True,
help_text="Region of the abnormality (not including lateralitiy)",
blank=True)
def __str__(self):
return self.name
class Meta:
ordering = ('name', )
class Examination(models.Model): class Examination(models.Model):
examination = models.CharField(max_length=200) examination = models.CharField(max_length=200)
@@ -79,39 +56,6 @@ class Condition(tagulous.models.TagModel):
class Sign(tagulous.models.TagModel): class Sign(tagulous.models.TagModel):
pass pass
class Answer(models.Model):
question = models.ForeignKey(
"Long", related_name="answers", on_delete=models.CASCADE
)
answer = models.TextField(max_length=500)
answer_compare = models.TextField(max_length=500)
class MarkOptions(models.TextChoices):
UNMARKED = "", _("Unmarked")
INCORRECT = "0", _("Incorrect")
HALF_MARK = "1", _("Half mark")
CORRECT = "2", _("Correct")
status = models.CharField(
max_length=1, choices=MarkOptions.choices, default=MarkOptions.UNMARKED
)
def __str__(self):
return self.answer
def save(self, *args, **kwargs):
self.clean()
return super(Answer, self).save(*args, **kwargs)
def clean(self):
if self.answer:
self.answer = self.answer.strip()
s = self.answer.lower()
s = s.translate(str.maketrans('', '', string.punctuation))
self.answer_compare = s
class Long(models.Model): class Long(models.Model):
#author = models.ForeignKey('auth.User', on_delete=models.CASCADE) #author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
@@ -119,37 +63,6 @@ class Long(models.Model):
question = models.TextField(null=True, blank=True) question = models.TextField(null=True, blank=True)
feedback = models.TextField(null=True, blank=True) feedback = models.TextField(null=True, blank=True)
normal = models.BooleanField(default=False, help_text="Tick if true")
NONE = "NONE"
LEFT = "LEFT"
RIGHT = "RIGHT"
BILATERAL = "BILAT"
LATERALITY_CHOICES = (
(NONE, "None"),
(LEFT, "Left"),
(RIGHT, "Right"),
(BILATERAL, "Bilateral"),
)
abnormality = models.ManyToManyField(
Abnormality,
blank=True,
help_text="The abnormality (laterality and region independent). Used for categorisation but does not affect the answer",
)
region = models.ManyToManyField(
Region,
blank=True,
help_text="Region of the abnormality (laterality independent)")
examination = models.ManyToManyField(
Examination, help_text="Name of the (primary) examination")
laterality = models.CharField(
max_length=20,
choices=LATERALITY_CHOICES,
default=NONE,
help_text="Applies to the answer, not the examination")
condition = models.CharField(max_length=255, blank=True)
#condition = tagulous.models.TagField( #condition = tagulous.models.TagField(
# to=Condition, # to=Condition,
# blank=True, # blank=True,
@@ -161,6 +74,14 @@ class Long(models.Model):
#sign = tagulous.models.TagField( #sign = tagulous.models.TagField(
# to=Sign, blank=True, help_text='Radiological signs in the question') # to=Sign, blank=True, help_text='Radiological signs in the question')
# Model answers
model_observations = models.TextField(null=True, blank=True)
model_interpretation = models.TextField(null=True, blank=True)
model_principle_diagnosis = models.TextField(null=True, blank=True)
model_differential_diagnosis = models.TextField(null=True, blank=True)
model_further_management = models.TextField(null=True, blank=True)
DEFAULT_SITE_ID = 1 DEFAULT_SITE_ID = 1
site = models.ManyToManyField( site = models.ManyToManyField(
Site, Site,
@@ -193,91 +114,23 @@ class Long(models.Model):
authors = ", ".join([i.username for i in self.author.all()]) authors = ", ".join([i.username for i in self.author.all()])
return authors return authors
def get_regions(self):
"""Returns a comma seperated text list of regions"""
regions = ", ".join([i.name for i in self.region.all()])
return regions
def get_abnormalities(self):
"""Returns a comma seperated text list of regions"""
abnormalities = ", ".join([i.name for i in self.abnormality.all()])
return abnormalities
def get_examinations(self): def get_examinations(self):
"""Returns a comma seperated text list of regions""" """Returns a comma seperated text list of regions"""
examinations = ", ".join([i.examination for i in self.examination.all()]) examinations = ", ".join([i.examination for i in self.examination.all()])
return examinations return examinations
def __str__(self): def __str__(self):
n = "Normal"
if not self.normal:
#n = self.answers.first()
n = "{} / {}".format(self.abnormality.first(), self.region.first())
exams = self.get_examinations() exams = self.get_examinations()
lat = "" lat = ""
if self.laterality != "NONE": if self.laterality != "NONE":
lat = self.laterality lat = self.laterality
return "{} / {} {}".format(exams, lat, n) return "{} / {} {}".format(exams, lat, n)
def GetPrimaryAnswer(self):
if len(self.answers.all()) > 0:
return self.answers.all().first().answer
elif self.normal:
return "Normal"
else:
return "None yet..."
def GetExams(self): def GetExams(self):
e = self.exams.all().values_list("name", flat=True) e = self.exams.all().values_list("name", flat=True)
exams = ", ".join(e) exams = ", ".join(e)
return exams return exams
def GetUnmarkedAnswersString(self):
unmarked_answers = self.GetUnmarkedAnswers()
if not unmarked_answers:
return "No answers to mark"
return format_html(
"<span class='warn'>{} answer unmarked:</span> {}".format(
len(unmarked_answers), ", ".join(unmarked_answers)
)
)
def GetUnmarkedAnswers(self):
# If normal no answers to mark
if self.normal:
return []
user_answers = set(
[i.answer_compare for i in self.cid_user_answers.all() if i.normal == False]
)
unmarked_answers = user_answers - self.GetMarkedAnswers()
return unmarked_answers
def GetUnmarkedAnswerCount(self):
return len(self.GetUnmarkedAnswers())
def GetMarkedAnswers(self):
return set(
[
i.answer_compare
for i in self.answers.all()
if i.status != i.MarkOptions.UNMARKED
]
)
correct_answers = set(
[i.answer.get_compare_string() for i in self.answers.all()]
)
half_mark_answers = set(
[i.answer.get_compare_string() for i in self.half_mark_answers.all()]
)
incorrect_answers = set(
[i.answer.get_compare_string() for i in self.incorrect_answers.all()]
)
marked_answers = correct_answers | half_mark_answers | incorrect_answers
return marked_answers
def GetImages(self, feedback=False): def GetImages(self, feedback=False):
qs = self.images.all() qs = self.images.all()
@@ -294,24 +147,34 @@ class Long(models.Model):
#def GetNonFeedbackQuestionImages(self): #def GetNonFeedbackQuestionImages(self):
#return self.GetImages() #return self.GetImages()
class LongSeriesImage(models.Model):
class LongImage(models.Model):
long = models.ForeignKey(Long,
related_name="images",
on_delete=models.CASCADE)
image = models.ImageField(upload_to=image_directory_path, storage=image_storage) image = models.ImageField(upload_to=image_directory_path, storage=image_storage)
position = models.IntegerField(default=0)
series = models.ForeignKey("LongSeries", related_name="series", on_delete=models.SET_NULL, null=True)
feedback_image = models.BooleanField(default=False) class LongSeries(models.Model):
modality = models.ForeignKey(Modality, related_name="series_modality", on_delete=models.SET_NULL, null=True)
examination = models.ForeignKey(
Examination, help_text="Name of the examination", on_delete=models.SET_NULL, null=True)
long = models.ForeignKey("Long", related_name="long", on_delete=models.SET_NULL, null=True)
def image_tag(self): #class LongImage(models.Model):
if self.image: # long = models.ForeignKey(Long,
return mark_safe( # related_name="images",
'<img src="{}" class="admin-long-image" /><span class="admin-long-image-info">Click and hold to zoom<span>' # on_delete=models.CASCADE)
.format(self.image.url)) # image = models.ImageField(upload_to=image_directory_path, storage=image_storage)
else: #
return "" # feedback_image = models.BooleanField(default=False)
#
image_tag.short_description = 'Image' # def image_tag(self):
# if self.image:
# return mark_safe(
# '<img src="{}" class="admin-long-image" /><span class="admin-long-image-info">Click and hold to zoom<span>'
# .format(self.image.url))
# else:
# return ""
#
# image_tag.short_description = 'Image'
class Note(models.Model): class Note(models.Model):
@@ -395,11 +258,14 @@ class CidUserAnswer(models.Model):
Long, related_name="cid_user_answers", on_delete=models.CASCADE Long, related_name="cid_user_answers", on_delete=models.CASCADE
) )
# For longs the answer can be normal in which case the below field is true
normal = models.BooleanField(default=False)
answer = models.TextField(max_length=500, blank=True)
answer_compare = models.TextField(max_length=500, blank=True) # Answers
answer_observations = models.TextField(null=True, blank=True)
answer_interpretation = models.TextField(null=True, blank=True)
answer_principle_diagnosis = models.TextField(null=True, blank=True)
answer_differential_diagnosis = models.TextField(null=True, blank=True)
answer_further_management = models.TextField(null=True, blank=True)
cid = models.BigIntegerField(blank=True, null=True, help_text="Candidate ID (limitied by BigIntegerField size)") cid = models.BigIntegerField(blank=True, null=True, help_text="Candidate ID (limitied by BigIntegerField size)")
+20 -46
View File
@@ -21,22 +21,15 @@ from django.http import HttpResponseRedirect, HttpResponse
from .forms import ( from .forms import (
LongForm, LongForm,
MarkLongQuestionForm, MarkLongQuestionForm,
ImageFormSet, SeriesFormSet,
NoteForm, NoteForm,
RegionForm,
AbnormalityForm,
ExaminationForm, ExaminationForm,
AnswerFormSet,
AnswerUpdateFormSet,
) )
from .models import ( from .models import (
Long, Long,
Note, Note,
Abnormality,
Region,
Examination, Examination,
Exam, Exam,
Answer,
CidUserAnswer, CidUserAnswer,
) )
from .tables import LongTable from .tables import LongTable
@@ -236,28 +229,24 @@ def long_clone(request, pk):
form = LongForm(request.POST or None, instance=new_item) form = LongForm(request.POST or None, instance=new_item)
image_formset = ImageFormSet() series_formset = SeriesFormSet()
answer_formset = AnswerFormSet()
if form.is_valid(): if form.is_valid():
form.instance.author.add(request.user.id) form.instance.author.add(request.user.id)
# logger.debug(formset.is_valid()) # logger.debug(formset.is_valid())
if image_formset.is_valid() and answer_formset.is_valid(): if series_formset.is_valid():
response = super().form_valid(form) response = super().form_valid(form)
image_formset.instance = obj series_formset.instance = obj
image_formset.save() series_formset.save()
answer_formset.instance = obj
answer_formset.save()
return response return response
else: else:
return super().form_invalid(form) return super().form_invalid(form)
context = { context = {
"form": form, "form": form,
"image_formset": image_formset, "series_formset": series_formset,
"answer_formset": answer_formset
# other context # other context
} }
@@ -271,15 +260,12 @@ class LongCreateBase(LoginRequiredMixin, CreateView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(LongCreateBase, self).get_context_data(**kwargs) context = super(LongCreateBase, self).get_context_data(**kwargs)
if self.request.POST: if self.request.POST:
context["image_formset"] = ImageFormSet( context["series_formset"] = SeriesFormSet(
self.request.POST, self.request.FILES self.request.POST, self.request.FILES
) )
context["image_formset"].full_clean() context["series_formset"].full_clean()
context["answer_formset"] = AnswerFormSet(self.request.POST)
context["answer_formset"].full_clean()
else: else:
context["image_formset"] = ImageFormSet() context["series_formset"] = SeriesFormSet()
context["answer_formset"] = AnswerFormSet()
return context return context
def form_valid(self, form): def form_valid(self, form):
@@ -290,14 +276,11 @@ class LongCreateBase(LoginRequiredMixin, CreateView):
form.instance.author.add(self.request.user.id) form.instance.author.add(self.request.user.id)
context = self.get_context_data(form=form) context = self.get_context_data(form=form)
image_formset = context["image_formset"] series_formset = context["series_formset"]
answer_formset = context["answer_formset"] if series_formset.is_valid():
if image_formset.is_valid() and answer_formset.is_valid():
response = super().form_valid(form) response = super().form_valid(form)
image_formset.instance = self.object series_formset.instance = self.object
image_formset.save() series_formset.save()
answer_formset.instance = self.object
answer_formset.save()
# If the normal submit button is pressed we save as normal # If the normal submit button is pressed we save as normal
if "submit" in self.request.POST: if "submit" in self.request.POST:
return response return response
@@ -312,7 +295,6 @@ class LongCreateBase(LoginRequiredMixin, CreateView):
# @login_required # @login_required
class LongCreate(LongCreateBase): class LongCreate(LongCreateBase):
initial = {"laterality": Long.NONE}
def get_initial(self): def get_initial(self):
# There has to be a better way... # There has to be a better way...
@@ -346,17 +328,12 @@ class LongUpdate(LoginRequiredMixin, AuthorOrCheckerRequiredMixin, UpdateView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(LongUpdate, self).get_context_data(**kwargs) context = super(LongUpdate, self).get_context_data(**kwargs)
if self.request.POST: if self.request.POST:
context["image_formset"] = ImageFormSet( context["series_formset"] = SeriesFormSet(
self.request.POST, self.request.FILES, instance=self.object self.request.POST, self.request.FILES, instance=self.object
) )
context["image_formset"].full_clean() context["series_formset"].full_clean()
context["answer_formset"] = AnswerFormSet(
self.request.POST, instance=self.object
)
context["answer_formset"].full_clean()
else: else:
context["image_formset"] = ImageFormSet(instance=self.object) context["series_formset"] = SeriesFormSet(instance=self.object)
context["answer_formset"] = AnswerFormSet(instance=self.object)
return context return context
def form_valid(self, form): def form_valid(self, form):
@@ -367,15 +344,12 @@ class LongUpdate(LoginRequiredMixin, AuthorOrCheckerRequiredMixin, UpdateView):
form.instance.author.add(self.request.user.id) form.instance.author.add(self.request.user.id)
context = self.get_context_data(form=form) context = self.get_context_data(form=form)
image_formset = context["image_formset"] series_formset = context["series_formset"]
answer_formset = context["answer_formset"]
# logger.debug(formset.is_valid()) # logger.debug(formset.is_valid())
if image_formset.is_valid() and answer_formset.is_valid(): if series_formset.is_valid():
response = super().form_valid(form) response = super().form_valid(form)
image_formset.instance = self.object series_formset.instance = self.object
image_formset.save() series_formset.save()
answer_formset.instance = self.object
answer_formset.save()
return response return response
else: else:
return super().form_invalid(form) return super().form_invalid(form)
+1
View File
@@ -33,6 +33,7 @@ INSTALLED_APPS = [
'anatomy', 'anatomy',
'physics', 'physics',
'rapids', 'rapids',
'longs',
"reversion", "reversion",
"django_tables2", "django_tables2",
"django_filters", "django_filters",
+1
View File
@@ -28,6 +28,7 @@ urlpatterns = [
path("physics/", include("physics.urls"), name="physics"), path("physics/", include("physics.urls"), name="physics"),
#path("sbas/", include("sbas.urls"), name="sbas"), #path("sbas/", include("sbas.urls"), name="sbas"),
path("rapids/", include("rapids.urls"), name="rapids"), path("rapids/", include("rapids.urls"), name="rapids"),
path("longs/", include("longs.urls"), name="longs"),
path("accounts/", include("django.contrib.auth.urls")), path("accounts/", include("django.contrib.auth.urls")),
path("accounts/profile", views.profile, name="profile"), path("accounts/profile", views.profile, name="profile"),
path("", TemplateView.as_view(template_name="index.html"), name="home"), path("", TemplateView.as_view(template_name="index.html"), name="home"),
+1
View File
@@ -25,6 +25,7 @@ image_storage = FileSystemStorage(
) )
def image_directory_path(instance, filename): def image_directory_path(instance, filename):
return u"{0}".format(filename)
return u"picture/{0}".format(filename) return u"picture/{0}".format(filename)
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 446 B