Automatically choose renderer according to Accept header.

This commit is contained in:
Julien Palard 2023-04-21 11:01:45 +02:00
parent a2dad29337
commit bc75975da3
Signed by: mdk
GPG Key ID: 0EFC1AC1006886F8
6 changed files with 60 additions and 79 deletions

View File

@ -1,22 +0,0 @@
from django.template import RequestContext
from django.http import HttpResponse
from django.template import loader
from pygments import highlight
from pygments.lexers import get_lexer_by_name
from pygments.formatters import HtmlFormatter
def render_pygments(request, paste, data):
"""Renders Pygments template."""
lexer = get_lexer_by_name(paste.language.slug)
formatter = HtmlFormatter(style="emacs")
highlighted_content = highlight(paste.content, lexer, formatter)
data["paste"] = paste
data["highlighted"] = highlighted_content
rendered = loader.render_to_string("paste/show-pygments.html", data, request)
return HttpResponse(rendered)
def render_raw(request, paste, data):
"""Renders RAW content."""
return HttpResponse(paste.content, content_type="text/plain")

View File

@ -8,7 +8,7 @@ Et Paf.
Ce « pastebin-like » ne peut être utilisé qu'en ligne de commande, soit avec <tt>curl</tt> :
<div class="highlight"><pre><span></span>curl {{ absolute_index_url }} <span class="o">-F</span>python<span class="o">=</span>@hello.py
<div class="highlight"><pre><span></span>curl {{ request.build_absolute_uri }} <span class="o">-F</span>python<span class="o">=</span>@hello.py
</pre></div>
<p>Le nom, entre <tt>-F</tt> et <tt>=</tt> sert à choisir la coloration syntaxique.</p>
@ -17,13 +17,13 @@ Ce « pastebin-like » ne peut être utilisé qu'en ligne de commande, soit av
<div class="highlight"><pre><span></span>pafpy<span class="o">()</span>
<span class="o">{</span>
curl {{absolute_index_url}} -F<span class="s2">&quot;</span><span class="si">${</span><span class="nv">1</span><span class="p">##*.</span><span class="si">}</span><span class="s2">=@</span><span class="nv">$1</span><span class="s2">&quot;</span>
curl {{request.build_absolute_uri}} -F<span class="s2">&quot;</span><span class="si">${</span><span class="nv">1</span><span class="p">##*.</span><span class="si">}</span><span class="s2">=@</span><span class="nv">$1</span><span class="s2">&quot;</span>
<span class="o">}</span>
</pre></div>
Demo :
<div class="highlight"><pre><span></span>$ pafpy test.py
{{absolute_index_url}}D91F1CA
{{request.build_absolute_uri}}D91F1CA
</pre></div>
{% endblock %}

View File

@ -1,6 +1,6 @@
{% extends "base.html" %}
{% block extrastyle %}
<link href="/static/css//pasteque.css" rel="stylesheet">
<link href="/static/css/pasteque.css" rel="stylesheet">
{% endblock %}
{% block title %}{{ slug }}{% endblock %}

View File

@ -7,7 +7,5 @@ from webtools import settings
urlpatterns = [
path("", views.index, name="index"),
path("static/<path>", serve, {"document_root": settings.STATIC_ROOT}),
path("paste/<slug:slug>/<renderer>", views.show, name="paste"),
path("paste/<slug:slug>", views.show, name="paste"),
path("<slug>", views.show, name="short_paste"),
]

View File

@ -1,65 +1,72 @@
from . import renderers
import json
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.template import RequestContext, loader
from django.urls import reverse
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect, HttpResponse
from django.views.decorators.csrf import csrf_exempt
from .models import Paste, Language
from .forms import PasteForm
from pygments import highlight
from pygments.formatters import HtmlFormatter
from pygments.lexers import get_lexer_by_name
from webtools import settings
from paste.forms import PasteForm
from paste.models import Language, Paste
@csrf_exempt
def index(request):
"""Displays form."""
data = {"menu": "index", "max_characters": settings.PASTE["max_characters"]}
if request.method == "POST":
paste = Paste()
paste.choose_slug()
if request.FILES:
for language_name, any_file in request.FILES.items():
break
language = Language.by_name(language_name)
form = PasteForm(
{
"language": language.id,
"content": any_file.read().decode(),
},
instance=paste,
)
else:
form = PasteForm(request.POST, instance=paste)
if not form.is_valid():
data["form"] = form
return render(request, "paste/index.html", data)
form.save() # Some logic added to overrided method, see forms.py
location = request.build_absolute_uri(
reverse("short_paste", kwargs={"slug": paste.slug})
if request.method == "GET":
return render(request, "paste/index.html")
paste = Paste()
paste.choose_slug()
if request.FILES:
(language_name, the_file), *_ = request.FILES.items()
language = Language.by_name(language_name)
form = PasteForm(
{
"language": language.id,
"content": the_file.read().decode(),
},
instance=paste,
)
return HttpResponseRedirect(
location, content=location + "\n", content_type="text/plain"
)
data["form"] = PasteForm(
initial={
"language": Language.by_name(settings.PASTE["default_language"]).id,
}
if not form.is_valid():
return HttpResponse(json.dumps(form.errors, indent=4))
form.save()
location = request.build_absolute_uri(
reverse("short_paste", kwargs={"slug": paste.slug})
)
return HttpResponseRedirect(
location, content=location + "\n", content_type="text/plain"
)
data["absolute_index_url"] = request.build_absolute_uri(reverse("index"))
return render(request, "paste/index.html", data)
def show(request, slug, renderer="pygments"):
def show(request, slug):
"""Display paste."""
# Fetching object
paste = get_object_or_404(Paste, slug=slug)
data = {"slug": slug}
# Handling expiration
# Before rendering actions
paste.incr_viewcount()
# Handling rendering modes
if not renderer or renderer not in settings.PASTE["enabled_renderers"]:
renderer = settings.PASTE["default_renderer"]
data["current_renderer"] = renderer
data["renderers"] = settings.PASTE["enabled_renderers"]
render_method = getattr(renderers, "render_%s" % renderer)
return render_method(request, paste, data)
if "html" in request.headers["accept"]:
render_method = render_pygments
else:
render_method = render_raw
return render_method(request, paste, {"slug": slug})
def render_pygments(request, paste, data):
"""Renders Pygments template."""
lexer = get_lexer_by_name(paste.language.slug)
formatter = HtmlFormatter(style="emacs")
highlighted_content = highlight(paste.content, lexer, formatter)
data["paste"] = paste
data["highlighted"] = highlighted_content
rendered = loader.render_to_string("paste/show-pygments.html", data, request)
return HttpResponse(rendered)
def render_raw(request, paste, data):
"""Renders RAW content."""
return HttpResponse(paste.content, content_type="text/plain")

View File

@ -92,8 +92,6 @@ INSTALLED_APPS = (
PASTE = {
"has_meta_table": False,
"enabled_renderers": ["pygments", "raw"],
"default_renderer": "pygments",
"max_characters": 100000,
"default_language": "Python",
}