Add pdf option for problem
This commit is contained in:
parent
98b8cbe518
commit
69f08e84b5
7 changed files with 65 additions and 3 deletions
|
@ -256,6 +256,7 @@ urlpatterns = [
|
|||
problem.ProblemPdfView.as_view(),
|
||||
name="problem_pdf",
|
||||
),
|
||||
url(r"^/pdf_description$", problem.ProblemPdfDescriptionView.as_view(), name="problem_pdf_description"),
|
||||
url(r"^/clone", problem.ProblemClone.as_view(), name="problem_clone"),
|
||||
url(r"^/submit$", problem.problem_submit, name="problem_submit"),
|
||||
url(
|
||||
|
|
|
@ -193,6 +193,7 @@ class ProblemAdmin(CompareVersionAdmin):
|
|||
"is_organization_private",
|
||||
"organizations",
|
||||
"description",
|
||||
"pdf_description",
|
||||
"license",
|
||||
),
|
||||
},
|
||||
|
|
25
judge/migrations/0130_auto_20220831_1048.py
Normal file
25
judge/migrations/0130_auto_20220831_1048.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
# Generated by Django 2.2.25 on 2022-08-31 03:48
|
||||
|
||||
from django.db import migrations, models
|
||||
import judge.models.problem
|
||||
import judge.utils.problem_data
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('judge', '0129_auto_20220622_1424'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='problem',
|
||||
name='pdf_description',
|
||||
field=models.FileField(blank=True, null=True, storage=judge.utils.problem_data.ProblemDataStorage(), upload_to=judge.models.problem.problem_directory_file, verbose_name='pdf statement'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='problem',
|
||||
name='description',
|
||||
field=models.TextField(blank=True, verbose_name='problem body'),
|
||||
),
|
||||
]
|
|
@ -18,6 +18,7 @@ from judge.models.profile import Organization, Profile
|
|||
from judge.models.runtime import Language
|
||||
from judge.user_translations import gettext as user_gettext
|
||||
from judge.utils.raw_sql import RawSQLColumn, unique_together_left_join
|
||||
from judge.models.problem_data import problem_data_storage, problem_directory_file_helper
|
||||
|
||||
__all__ = [
|
||||
"ProblemGroup",
|
||||
|
@ -31,6 +32,8 @@ __all__ = [
|
|||
"TranslatedProblemForeignKeyQuerySet",
|
||||
]
|
||||
|
||||
def problem_directory_file(data, filename):
|
||||
return problem_directory_file_helper(data.code, filename)
|
||||
|
||||
class ProblemType(models.Model):
|
||||
name = models.CharField(
|
||||
|
@ -160,7 +163,7 @@ class Problem(models.Model):
|
|||
db_index=True,
|
||||
help_text=_("The full name of the problem, " "as shown in the problem list."),
|
||||
)
|
||||
description = models.TextField(verbose_name=_("problem body"))
|
||||
description = models.TextField(verbose_name=_("problem body"), blank=True)
|
||||
authors = models.ManyToManyField(
|
||||
Profile,
|
||||
verbose_name=_("creators"),
|
||||
|
@ -299,6 +302,13 @@ class Problem(models.Model):
|
|||
is_organization_private = models.BooleanField(
|
||||
verbose_name=_("private to organizations"), default=False
|
||||
)
|
||||
pdf_description = models.FileField(
|
||||
verbose_name=_("pdf statement"),
|
||||
storage=problem_data_storage,
|
||||
null=True,
|
||||
blank=True,
|
||||
upload_to=problem_directory_file,
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Problem, self).__init__(*args, **kwargs)
|
||||
|
|
|
@ -20,12 +20,12 @@ __all__ = [
|
|||
problem_data_storage = ProblemDataStorage()
|
||||
|
||||
|
||||
def _problem_directory_file(code, filename):
|
||||
def problem_directory_file_helper(code, filename):
|
||||
return os.path.join(code, os.path.basename(filename))
|
||||
|
||||
|
||||
def problem_directory_file(data, filename):
|
||||
return _problem_directory_file(data.problem.code, filename)
|
||||
return problem_directory_file_helper(data.problem.code, filename)
|
||||
|
||||
|
||||
CHECKERS = (
|
||||
|
|
|
@ -402,6 +402,27 @@ class ProblemPdfView(ProblemMixin, SingleObjectMixin, View):
|
|||
return response
|
||||
|
||||
|
||||
class ProblemPdfDescriptionView(ProblemMixin, SingleObjectMixin, View):
|
||||
def get(self, request, *args, **kwargs):
|
||||
problem = self.get_object()
|
||||
if not problem.pdf_description:
|
||||
raise Http404()
|
||||
response = HttpResponse()
|
||||
if hasattr(settings, "DMOJ_PDF_PROBLEM_INTERNAL") and request.META.get(
|
||||
"SERVER_SOFTWARE", ""
|
||||
).startswith("nginx/"):
|
||||
response["X-Accel-Redirect"] = problem.pdf_description.path
|
||||
else:
|
||||
with open(problem.pdf_description.path, "rb") as f:
|
||||
response.content = f.read()
|
||||
|
||||
response["Content-Type"] = "application/pdf"
|
||||
response["Content-Disposition"] = "inline; filename=%s.pdf" % (
|
||||
problem.code,
|
||||
)
|
||||
return response
|
||||
|
||||
|
||||
class ProblemList(QueryStringSortMixin, TitleMixin, SolvedProblemMixin, ListView):
|
||||
model = Problem
|
||||
title = gettext_lazy("Problems")
|
||||
|
|
|
@ -377,6 +377,10 @@
|
|||
{{ description|markdown("problem", MATH_ENGINE)|reference|str|safe }}
|
||||
{% endcache %}
|
||||
|
||||
{% if problem.pdf_description %}
|
||||
<embed src="{{url('problem_pdf_description', problem.code)}}" width="100%" height="500" type="application/pdf">
|
||||
{% endif %}
|
||||
|
||||
{% with license=problem.license %}
|
||||
{% if license %}
|
||||
<span class="license">
|
||||
|
|
Loading…
Reference in a new issue