From be306c6643f6528908fbed17aee0a791daf497e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soutad=C3=A9?= Date: Sun, 22 Jul 2012 10:47:24 +0200 Subject: [PATCH] Add article generator --- forms.py | 3 +- generators/__init__.py | 2 +- generators/article.py | 62 ++++++++++++++++++++++++++++++++ generators/generator.py | 6 ++-- generators/index.py | 3 ++ models.py | 63 +++++++++++++++++++++++++++++--- templates/add_article.html | 27 ++++++++++++++ templates/base.html | 1 + templates/edit_article.html | 29 ++++++++++++++- templates/edit_user.html | 3 ++ views.py | 72 ++++++++++++++++++++++++------------- 11 files changed, 237 insertions(+), 34 deletions(-) create mode 100644 generators/article.py diff --git a/forms.py b/forms.py index 7d03673..63ce7ac 100644 --- a/forms.py +++ b/forms.py @@ -8,7 +8,7 @@ class BlogForm(ModelForm): class ArticleForm(ModelForm): class Meta: model = Article - exclude = ('creation_date', 'author', 'blog', 'tags') + exclude = ('title_slug', 'creation_date', 'author', 'blog', 'tags') def __init__(self, *args, **kwargs): super(ArticleForm, self).__init__(*args, **kwargs) @@ -23,4 +23,3 @@ class UserForm(ModelForm): class Meta: model = User exclude = ('is_staff', 'is_active', 'last_login', 'last_joined', 'user_permissions', 'groups', 'date_joined') - diff --git a/generators/__init__.py b/generators/__init__.py index dd6dca6..8b4c9af 100644 --- a/generators/__init__.py +++ b/generators/__init__.py @@ -1 +1 @@ -__all__ = ["generator", "index"] +__all__ = ["generator", "index", "article"] diff --git a/generators/article.py b/generators/article.py new file mode 100644 index 0000000..91ddfa8 --- /dev/null +++ b/generators/article.py @@ -0,0 +1,62 @@ +import os +import datetime +from xml.dom.minidom import parse, parseString +from dynastie.generators.generator import DynastieGenerator +from django.db import models + +# TODO : content + +class Article(DynastieGenerator): + + def createArticle(self, article, dom, article_elem, root): + values = {} + values['title'] = article.title + values['author'] = article.author.first_name + values['date'] = article.creation_date.strftime("%d/%m/%Y") + values['content'] = '' + + self.simpleTransform(values, dom, article_elem, root) + + def parse(self, article, dom, root): + for node in root.childNodes: + if node.prefix == 'dyn': + if node.localName == 'content': + article_elem = self.createElement(dom, 'article') + self.createArticle(article, dom, article_elem, node) + root.replaceChild(article_elem, node) + + continue + if node.hasChildNodes(): + self.parse(article, dom, node) + return + + def generate(self, blog, src, output): + from dynastie.models import Article, Blog + + if not os.path.exists(src + '/_article.html'): + self.addError('No _article.html found, exiting') + return self.report + + try: + dom = parse(src + '/_article.html') + except xml.dom.DOMException as e: + self.addError('Error parsing _article.html : ' + e) + return self.report + + if not os.path.exists(output + '/articles'): + os.mkdir(output + '/articles') + + articles = Article.objects.all() + + for article in articles: + #print 'Generate ' + filename + nodes = dom.getElementsByTagName("*") + self.parse(article, dom, nodes[0]) + self.writeIfNotTheSame(output + '/articles/' + article.title_slug + '.html', nodes[0].toxml('utf8')) + dom = parse(src + '/_article.html') + + if not self.somethingWrote: + self.addReport('Nothing changed') + + return self.report + diff --git a/generators/generator.py b/generators/generator.py index 57ef22d..8ba551d 100644 --- a/generators/generator.py +++ b/generators/generator.py @@ -7,9 +7,11 @@ class DynastieGenerator: URI = "http://indefero.soutade.fr/p/dynastie" report = '' + somethingWrote = False def __init__(self): self.report = '' + self.somethingWrote = False def addReport(self, string, color=''): if color != '': @@ -40,10 +42,8 @@ class DynastieGenerator: dst_md5.update(content) if src_md5.digest() == dst_md5.digest(): - self.addReport(filename + ' regenerated with the same content, skipping...') filename = filename + '.gz' if not os.path.exists(filename): - self.addReport(filename + ' was not previously compressed') f = gzip.open(filename, 'wb') f.write(content) f.close() @@ -60,6 +60,8 @@ class DynastieGenerator: f = gzip.open(filename, 'wb') f.write(content) f.close() + + self.somethingWrote = True def createElement(self, dom, name='', content=''): div = dom.createElement('div') diff --git a/generators/index.py b/generators/index.py index b726040..9d5de23 100644 --- a/generators/index.py +++ b/generators/index.py @@ -135,5 +135,8 @@ class Index(DynastieGenerator): self.cur_page = self.cur_page + 1 filename = output + '/index' + str(self.cur_page) + '.html' + if not self.somethingWrote: + self.addReport('Nothing changed') + return self.report diff --git a/models.py b/models.py index a516fcc..4a08a67 100644 --- a/models.py +++ b/models.py @@ -2,6 +2,8 @@ import os import shutil import hashlib import inspect +from unicodedata import normalize +from re import sub from datetime import datetime from django.db import models from django.contrib.auth.models import User @@ -27,14 +29,16 @@ class Blog(models.Model): self.output_path = 'sites/' + self.name + '_output' def create(self): + self.create_paths() if not os.path.exists('sites'): os.mkdir('sites') - self.remove() - - os.mkdir(self.src_path) - os.mkdir(self.output_path) + if not os.path.exists(self.src_path): + os.mkdir(self.src_path) + if not os.path.exists(self.output_path): + os.mkdir(self.output_path) + def remove(self): if os.path.exists(self.src_path): shutil.rmtree(self.src_path) @@ -109,6 +113,7 @@ class Blog(models.Model): r = e.generate(self, self.src_path, self.output_path) if not r is None: self.report = self.report + '
\n' + r + return self.report class Editor(models.Model): @@ -124,6 +129,7 @@ class Tag(models.Model): class Article(models.Model): title = models.CharField(max_length=255) + title_slug = models.CharField(max_length=255) category = models.ForeignKey(Category, blank=True, null=True, on_delete=models.SET_NULL) published = models.BooleanField() creation_date = models.DateField() @@ -134,6 +140,51 @@ class Article(models.Model): tags = models.ManyToManyField(Tag, blank=True, null=True) blog = models.ForeignKey(Blog) + + def slugify(self): + name = normalize('NFKD', self.title).encode('ascii', 'ignore').replace(' ', '-').lower() + #remove `other` characters + name = sub('[^a-zA-Z0-9_-]', '', name) + #nomalize dashes + name = sub('-+', '-', name) + self.title_slug = name + + def save(self): + self.slugify() + super(Article, self).save() + + def createArticle(self, content): + b = self.blog + b.create_paths() + output = b.src_path + if not os.path.exists(output + '/_articles'): + os.mkdir(output + '/_articles') + + filename = output + '/_articles/' + str(self.pk) + if os.path.exists(filename): + os.unlink(filename) + f = open(filename, 'wb') + f.write(content) + f.close() + + def remove(self): + b = self.blog + b.create_paths() + + output = b.src_path + filename = output + '/_articles/' + str(self.pk) + if os.path.exists(filename): + os.unlink(filename) + + output = b.output_path + filename = output + '/articles/' + self.title_slug + '.html' + if os.path.exists(filename): + os.unlink(filename) + filename = filename + '.gz' + if os.path.exists(filename): + os.unlink(filename) + + class Comment(models.Model): article = models.ForeignKey(Article) parent = models.ForeignKey('Comment') @@ -149,3 +200,7 @@ def delete_blog_signal(sender, **kwargs): @receiver(post_delete, sender=Blog) def delete_blog_signal(sender, **kwargs): sender.remove() + +@receiver(post_delete, sender=Article) +def delete_article_signal(sender, **kwargs): + sender.remove() diff --git a/templates/add_article.html b/templates/add_article.html index 7e60962..e2e6bca 100644 --- a/templates/add_article.html +++ b/templates/add_article.html @@ -1,8 +1,35 @@ {% extends "templates/base.html" %} +{% block head %} + + +{% endblock %} + {% block content %}
{% csrf_token %} {{ form.as_p }} +

