Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

static.py 4.2KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. """
  2. Views and functions for serving static files. These are only to be used
  3. during development, and SHOULD NOT be used in a production setting.
  4. """
  5. import mimetypes
  6. import posixpath
  7. from pathlib import Path
  8. from django.http import FileResponse, Http404, HttpResponse, HttpResponseNotModified
  9. from django.template import Context, Engine, TemplateDoesNotExist, loader
  10. from django.utils._os import safe_join
  11. from django.utils.http import http_date, parse_http_date
  12. from django.utils.translation import gettext as _
  13. from django.utils.translation import gettext_lazy
  14. def serve(request, path, document_root=None, show_indexes=False):
  15. """
  16. Serve static files below a given point in the directory structure.
  17. To use, put a URL pattern such as::
  18. from django.views.static import serve
  19. path('<path:path>', serve, {'document_root': '/path/to/my/files/'})
  20. in your URLconf. You must provide the ``document_root`` param. You may
  21. also set ``show_indexes`` to ``True`` if you'd like to serve a basic index
  22. of the directory. This index view will use the template hardcoded below,
  23. but if you'd like to override it, you can create a template called
  24. ``static/directory_index.html``.
  25. """
  26. path = posixpath.normpath(path).lstrip("/")
  27. fullpath = Path(safe_join(document_root, path))
  28. if fullpath.is_dir():
  29. if show_indexes:
  30. return directory_index(path, fullpath)
  31. raise Http404(_("Directory indexes are not allowed here."))
  32. if not fullpath.exists():
  33. raise Http404(_("“%(path)s” does not exist") % {"path": fullpath})
  34. # Respect the If-Modified-Since header.
  35. statobj = fullpath.stat()
  36. if not was_modified_since(
  37. request.META.get("HTTP_IF_MODIFIED_SINCE"), statobj.st_mtime
  38. ):
  39. return HttpResponseNotModified()
  40. content_type, encoding = mimetypes.guess_type(str(fullpath))
  41. content_type = content_type or "application/octet-stream"
  42. response = FileResponse(fullpath.open("rb"), content_type=content_type)
  43. response.headers["Last-Modified"] = http_date(statobj.st_mtime)
  44. if encoding:
  45. response.headers["Content-Encoding"] = encoding
  46. return response
  47. DEFAULT_DIRECTORY_INDEX_TEMPLATE = """
  48. {% load i18n %}
  49. <!DOCTYPE html>
  50. <html lang="en">
  51. <head>
  52. <meta http-equiv="Content-type" content="text/html; charset=utf-8">
  53. <meta http-equiv="Content-Language" content="en-us">
  54. <meta name="robots" content="NONE,NOARCHIVE">
  55. <title>{% blocktranslate %}Index of {{ directory }}{% endblocktranslate %}</title>
  56. </head>
  57. <body>
  58. <h1>{% blocktranslate %}Index of {{ directory }}{% endblocktranslate %}</h1>
  59. <ul>
  60. {% if directory != "/" %}
  61. <li><a href="../">../</a></li>
  62. {% endif %}
  63. {% for f in file_list %}
  64. <li><a href="{{ f|urlencode }}">{{ f }}</a></li>
  65. {% endfor %}
  66. </ul>
  67. </body>
  68. </html>
  69. """
  70. template_translatable = gettext_lazy("Index of %(directory)s")
  71. def directory_index(path, fullpath):
  72. try:
  73. t = loader.select_template(
  74. [
  75. "static/directory_index.html",
  76. "static/directory_index",
  77. ]
  78. )
  79. except TemplateDoesNotExist:
  80. t = Engine(libraries={"i18n": "django.templatetags.i18n"}).from_string(
  81. DEFAULT_DIRECTORY_INDEX_TEMPLATE
  82. )
  83. c = Context()
  84. else:
  85. c = {}
  86. files = []
  87. for f in fullpath.iterdir():
  88. if not f.name.startswith("."):
  89. url = str(f.relative_to(fullpath))
  90. if f.is_dir():
  91. url += "/"
  92. files.append(url)
  93. c.update(
  94. {
  95. "directory": path + "/",
  96. "file_list": files,
  97. }
  98. )
  99. return HttpResponse(t.render(c))
  100. def was_modified_since(header=None, mtime=0):
  101. """
  102. Was something modified since the user last downloaded it?
  103. header
  104. This is the value of the If-Modified-Since header. If this is None,
  105. I'll just return True.
  106. mtime
  107. This is the modification time of the item we're talking about.
  108. """
  109. try:
  110. if header is None:
  111. raise ValueError
  112. header_mtime = parse_http_date(header)
  113. if int(mtime) > header_mtime:
  114. raise ValueError
  115. except (ValueError, OverflowError):
  116. return True
  117. return False