few fixes towards functional status

This commit is contained in:
Ross
2020-10-16 21:38:01 +01:00
parent 774a867f59
commit 644bf9ce76
10 changed files with 261 additions and 66 deletions
+1
View File
@@ -0,0 +1 @@
media/
+147
View File
@@ -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'),
),
]
+18
View File
@@ -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'),
),
]
View File
+2
View File
@@ -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
+3 -3
View File
@@ -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>
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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"]