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")