Add pdf option for problem

This commit is contained in:
cuom1999 2022-08-30 22:50:08 -05:00
parent 98b8cbe518
commit 69f08e84b5
7 changed files with 65 additions and 3 deletions

View file

@ -256,6 +256,7 @@ urlpatterns = [
problem.ProblemPdfView.as_view(), problem.ProblemPdfView.as_view(),
name="problem_pdf", 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"^/clone", problem.ProblemClone.as_view(), name="problem_clone"),
url(r"^/submit$", problem.problem_submit, name="problem_submit"), url(r"^/submit$", problem.problem_submit, name="problem_submit"),
url( url(

View file

@ -193,6 +193,7 @@ class ProblemAdmin(CompareVersionAdmin):
"is_organization_private", "is_organization_private",
"organizations", "organizations",
"description", "description",
"pdf_description",
"license", "license",
), ),
}, },

View 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'),
),
]

View file

@ -18,6 +18,7 @@ from judge.models.profile import Organization, Profile
from judge.models.runtime import Language from judge.models.runtime import Language
from judge.user_translations import gettext as user_gettext from judge.user_translations import gettext as user_gettext
from judge.utils.raw_sql import RawSQLColumn, unique_together_left_join 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__ = [ __all__ = [
"ProblemGroup", "ProblemGroup",
@ -31,6 +32,8 @@ __all__ = [
"TranslatedProblemForeignKeyQuerySet", "TranslatedProblemForeignKeyQuerySet",
] ]
def problem_directory_file(data, filename):
return problem_directory_file_helper(data.code, filename)
class ProblemType(models.Model): class ProblemType(models.Model):
name = models.CharField( name = models.CharField(
@ -160,7 +163,7 @@ class Problem(models.Model):
db_index=True, db_index=True,
help_text=_("The full name of the problem, " "as shown in the problem list."), 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( authors = models.ManyToManyField(
Profile, Profile,
verbose_name=_("creators"), verbose_name=_("creators"),
@ -299,6 +302,13 @@ class Problem(models.Model):
is_organization_private = models.BooleanField( is_organization_private = models.BooleanField(
verbose_name=_("private to organizations"), default=False 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): def __init__(self, *args, **kwargs):
super(Problem, self).__init__(*args, **kwargs) super(Problem, self).__init__(*args, **kwargs)

View file

@ -20,12 +20,12 @@ __all__ = [
problem_data_storage = ProblemDataStorage() 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)) return os.path.join(code, os.path.basename(filename))
def problem_directory_file(data, 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 = ( CHECKERS = (

View file

@ -402,6 +402,27 @@ class ProblemPdfView(ProblemMixin, SingleObjectMixin, View):
return response 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): class ProblemList(QueryStringSortMixin, TitleMixin, SolvedProblemMixin, ListView):
model = Problem model = Problem
title = gettext_lazy("Problems") title = gettext_lazy("Problems")

View file

@ -377,6 +377,10 @@
{{ description|markdown("problem", MATH_ENGINE)|reference|str|safe }} {{ description|markdown("problem", MATH_ENGINE)|reference|str|safe }}
{% endcache %} {% 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 %} {% with license=problem.license %}
{% if license %} {% if license %}
<span class="license"> <span class="license">