{% endblock %} diff --git a/templates/base.html b/templates/base.html index e79e7f1..13a3063 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,6 +1,7 @@ Dynastie + {% block head %} {% endblock %} Users Blogs Categories Disconnect

diff --git a/templates/edit_article.html b/templates/edit_article.html index fa09932..b03f13c 100644 --- a/templates/edit_article.html +++ b/templates/edit_article.html @@ -1,8 +1,35 @@ {% extends "templates/base.html" %} +{% block head %} + + +{% endblock %} + {% block content %}
{% csrf_token %} {{ form.as_p }} - + +
{% endblock %} diff --git a/templates/edit_user.html b/templates/edit_user.html index 078b921..6a2893b 100644 --- a/templates/edit_user.html +++ b/templates/edit_user.html @@ -1,6 +1,9 @@ {% extends "templates/base.html" %} {% block content %} +{% if edited %} +

User successfuly updated

+{% endif %} {% if user.is_superuser or user.id == user_to_edit.id %}
{% csrf_token %} diff --git a/views.py b/views.py index ac1b72c..c3d5cf1 100644 --- a/views.py +++ b/views.py @@ -1,3 +1,4 @@ +import os from datetime import datetime, date, time from django.shortcuts import render from django.contrib.auth import authenticate, login, logout @@ -23,13 +24,13 @@ def index(request): c = {'auth_key': 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',\ 'login_failed' : login_failed} - return render(request, 'templates/login.html', c); + return render(request, 'templates/login.html', c) def disconnect(request): logout(request) c = {'auth_key': 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',\ 'login_failed' : False} - return render(request, 'templates/login.html', c); + return render(request, 'templates/login.html', c) @login_required def user(request): @@ -37,7 +38,7 @@ def user(request): c = {'users' : users} - return render(request, 'templates/user.html', c); + return render(request, 'templates/user.html', c) @login_required def add_user(request): @@ -66,21 +67,24 @@ def add_user(request): @login_required def edit_user(request, user_id): - if user_id != request.user.id and not request.user.is_superuser: - return HttpResponseRedirect('/user') - user = User.objects.get(pk=user_id) if user is None: raise Http404 + edited = False + if request.method == 'POST': # If the form has been submitted... + if int(user_id) != int(request.user.id) and (not request.user.is_superuser): + return HttpResponseRedirect('/user/' + str(user_id)) if 'edit' in request.POST: - form = UserForm(request.POST, instance=user) # A form bound to the POST data + form = UserForm(request.POST, instance=user, initial={'password':''}) # A form bound to the POST data if form.is_valid(): # All validation rules pass form.save() - user.set_password(request.POST['password']) + if request.POST['password'] != '': + user.set_password(request.POST['password']) user.save() + edited = True else: if 'delete' in request.POST and request.user.is_superuser: User.objects.get(pk=user_id).delete() @@ -88,11 +92,11 @@ def edit_user(request, user_id): if 'cancel' in request.POST: return HttpResponseRedirect('/user') else: - form = UserForm(instance=user) # An unbound form + form = UserForm(instance=user, initial={'password':''}) # An unbound form + + c = {'user_to_edit' : user, 'form' : form, 'edited' : edited} - c = {'user_to_edit' : user, 'form' : form} - - return render(request, 'templates/edit_user.html', c); + return render(request, 'templates/edit_user.html', c) @login_required def category(request): @@ -100,7 +104,7 @@ def category(request): c = {'categories' : categories} - return render(request, 'templates/category.html', c); + return render(request, 'templates/category.html', c) @login_required def add_category(request): @@ -143,7 +147,7 @@ def edit_category(request, category_id): c = {'category' : category, 'form' : form} - return render(request, 'templates/edit_category.html', c); + return render(request, 'templates/edit_category.html', c) @login_required def delete_category(request, category_id): @@ -168,7 +172,7 @@ def blog(request): c = {'blogs' : b} - return render(request, 'templates/blog.html', c); + return render(request, 'templates/blog.html', c) @login_required def add_blog(request): @@ -207,7 +211,7 @@ def view_blog(request, blog_id): c = {'blog' : b, 'articles' : articles, 'form' : form} - return render(request, 'templates/view_blog.html', c); + return render(request, 'templates/view_blog.html', c) @login_required def edit_blog(request, blog_id): @@ -236,12 +240,12 @@ def edit_blog(request, blog_id): c = {'blog' : b, 'articles' : articles, 'form' : form} - return render(request, 'templates/view_blog.html', c); + return render(request, 'templates/view_blog.html', c) @login_required def add_article(request, blog_id): if not request.user.is_superuser: - b = Blog.objects.filter(id=blog_id).filter(writers=request.user.id) + b = Blog.objects.filter(id=blog_id).filter(writers=request.user.id)[0] if b is None: raise Http404 @@ -249,9 +253,12 @@ def add_article(request, blog_id): if request.method == 'POST': # If the form has been submitted... if 'add' in request.POST: article = Article(blog=Blog.objects.get(pk=blog_id), author=User.objects.get(pk=request.user.id), creation_date=datetime.now()) + content = request.POST['content'] + # del request.POST['content'] form = ArticleForm(request.POST, instance=article) # A form bound to the POST data if form.is_valid(): # All validation rules pass - form.save() + form = form.save() + form.createArticle(content) # Process the data in form.cleaned_data # ... return HttpResponseRedirect('/blog/' + blog_id) # Redirect after POST @@ -271,18 +278,24 @@ def edit_article(request, article_id): if article is None: raise Http404 + title = article.title + blog_id = article.blog.id if not request.user.is_superuser: - b = Blog.objects.filter(id=article.blog.id).filter(writers=request.user.id) + b = Blog.objects.filter(pk=article.blog.id).filter(writers=request.user.id)[0] if b is None: raise Http404 + else: + b = Blog.objects.get(pk=article.blog.id) if request.method == 'POST': # If the form has been submitted... if 'edit' in request.POST: form = ArticleForm(request.POST, instance=article) # A form bound to the POST data if form.is_valid(): # All validation rules pass + if title != article.title: + article.remove() form.save() # Process the data in form.cleaned_data # ... @@ -293,8 +306,17 @@ def edit_article(request, article_id): else: form = ArticleForm(instance=article) # An unbound form + b.create_paths() + filename = b.src_path + '/_articles/' + str(article.pk) + if os.path.exists(filename): + f = open(filename, 'rb') + content = f.read() + f.close() + else: + content = 'Empty article' + return render(request, 'edit_article.html', { - 'form': form, 'article_id' : article_id + 'form': form, 'article_id' : article_id, 'content' : content }) @login_required @@ -304,14 +326,16 @@ def delete_article(request, article_id): if article is None: raise Http404 - b = Blog.objects.filter(writers=request.user.id).filter(pk=article.blog.id) - + b = Blog.objects.filter(writers=request.user.id).filter(pk=article.blog.pk) + if b is None: raise Http404 + blog_id = article.blog.pk + article.delete() - return HttpResponseRedirect('/blog/' + str(article.blog.id)) + return HttpResponseRedirect('/blog/' + str(blog_id)) @login_required def generate(request, blog_id):