Source code for django.views.static

"""Views and functions for serving static files. These are only to be usedduring development, and SHOULD NOT be used in a production setting."""importmimetypesimportposixpathimportrefrompathlibimportPathfromdjango.httpimport(FileResponse,Http404,HttpResponse,HttpResponseNotModified,)fromdjango.templateimportContext,Engine,TemplateDoesNotExist,loaderfromdjango.utils._osimportsafe_joinfromdjango.utils.httpimporthttp_date,parse_http_datefromdjango.utils.translationimportgettextas_,gettext_lazydefserve(request,path,document_root=None,show_indexes=False):""" Serve static files below a given point in the directory structure. To use, put a URL pattern such as:: from django.views.static import serve url(r'^(?P<path>.*)$', serve, {'document_root': '/path/to/my/files/'}) in your URLconf. You must provide the ``document_root`` param. You may also set ``show_indexes`` to ``True`` if you'd like to serve a basic index of the directory. This index view will use the template hardcoded below, but if you'd like to override it, you can create a template called ``static/directory_index.html``. """path=posixpath.normpath(path).lstrip('/')fullpath=Path(safe_join(document_root,path))iffullpath.is_dir():ifshow_indexes:returndirectory_index(path,fullpath)raiseHttp404(_("Directory indexes are not allowed here."))ifnotfullpath.exists():raiseHttp404(_('"%(path)s" does not exist')%{'path':fullpath})# Respect the If-Modified-Since header.statobj=fullpath.stat()ifnotwas_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'),statobj.st_mtime,statobj.st_size):returnHttpResponseNotModified()content_type,encoding=mimetypes.guess_type(str(fullpath))content_type=content_typeor'application/octet-stream'response=FileResponse(fullpath.open('rb'),content_type=content_type)response["Last-Modified"]=http_date(statobj.st_mtime)ifencoding:response["Content-Encoding"]=encodingreturnresponseDEFAULT_DIRECTORY_INDEX_TEMPLATE="""{% load i18n %}<!DOCTYPE html><html lang="en"> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <meta http-equiv="Content-Language" content="en-us"> <meta name="robots" content="NONE,NOARCHIVE"> <title>{% blocktrans %}Index of {{ directory }}{% endblocktrans %}</title> </head> <body> <h1>{% blocktrans %}Index of {{ directory }}{% endblocktrans %}</h1> <ul> {% if directory != "/" %} <li><a href="../">../</a></li> {% endif %} {% for f in file_list %} <li><a href="{{ f|urlencode }}">{{ f }}</a></li> {% endfor %} </ul> </body></html>"""template_translatable=gettext_lazy("Index of %(directory)s")defdirectory_index(path,fullpath):try:t=loader.select_template(['static/directory_index.html','static/directory_index',])exceptTemplateDoesNotExist:t=Engine(libraries={'i18n':'django.templatetags.i18n'}).from_string(DEFAULT_DIRECTORY_INDEX_TEMPLATE)c=Context()else:c={}files=[]forfinfullpath.iterdir():ifnotf.name.startswith('.'):url=str(f.relative_to(fullpath))iff.is_dir():url+='/'files.append(url)c.update({'directory':path+'/','file_list':files,})returnHttpResponse(t.render(c))defwas_modified_since(header=None,mtime=0,size=0):""" Was something modified since the user last downloaded it? header This is the value of the If-Modified-Since header. If this is None, I'll just return True. mtime This is the modification time of the item we're talking about. size This is the size of the item we're talking about. """try:ifheaderisNone:raiseValueErrormatches=re.match(r"^([^;]+)(; length=([0-9]+))?$",header,re.IGNORECASE)header_mtime=parse_http_date(matches.group(1))header_len=matches.group(3)ifheader_lenandint(header_len)!=size:raiseValueErrorifint(mtime)>header_mtime:raiseValueErrorexcept(AttributeError,ValueError,OverflowError):returnTruereturnFalse