Files
Website/article/views.py
2021-11-29 00:03:59 +01:00

249 lines
8.0 KiB
Python

import time
import os
import glob
import datetime
import requests
from django.shortcuts import render, HttpResponse, Http404
from django.core.exceptions import PermissionDenied
from .models import Article
from .forms import ArticleForm
from .adapt import adapt
from django.template.loader import engines
from django.views.decorators.csrf import csrf_exempt
from home.context import home, hydrate
from rich import print
def get_article_context(request):
"""Create the context of the article view."""
d = home(request)
objects = Article.objects.filter(public=True)
if request.user.is_authenticated:
objects.union(Article.objects.filter(author=request.user))
d["objects"] = objects
return d
def reset_template_cache():
"""Attempt to get rid of template caching of django."""
print("engines:", engines)
for engine in engines.all():
print("engine:", engine.engine.template_loaders[0])
engine.engine.template_loaders[0].reset()
@hydrate(get_article_context)
def index(request, context={}):
"""Select or create an article."""
return render(request, "article/index.html", context)
def clean_templates():
"""Remove the unused templates."""
# print(f"{os.getcwd()}/article/static/cache")
# print('machin directory:', os.listdir(f"{os.getcwd()}/article/static"))
# print(os.listdir(f"{os.getcwd()}/article/static/cache"))
# os.system(f"rm -rf {os.getcwd()}/article/templates/article/cache")
# os.system(f"mkdir {os.getcwd()}/article/templates/article/cache")
static_cache_path = os.path.join(os.getcwd(), "article/static/article/cache")
templates_cache_path = os.path.join(os.getcwd(), "article/templates/cache")
if os.path.exists(static_cache_path):
os.system(f"rm -rf {static_cache_path}")
# print("static:", static_cache_path)
# print("templates:", templates_cache_path)
if os.path.exists(templates_cache_path):
print(
"before deleting templates",
os.listdir(templates_cache_path),
)
path = os.path.join(templates_cache_path, "*")
# print('path:', path)
for file in glob.glob(path):
print(file, "is deleted.")
os.remove(file)
print(
"after deleting templates",
os.listdir(templates_cache_path),
)
def build_template(title: str, article: Article, layout: str = "marc"):
"""Build the template and its assets."""
markdown_path = os.path.join(os.getcwd(), f"media/article/{title}.md")
html_path = os.path.join(os.getcwd(), f"article/templates/cache/{title}.html")
article_templates = os.path.join(os.getcwd(), "article/templates/cache")
article_static = os.path.join(os.getcwd(), "article/static/article")
with open(markdown_path, "w") as f:
f.write(article.content)
cmd = " ".join(
(
os.path.join(os.getcwd(), "node_modules/.bin/generate-md"),
f" --layout {layout}",
f" --input {markdown_path}",
f" --output {article_templates}",
)
)
print(cmd)
os.system(cmd)
layout_path = os.path.join(article_templates, layout)
os.rename(os.path.join(article_templates, "assets"), layout_path)
if layout in os.listdir(article_static):
os.system(f"rm -rf {layout_path}")
# else:
os.system(f"mv {layout_path} {article_static}")
with open(html_path, "r") as stream:
text = str(stream.read())
text = adapt(text, title, layout)
with open(html_path, "w") as stream:
stream.write(text)
def read(request, title: str):
"""Read an article."""
reset_template_cache()
clean_templates()
print("title", title)
if "." in title:
title_no_extension = "".join(title.split(".")[:-1])
else:
title_no_extension = title
print("title_no_extension", title_no_extension)
article = Article.objects.filter(title=title_no_extension).first()
# article = Article.objects.all()[0]
print("article.layout:", article.layout)
if not article:
raise Http404("This article was not found.")
print("GET:", request.GET)
layout = request.GET.get("layout") or article.layout or "marc"
layouts = os.listdir("./node_modules/markdown-styles/layouts")
article.read = datetime.datetime.now()
article.view_count += 1
article.save()
if layout not in layouts:
print(layout, "not in ", layouts)
return render(request, "article/403.html", dict(layouts=layouts))
if title.endswith(".md"):
return HttpResponse(article.content, content_type="text/markdown")
extensions = ["pdf", "docs"]
for extension in extensions:
if title.endswith(extension):
return read_as(article, extension)
# Never happens since order matters in `urls.py`.
if title == "index":
raise PermissionDenied
build_template(title, article, layout)
# Messing with template loader cache system
title_template = title + "." + str(time.time())
path = os.path.join(os.getcwd(), f"article/templates/cache/{title_template}.html")
title_path = os.path.join(os.getcwd(), f"article/templates/cache/{title}.html")
os.system(f"mv {title_path} {path}")
print(os.listdir(os.path.join(os.getcwd(), f"article/templates/cache/")))
# Fill context with http parameters and article meta data.
# Deal with priority when combined dictionaries
# have the same keys.
context = dict(stats=os.stat(path))
context.update(article.__dict__)
context.update(request.GET)
return render(request, f"cache/{title_template}.html", context)
# print(f'removing {title}.html')
# title_layout = title + "." + layout
# elif not f"{title}.html" in os.listdir(f"{os.getcwd()}/article/templates/article"):
# return render(request, f"cache/{title}.html", request.GET)
# context = dict(**request.GET)
# print(context)
# template = loader.get_template(f"cache/{title_layout}.html")
# os.system(f'head -n 20 {os.getcwd()}/article/templates/cache/{title_layout}.html')
# html = template.render(context, request)
# # template.render()
# # template.render(clean=True)
# print(html[:1000])
# print("code generated")
# return HttpResponse(html)
def fetch_article_data(file, request):
"""Read a file to fetch data to fill the sql fields."""
d = {}
d["title"] = request.POST.get("title") or str(file)
if d["title"].endswith(".md"):
d["title"] = d["title"][:-3]
print(type(file))
# d['file'] = file
d["content"] = file.read().decode("utf-8")
if request.user:
d["author"] = request.user
d["public"] = request.POST.get("public") or False
print(d)
return d
def read_as(article: Article, extension: str):
"""Read the markdown as a pdf using the pandoc api."""
from django_project.settings import PANDOC_API_URL as host
# Post markdown to pandoc api
post_url = f"{host}/api/{article.title}.{extension}"
print("post url:", post_url)
requests.post(
post_url,
files={"file": (article.title, article.content)},
data={"output": "extension"},
)
# Get generated page in pandoc api
get_url = f"{host}/file/{article.title}.{extension}"
print("get url:", get_url)
return HttpResponse(
requests.get(get_url).content, content_type=f"application/{extension}"
)
@csrf_exempt
def upload(request):
"""Upload a new article."""
print("received markdown")
if request.method == "POST":
print(request.FILES)
d = fetch_article_data(request.FILES["file"], request)
form = ArticleForm(d)
if form.is_valid():
print("[lightgreen]valid form[/]")
form.save()
return HttpResponse("success")
print("[red]invalid form[/]")
print(f"[red]{form.errors.as_data()}[/]")
return HttpResponse("invalid form", status=500)
if request.method == "GET":
form = ArticleForm()
context = dict(form=form)
return render(request, "api/upload.html", context)
raise PermissionDenied("Only GET and POST methods are allowed")