few fixes towards functional status
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
media/
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
# Generated by Django 3.1.2 on 2020-10-16 19: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
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
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)),
|
||||||
|
('created_date', models.DateTimeField(default=django.utils.timezone.now)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='BodyPart',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('bodypart', models.CharField(max_length=200)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
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)),
|
||||||
|
('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)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Modality',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('modality', models.CharField(max_length=200)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='QuestionType',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('text', models.CharField(max_length=400)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
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)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
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)),
|
||||||
|
('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='anatomy.exam')),
|
||||||
|
('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='cid_user_answers', to='anatomy.anatomyquestion')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
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'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# 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'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -171,6 +171,8 @@ class Exam(models.Model):
|
|||||||
exam_questions = models.ManyToManyField(AnatomyQuestion,
|
exam_questions = models.ManyToManyField(AnatomyQuestion,
|
||||||
related_name="exams")
|
related_name="exams")
|
||||||
|
|
||||||
|
active = models.BooleanField(help_text="If an exam should be available", default=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
console.log(data.flagged);
|
console.log(data.flagged);
|
||||||
if (data.flagged) {
|
if(data.flagged) {
|
||||||
$("#flagged-button").text("Flagged");
|
$("#flagged-button").text("Flagged");
|
||||||
$("#flagged-button").attr("class", "flagged");
|
$("#flagged-button").attr("class", "flagged");
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
});
|
});
|
||||||
$("#id_answer").keyup(function (event) {
|
$("#id_answer").keyup(function (event) {
|
||||||
if (event.keyCode == 13) {
|
if(event.keyCode == 13) {
|
||||||
$(".btn-default").click();
|
$(".btn-default").click();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
<ul id=question-list>
|
<ul id=question-list>
|
||||||
{% for question in questions %}
|
{% for question in questions %}
|
||||||
<li><a class={% if question.pk in answered_questions %}answered{% else %}unanswered{% endif %}
|
<li><a class={% if question.pk in answered_questions %}answered{% else %}unanswered{% endif %}
|
||||||
href="{% url 'exam' pk=exam.pk sk=forloop.counter0 %}">{{ forloop.counter }}{% if question.pk in flagged_questions %}!{% endif %}</a>
|
href="{% url 'anatomy:exam_take' pk=exam.pk sk=forloop.counter0 %}">{{ forloop.counter }}{% if question.pk in flagged_questions %}!{% endif %}</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,6 @@
|
|||||||
<div class="anatomy">
|
<div class="anatomy">
|
||||||
<h1>{{ exam.name }}</h1>
|
<h1>{{ exam.name }}</h1>
|
||||||
This exam has {{question_number}} questions.
|
This exam has {{question_number}} questions.
|
||||||
<p><button><a href="{% url 'anatomy:exam' pk=exam.pk sk=0 %}">Click here to start</a></button></p>
|
<p><button><a href="{% url 'anatomy:exam_take' pk=exam.pk sk=0 %}">Click here to start</a></button></p>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
+7
-3
@@ -7,14 +7,18 @@ urlpatterns = [
|
|||||||
# path('', views.question_list, name='question_list'),
|
# path('', views.question_list, name='question_list'),
|
||||||
path("", views.index, name="index"),
|
path("", views.index, name="index"),
|
||||||
path("question/<int:pk>/", views.question_detail, name="question_detail"),
|
path("question/<int:pk>/", views.question_detail, name="question_detail"),
|
||||||
path("question/<int:pk>/answer/", views.answer_question, name="answer_question"),
|
path("question/<int:pk>/answer/",
|
||||||
|
views.answer_question,
|
||||||
|
name="answer_question"),
|
||||||
path("exam/<int:pk>/<int:sk>/mark", views.mark, name="mark"),
|
path("exam/<int:pk>/<int:sk>/mark", views.mark, name="mark"),
|
||||||
path("exam/<int:pk>/mark", views.mark_overview, name="mark_overview"),
|
path("exam/<int:pk>/mark", views.mark_overview, name="mark_overview"),
|
||||||
path("exam/<int:pk>/<int:sk>/", views.exam, name="exam"),
|
path("exam/<int:pk>/<int:sk>/", views.exam_take, name="exam_take"),
|
||||||
path("exam/<int:pk>/", views.exam_overview, name="exam_overview"),
|
path("exam/<int:pk>/", views.exam_overview, name="exam_overview"),
|
||||||
path("exam/<int:pk>/scores", views.exam_scores_cid, name="exam_scores_cid"),
|
path("exam/<int:pk>/scores", views.exam_scores_cid,
|
||||||
|
name="exam_scores_cid"),
|
||||||
path("exam/<int:pk>/json", views.exam_json, name="exam_json"),
|
path("exam/<int:pk>/json", views.exam_json, name="exam_json"),
|
||||||
path("submit_answers", views.postExamAnswers, name="exam_answers_submit"),
|
path("submit_answers", views.postExamAnswers, name="exam_answers_submit"),
|
||||||
path("exam/", views.exam_list, name="exam_list"),
|
path("exam/", views.exam_list, name="exam_list"),
|
||||||
|
path("active_exams/", views.active_exams, name="active_exams"),
|
||||||
path("ajax/exam/flag/", views.flag_question, name="flag_question"),
|
path("ajax/exam/flag/", views.flag_question, name="flag_question"),
|
||||||
]
|
]
|
||||||
|
|||||||
+60
-45
@@ -12,6 +12,7 @@ from .forms import AnatomyAnswerForm, MarkAnatomyQuestionForm
|
|||||||
from .models import (
|
from .models import (
|
||||||
AnatomyQuestion,
|
AnatomyQuestion,
|
||||||
CidUserAnswer,
|
CidUserAnswer,
|
||||||
|
UserAnswer,
|
||||||
Exam,
|
Exam,
|
||||||
Answers,
|
Answers,
|
||||||
HalfMarkAnswers,
|
HalfMarkAnswers,
|
||||||
@@ -40,7 +41,8 @@ def image_as_base64(image_file):
|
|||||||
# encoded_string = base64.b64encode(img_f.read())
|
# encoded_string = base64.b64encode(img_f.read())
|
||||||
encoded_string = base64.b64encode(image_file.file.read())
|
encoded_string = base64.b64encode(image_file.file.read())
|
||||||
mimetype, enc = mimetypes.guess_type(image_file.path)
|
mimetype, enc = mimetypes.guess_type(image_file.path)
|
||||||
return "data:image/{};base64,{}".format(mimetype, encoded_string.decode("utf-8"))
|
return "data:image/{};base64,{}".format(mimetype,
|
||||||
|
encoded_string.decode("utf-8"))
|
||||||
|
|
||||||
|
|
||||||
from django.template.defaulttags import register
|
from django.template.defaulttags import register
|
||||||
@@ -60,7 +62,8 @@ def user_is_admin(user):
|
|||||||
|
|
||||||
def question_list(request):
|
def question_list(request):
|
||||||
questions = AnatomyQuestion.objects.all()
|
questions = AnatomyQuestion.objects.all()
|
||||||
return render(request, "anatomy/question_list.html", {"questions": questions})
|
return render(request, "anatomy/question_list.html",
|
||||||
|
{"questions": questions})
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@@ -72,15 +75,15 @@ def index(request):
|
|||||||
@login_required
|
@login_required
|
||||||
def question_detail(request, pk):
|
def question_detail(request, pk):
|
||||||
question = get_object_or_404(AnatomyQuestion, pk=pk)
|
question = get_object_or_404(AnatomyQuestion, pk=pk)
|
||||||
return render(request, "anatomy/question_detail.html", {"question": question})
|
return render(request, "anatomy/question_detail.html",
|
||||||
|
{"question": question})
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def answer_question(request, pk):
|
def answer_question(request, pk):
|
||||||
question = get_object_or_404(AnatomyQuestion, pk=pk)
|
question = get_object_or_404(AnatomyQuestion, pk=pk)
|
||||||
answer = question.user_answers.filter(
|
answer = question.user_answers.filter(
|
||||||
user=request.user
|
user=request.user).first() # .filter(user=User)
|
||||||
).first() # .filter(user=User)
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
if answer:
|
if answer:
|
||||||
form = AnatomyAnswerForm(request.POST, instance=answer)
|
form = AnatomyAnswerForm(request.POST, instance=answer)
|
||||||
@@ -95,9 +98,10 @@ def answer_question(request, pk):
|
|||||||
return redirect("question_detail", pk=pk)
|
return redirect("question_detail", pk=pk)
|
||||||
else:
|
else:
|
||||||
form = AnatomyAnswerForm(instance=answer)
|
form = AnatomyAnswerForm(instance=answer)
|
||||||
return render(
|
return render(request, "anatomy/answer_question.html", {
|
||||||
request, "anatomy/answer_question.html", {"form": form, "question": question}
|
"form": form,
|
||||||
)
|
"question": question
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@@ -122,12 +126,16 @@ def exam_overview(request, pk):
|
|||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
"anatomy/exam_overview.html",
|
"anatomy/exam_overview.html",
|
||||||
{"exam": exam, "questions": questions, "question_number": question_number},
|
{
|
||||||
|
"exam": exam,
|
||||||
|
"questions": questions,
|
||||||
|
"question_number": question_number
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def exam(request, pk, sk):
|
def exam_take(request, pk, sk):
|
||||||
exam = get_object_or_404(Exam, pk=pk)
|
exam = get_object_or_404(Exam, pk=pk)
|
||||||
|
|
||||||
questions = exam.exam_questions.all()
|
questions = exam.exam_questions.all()
|
||||||
@@ -146,9 +154,8 @@ def exam(request, pk, sk):
|
|||||||
|
|
||||||
# Get data for flagged
|
# Get data for flagged
|
||||||
# answered_questions = UserAnswer.objects.filter(user=request.user).values_list("question__pk", flat=True)
|
# answered_questions = UserAnswer.objects.filter(user=request.user).values_list("question__pk", flat=True)
|
||||||
user_answer_data = UserAnswer.objects.filter(user=request.user).values_list(
|
user_answer_data = UserAnswer.objects.filter(
|
||||||
"question__pk", "answer", "flagged"
|
user=request.user).values_list("question__pk", "answer", "flagged")
|
||||||
)
|
|
||||||
# flagged_questions = UserAnswer.objects.filter(user=request.user, flagged=True).values_list("question__pk", flat=True)
|
# flagged_questions = UserAnswer.objects.filter(user=request.user, flagged=True).values_list("question__pk", flat=True)
|
||||||
# flagged_questions I= UserAnswer.filter(user=request.user, ).values_list("question__pk", flat=True)
|
# flagged_questions I= UserAnswer.filter(user=request.user, ).values_list("question__pk", flat=True)
|
||||||
|
|
||||||
@@ -162,8 +169,7 @@ def exam(request, pk, sk):
|
|||||||
|
|
||||||
# u = question.user_answers
|
# u = question.user_answers
|
||||||
answer = question.user_answers.filter(
|
answer = question.user_answers.filter(
|
||||||
user=request.user
|
user=request.user).first() # .filter(user=User)
|
||||||
).first() # .filter(user=User)
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
if answer:
|
if answer:
|
||||||
form = AnatomyAnswerForm(request.POST, instance=answer)
|
form = AnatomyAnswerForm(request.POST, instance=answer)
|
||||||
@@ -176,9 +182,9 @@ def exam(request, pk, sk):
|
|||||||
# answer.published_date = timezone.now()
|
# answer.published_date = timezone.now()
|
||||||
answer.save()
|
answer.save()
|
||||||
if "next" in request.POST:
|
if "next" in request.POST:
|
||||||
return redirect("exam", pk=pk, sk=n + 1)
|
return redirect("anatomy:exam_take", pk=pk, sk=n + 1)
|
||||||
elif "previous" in request.POST:
|
elif "previous" in request.POST:
|
||||||
return redirect("exam", pk=pk, sk=n - 1)
|
return redirect("anatomy:exam_take", pk=pk, sk=n - 1)
|
||||||
else:
|
else:
|
||||||
form = AnatomyAnswerForm(instance=answer)
|
form = AnatomyAnswerForm(instance=answer)
|
||||||
return render(
|
return render(
|
||||||
@@ -214,9 +220,9 @@ def postExamAnswers(request):
|
|||||||
for k in request.POST.dict():
|
for k in request.POST.dict():
|
||||||
for q in json.loads(k):
|
for q in json.loads(k):
|
||||||
# As access is not restricted make sure the data appears valid
|
# As access is not restricted make sure the data appears valid
|
||||||
if (not isinstance(q["cid"], int)) or (
|
if (not isinstance(q["cid"],
|
||||||
not isinstance(q["eid"], int) or (not isinstance(q["ans"], str))
|
int)) or (not isinstance(q["eid"], int) or
|
||||||
):
|
(not isinstance(q["ans"], str))):
|
||||||
return JsonResponse({"success": False})
|
return JsonResponse({"success": False})
|
||||||
|
|
||||||
# The model should catch invalid data but this should be less intensive
|
# The model should catch invalid data but this should be less intensive
|
||||||
@@ -224,12 +230,21 @@ def postExamAnswers(request):
|
|||||||
if q["cid"] > max_int or q["eid"] > max_int:
|
if q["cid"] > max_int or q["eid"] > max_int:
|
||||||
return JsonResponse({"success": False})
|
return JsonResponse({"success": False})
|
||||||
|
|
||||||
|
exam = get_object_or_404(Exam, pk=q["eid"])
|
||||||
|
|
||||||
|
if not exam.active:
|
||||||
|
return JsonResponse({
|
||||||
|
"success":
|
||||||
|
False,
|
||||||
|
"error":
|
||||||
|
"No active exam: {}".format(q["eid"])
|
||||||
|
})
|
||||||
|
|
||||||
exiting_answers = CidUserAnswer.objects.filter(
|
exiting_answers = CidUserAnswer.objects.filter(
|
||||||
question__id=q["qid"], exam__id=q["eid"], cid=q["cid"]
|
question__id=q["qid"], exam__id=q["eid"], cid=q["cid"])
|
||||||
)
|
|
||||||
|
|
||||||
if not exiting_answers:
|
if not exiting_answers:
|
||||||
ans = UserAnswer(answer=q["ans"], cid=q["cid"])
|
ans = CidUserAnswer(answer=q["ans"], cid=q["cid"])
|
||||||
ans.question_id = q["qid"]
|
ans.question_id = q["qid"]
|
||||||
ans.exam_id = q["eid"]
|
ans.exam_id = q["eid"]
|
||||||
|
|
||||||
@@ -258,9 +273,10 @@ def mark_overview(request, pk):
|
|||||||
|
|
||||||
questions = exam.exam_questions.all()
|
questions = exam.exam_questions.all()
|
||||||
|
|
||||||
return render(
|
return render(request, "anatomy/mark_overview.html", {
|
||||||
request, "anatomy/mark_overview.html", {"exam": exam, "questions": questions}
|
"exam": exam,
|
||||||
)
|
"questions": questions
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@@ -286,12 +302,9 @@ def mark(request, pk, sk):
|
|||||||
half_correct_answers = [i.answer for i in question.half_mark_answers.all()]
|
half_correct_answers = [i.answer for i in question.half_mark_answers.all()]
|
||||||
incorrect_answers = [i.answer for i in question.incorrect_answers.all()]
|
incorrect_answers = [i.answer for i in question.incorrect_answers.all()]
|
||||||
|
|
||||||
user_answers = (
|
user_answers = (set([i.answer for i in question.user_answers.all()]) -
|
||||||
set([i.answer for i in question.user_answers.all()])
|
set(correct_answers) - set(half_correct_answers) -
|
||||||
- set(correct_answers)
|
set(incorrect_answers)) # .filter(user=User)
|
||||||
- set(half_correct_answers)
|
|
||||||
- set(incorrect_answers)
|
|
||||||
) # .filter(user=User)
|
|
||||||
user_answers = set([i for i in user_answers if i.strip() != ""])
|
user_answers = set([i for i in user_answers if i.strip() != ""])
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
|
|
||||||
@@ -343,9 +356,9 @@ def mark(request, pk, sk):
|
|||||||
# answer.published_date = timezone.now()
|
# answer.published_date = timezone.now()
|
||||||
# answer.save()
|
# answer.save()
|
||||||
if "next" in request.POST:
|
if "next" in request.POST:
|
||||||
return redirect("mark", pk=pk, sk=n + 1)
|
return redirect("anatomy:mark", pk=pk, sk=n + 1)
|
||||||
elif "previous" in request.POST:
|
elif "previous" in request.POST:
|
||||||
return redirect("mark", pk=pk, sk=n - 1)
|
return redirect("anatomy:mark", pk=pk, sk=n - 1)
|
||||||
else:
|
else:
|
||||||
form = MarkAnatomyQuestionForm()
|
form = MarkAnatomyQuestionForm()
|
||||||
return render(
|
return render(
|
||||||
@@ -360,10 +373,15 @@ def mark(request, pk, sk):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def active_exams(request):
|
||||||
|
|
||||||
|
|
||||||
def exam_json(request, pk):
|
def exam_json(request, pk):
|
||||||
exam = get_object_or_404(Exam, pk=pk)
|
exam = get_object_or_404(Exam, pk=pk)
|
||||||
|
|
||||||
|
if not exam.active:
|
||||||
|
raise Http404("No available exam")
|
||||||
|
|
||||||
questions = exam.exam_questions.all()
|
questions = exam.exam_questions.all()
|
||||||
|
|
||||||
exam_questions = defaultdict(dict)
|
exam_questions = defaultdict(dict)
|
||||||
@@ -392,11 +410,8 @@ def exam_scores_cid(request, pk):
|
|||||||
|
|
||||||
questions = exam.exam_questions.all()
|
questions = exam.exam_questions.all()
|
||||||
|
|
||||||
cids = (
|
cids = (CidUserAnswer.objects.filter(question__in=questions).values_list(
|
||||||
UserAnswer.objects.filter(question__in=questions)
|
"cid", flat=True).distinct())
|
||||||
.values_list("cid", flat=True)
|
|
||||||
.distinct()
|
|
||||||
)
|
|
||||||
|
|
||||||
user_answers_and_marks = defaultdict(list)
|
user_answers_and_marks = defaultdict(list)
|
||||||
user_answers_marks = defaultdict(list)
|
user_answers_marks = defaultdict(list)
|
||||||
@@ -416,7 +431,8 @@ def exam_scores_cid(request, pk):
|
|||||||
ans = s[0].answer
|
ans = s[0].answer
|
||||||
if ans in q.answers.all().values_list("answer", flat=True):
|
if ans in q.answers.all().values_list("answer", flat=True):
|
||||||
a = 2
|
a = 2
|
||||||
elif ans in q.half_mark_answers.all().values_list("answer", flat=True):
|
elif ans in q.half_mark_answers.all().values_list("answer",
|
||||||
|
flat=True):
|
||||||
a = 1
|
a = 1
|
||||||
else:
|
else:
|
||||||
a = 0
|
a = 0
|
||||||
@@ -467,9 +483,8 @@ def exam_scores(request, pk):
|
|||||||
|
|
||||||
questions = exam.exam_questions.all()
|
questions = exam.exam_questions.all()
|
||||||
|
|
||||||
users = (
|
users = (CidUserAnswer.objects.filter(
|
||||||
UserAnswer.objects.filter(question__in=questions).values_list("user").distinct()
|
question__in=questions).values_list("user").distinct())
|
||||||
)
|
|
||||||
|
|
||||||
user_answers_and_marks = defaultdict(list)
|
user_answers_and_marks = defaultdict(list)
|
||||||
user_answers_marks = defaultdict(list)
|
user_answers_marks = defaultdict(list)
|
||||||
@@ -489,7 +504,8 @@ def exam_scores(request, pk):
|
|||||||
ans = s[0].answer
|
ans = s[0].answer
|
||||||
if ans in q.answers.all().values_list("answer", flat=True):
|
if ans in q.answers.all().values_list("answer", flat=True):
|
||||||
a = 2
|
a = 2
|
||||||
elif ans in q.half_mark_answers.all().values_list("answer", flat=True):
|
elif ans in q.half_mark_answers.all().values_list("answer",
|
||||||
|
flat=True):
|
||||||
a = 1
|
a = 1
|
||||||
else:
|
else:
|
||||||
a = 0
|
a = 0
|
||||||
@@ -527,4 +543,3 @@ def exam_scores(request, pk):
|
|||||||
"user_answers_and_marks": user_answers_and_marks,
|
"user_answers_and_marks": user_answers_and_marks,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+22
-14
@@ -31,7 +31,6 @@ ALLOWED_HOSTS = ["localhost", "127.0.0.1", "161.35.163.87"]
|
|||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
'anatomy',
|
'anatomy',
|
||||||
#"tagulous",
|
|
||||||
"reversion",
|
"reversion",
|
||||||
"django_tables2",
|
"django_tables2",
|
||||||
"django_filters",
|
"django_filters",
|
||||||
@@ -44,6 +43,7 @@ INSTALLED_APPS = [
|
|||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
|
#"tagulous",
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
@@ -116,12 +116,12 @@ AUTH_PASSWORD_VALIDATORS = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
SERIALIZATION_MODULES = {
|
#SERIALIZATION_MODULES = {
|
||||||
"xml": "tagulous.serializers.xml_serializer",
|
# "xml": "tagulous.serializers.xml_serializer",
|
||||||
"json": "tagulous.serializers.json",
|
# "json": "tagulous.serializers.json",
|
||||||
"python": "tagulous.serializers.python",
|
# "python": "tagulous.serializers.python",
|
||||||
"yaml": "tagulous.serializers.pyyaml",
|
# "yaml": "tagulous.serializers.pyyaml",
|
||||||
}
|
#}
|
||||||
|
|
||||||
# Internationalization
|
# Internationalization
|
||||||
# https://docs.djangoproject.com/en/1.11/topics/i18n/
|
# https://docs.djangoproject.com/en/1.11/topics/i18n/
|
||||||
@@ -142,20 +142,28 @@ USE_TZ = True
|
|||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
|
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
|
||||||
|
|
||||||
|
REMOTE_URL = "http://161.35.163.87/"
|
||||||
|
|
||||||
|
if DEBUG:
|
||||||
|
STATIC_URL = REMOTE_URL + STATIC_URL
|
||||||
|
|
||||||
MEDIA_URL = '/media/'
|
MEDIA_URL = '/media/'
|
||||||
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
|
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
|
||||||
|
|
||||||
|
if DEBUG:
|
||||||
|
MEDIA_URL = REMOTE_URL + MEDIA_URL
|
||||||
|
|
||||||
# Redirect to home URL after login (Default redirects to /accounts/profile/)
|
# Redirect to home URL after login (Default redirects to /accounts/profile/)
|
||||||
LOGIN_REDIRECT_URL = "/"
|
LOGIN_REDIRECT_URL = "/"
|
||||||
|
|
||||||
TAGULOUS_AUTOCOMPLETE_JS = (
|
#TAGULOUS_AUTOCOMPLETE_JS = (
|
||||||
"tagulous/lib/jquery.js",
|
#"tagulous/lib/jquery.js",
|
||||||
"tagulous/lib/select2-3/select2.min.js",
|
#"tagulous/lib/select2-3/select2.min.js",
|
||||||
"tagulous/tagulous.js",
|
#"tagulous/tagulous.js",
|
||||||
"tagulous/adaptor/select2-3.js",
|
#"tagulous/adaptor/select2-3.js",
|
||||||
)
|
#)
|
||||||
|
|
||||||
TAGULOUS_AUTOCOMPLETE_CSS = {"all": ["tagulous/lib/select2-3/select2.css"]}
|
#TAGULOUS_AUTOCOMPLETE_CSS = {"all": ["tagulous/lib/select2-3/select2.css"]}
|
||||||
|
|
||||||
INTERNAL_IPS = ["localhost", "127.0.0.1"]
|
INTERNAL_IPS = ["localhost", "127.0.0.1"]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user