Add article generator
This commit is contained in:
parent
fa07825546
commit
be306c6643
3
forms.py
3
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')
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
__all__ = ["generator", "index"]
|
||||
__all__ = ["generator", "index", "article"]
|
||||
|
|
62
generators/article.py
Normal file
62
generators/article.py
Normal file
|
@ -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
|
||||
|
|
@ -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()
|
||||
|
@ -61,6 +61,8 @@ class DynastieGenerator:
|
|||
f.write(content)
|
||||
f.close()
|
||||
|
||||
self.somethingWrote = True
|
||||
|
||||
def createElement(self, dom, name='', content=''):
|
||||
div = dom.createElement('div')
|
||||
if name != '':
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
59
models.py
59
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,12 +29,14 @@ 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()
|
||||
|
||||
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):
|
||||
|
@ -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 + '<br/>\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()
|
||||
|
|
|
@ -1,8 +1,35 @@
|
|||
{% extends "templates/base.html" %}
|
||||
|
||||
{% block head %}
|
||||
<script type="text/javascript" src="/static/js/tinymce/jscripts/tiny_mce/tiny_mce.js"></script>
|
||||
<script type="text/javascript">
|
||||
tinyMCE.init({
|
||||
// General options
|
||||
mode : "textareas",
|
||||
theme : "advanced",
|
||||
plugins : "autolink,lists,spellchecker,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template",
|
||||
editor_selector : "mceAdvanced",
|
||||
|
||||
// Theme options
|
||||
theme_advanced_buttons1 : "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,formatselect,fontselect,fontsizeselect",
|
||||
theme_advanced_buttons2 : "bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,insertdate,inserttime,preview,|,forecolor,backcolor",
|
||||
theme_advanced_buttons3 : "tablecontrols,|,hr,removeformat,visualaid,|,charmap,emotions,iespell,media,advhr",
|
||||
// theme_advanced_buttons4 : "insertlayer,moveforward,movebackward,absolute,|,styleprops,spellchecker,|,cite,abbr,acronym,del,ins,attribs,|,visualchars,nonbreaking,template,blockquote,pagebreak,|,insertfile,insertimage",
|
||||
theme_advanced_toolbar_location : "top",
|
||||
theme_advanced_toolbar_align : "left",
|
||||
theme_advanced_statusbar_location : "bottom",
|
||||
theme_advanced_resizing : true,
|
||||
width: "100%",
|
||||
height: "400"
|
||||
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<form action="/article/add/{{ blog_id }}" method="post">{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<textarea name="content" class="mceAdvanced"></textarea><br/><br/>
|
||||
<input type="submit" name="add" value="Add" /><input type="submit" name="preview" value="Preview" /><input type="submit" name="cancel" value="Cancel" />
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Dynastie</title>
|
||||
{% block head %} {% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
<a href="/user">Users</a> <a href="/blog">Blogs</a> <a href="/category">Categories</a> <a href="/disconnect">Disconnect</a><br/><br/>
|
||||
|
|
|
@ -1,8 +1,35 @@
|
|||
{% extends "templates/base.html" %}
|
||||
|
||||
{% block head %}
|
||||
<script type="text/javascript" src="/static/js/tinymce/jscripts/tiny_mce/tiny_mce.js"></script>
|
||||
<script type="text/javascript">
|
||||
tinyMCE.init({
|
||||
// General options
|
||||
mode : "textareas",
|
||||
theme : "advanced",
|
||||
plugins : "autolink,lists,spellchecker,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template",
|
||||
editor_selector : "mceAdvanced",
|
||||
|
||||
// Theme options
|
||||
theme_advanced_buttons1 : "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,formatselect,fontselect,fontsizeselect",
|
||||
theme_advanced_buttons2 : "bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,insertdate,inserttime,preview,|,forecolor,backcolor",
|
||||
theme_advanced_buttons3 : "tablecontrols,|,hr,removeformat,visualaid,|,charmap,emotions,iespell,media,advhr",
|
||||
// theme_advanced_buttons4 : "insertlayer,moveforward,movebackward,absolute,|,styleprops,spellchecker,|,cite,abbr,acronym,del,ins,attribs,|,visualchars,nonbreaking,template,blockquote,pagebreak,|,insertfile,insertimage",
|
||||
theme_advanced_toolbar_location : "top",
|
||||
theme_advanced_toolbar_align : "left",
|
||||
theme_advanced_statusbar_location : "bottom",
|
||||
theme_advanced_resizing : true,
|
||||
width: "100%",
|
||||
height: "400"
|
||||
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<form action="/article/edit/{{ article_id }}" method="post">{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<input type="submit" name="edit" value="Edit" /><input type="submit" name="cancel" value="Cancel" />
|
||||
<textarea name="content" class="mceAdvanced">{{ content }}</textarea>
|
||||
<input type="submit" name="edit" value="Edit" /><input type="submit" name="preview" value="Preview" /><input type="submit" name="cancel" value="Cancel" />
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{% extends "templates/base.html" %}
|
||||
|
||||
{% block content %}
|
||||
{% if edited %}
|
||||
<p style="color:green">User successfuly updated</p>
|
||||
{% endif %}
|
||||
{% if user.is_superuser or user.id == user_to_edit.id %}
|
||||
<form action="/user/edit/{{ user_to_edit.id }}" method="post">
|
||||
{% csrf_token %}
|
||||
|
|
66
views.py
66
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()
|
||||
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}
|
||||
c = {'user_to_edit' : user, 'form' : form, 'edited' : edited}
|
||||
|
||||
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):
|
||||
|
|
Loading…
Reference in New Issue
Block a user