Merge soutade.fr:dynastie

This commit is contained in:
Grégory Soutadé 2012-10-20 19:12:23 +02:00
commit a0ff5228f2
17 changed files with 473 additions and 125 deletions

View File

@ -17,9 +17,14 @@ class PostForm(ModelForm):
class CategoryForm(ModelForm): class CategoryForm(ModelForm):
class Meta: class Meta:
model = Category model = Category
exclude = ('parent', 'name_slug') exclude = ('parent', 'name_slug', 'blog')
class UserForm(ModelForm): class UserForm(ModelForm):
class Meta: class Meta:
model = User model = User
exclude = ('is_staff', 'is_active', 'last_login', 'last_joined', 'user_permissions', 'groups', 'date_joined') exclude = ('is_staff', 'is_active', 'last_login', 'last_joined', 'user_permissions', 'groups', 'date_joined')
class CommentForm(ModelForm):
class Meta:
model = Comment
exclude = ('post', 'parent', 'date')

View File

@ -19,6 +19,8 @@ class Archive(Index):
if node.hasAttribute('year'): if node.hasAttribute('year'):
self.replaceByText(dom, root, node, str(self.cur_year)) self.replaceByText(dom, root, node, str(self.cur_year))
return None
def createArchives(self, src, output, dom, hooks, posts): def createArchives(self, src, output, dom, hooks, posts):
filename = self.filename + '.html' filename = self.filename + '.html'
self.nb_pages = 0 self.nb_pages = 0

View File

@ -19,6 +19,7 @@ class Category(Index):
self.replaceByText(dom, root, node, self.cur_category.name) self.replaceByText(dom, root, node, self.cur_category.name)
if node.hasAttribute('description'): if node.hasAttribute('description'):
self.replaceByText(dom, root, node, self.cur_category.description) self.replaceByText(dom, root, node, self.cur_category.description)
return None
def generate(self, blog, src, output): def generate(self, blog, src, output):
from dynastie.models import Post, Blog, Category from dynastie.models import Post, Blog, Category

View File

@ -141,11 +141,13 @@ class DynastieGenerator:
else: else:
new_elem = self.createElement(dom, node.localName) new_elem = self.createElement(dom, node.localName)
new_elem.appendChild(content) new_elem.appendChild(content)
elem.appendChild(new_elem) else:
new_elem = node.cloneNode(False)
self.simpleTransform(values, dom, new_elem, node)
else: else:
new_elem = node.cloneNode(False) new_elem = node.cloneNode(False)
self.simpleTransform(values, dom, new_elem, node) self.simpleTransform(values, dom, new_elem, node)
elem.appendChild(new_elem) elem.appendChild(new_elem)
def replaceByText(self, dom, root, node, content): def replaceByText(self, dom, root, node, content):
new_node = dom.createTextNode(content) new_node = dom.createTextNode(content)
@ -155,10 +157,9 @@ class DynastieGenerator:
for node in root.childNodes: for node in root.childNodes:
if node.prefix == 'dyn': if node.prefix == 'dyn':
if node.localName in hooks: if node.localName in hooks:
hooks[node.localName](posts, dom, root, node) node = hooks[node.localName](posts, dom, root, node)
if node.hasChildNodes(): if not node is None and node.hasChildNodes():
self._parse(hooks, posts, dom, node) self._parse(hooks, posts, dom, node)
return
def parse(self, src, hooks, posts, dom, root): def parse(self, src, hooks, posts, dom, root):
bases = dom.getElementsByTagNameNS(self.URI, 'base') bases = dom.getElementsByTagNameNS(self.URI, 'base')

View File

@ -17,7 +17,7 @@ class Index(DynastieGenerator):
def createNavigation(self, posts, dom, root, node): def createNavigation(self, posts, dom, root, node):
if self.nb_pages == 0 or self.nb_pages == 1: if self.nb_pages == 0 or self.nb_pages == 1:
return '' return None
if self.dirname != '': if self.dirname != '':
if self.dirname.startswith('/'): if self.dirname.startswith('/'):
@ -58,13 +58,16 @@ class Index(DynastieGenerator):
new_dom = parseString('<div class="navigation">' + nav + '</div>') new_dom = parseString('<div class="navigation">' + nav + '</div>')
new_node = new_dom.getElementsByTagName('div')[0] new_node = new_dom.getElementsByTagName('div')[0]
root.replaceChild(new_node.cloneNode(True), node) res = new_node.cloneNode(True)
root.replaceChild(res, node)
return res
def createPost(self, post, dom, post_elem, root): def createPost(self, post, dom, post_elem, root):
values = {} values = {}
values['title'] = self.createLinkElem(dom, post.getPath(), post.title) values['title'] = self.createLinkElem(dom, post.getPath(), post.title)
values['author'] = post.author.first_name + ' ' + post.author.last_name values['author'] = post.author.first_name + ' ' + post.author.last_name
values['date'] = post.creation_date.strftime("%A, %d %B %Y %H:%m") values['date'] = post.creation_date.strftime('%A, %d %B %Y %H:%m')
values['post_content'] = '' values['post_content'] = ''
blog = post.blog blog = post.blog
@ -81,17 +84,17 @@ class Index(DynastieGenerator):
f.close() f.close()
self.simpleTransform(values, dom, post_elem, root) self.simpleTransform(values, dom, post_elem, root)
content_nodes = post_elem.getElementsByTagName("div") content_nodes = post_elem.getElementsByTagName('div')
post_transform = ('post_content') post_transform = ['post_content']
for content_node in content_nodes: for content_node in content_nodes:
the_class = content_node.getAttribute('class') the_class = content_node.getAttribute('class')
if not the_class in post_transform: if not the_class in post_transform:
continue continue
if the_class == 'post_content': new_node = dom.createTextNode(post_content)
new_node = dom.createTextNode(post_content) content_node.appendChild(new_node)
content_node.appendChild(new_node)
def createPosts(self, posts, dom, root, node): def createPosts(self, posts, dom, root, node):
posts_elem = self.createElement(dom, 'posts') posts_elem = self.createElement(dom, 'posts')
for i in range(0, self.posts_per_page): for i in range(0, self.posts_per_page):
@ -106,6 +109,7 @@ class Index(DynastieGenerator):
if self.cur_post == len(posts): if self.cur_post == len(posts):
break break
root.replaceChild(posts_elem, node) root.replaceChild(posts_elem, node)
return posts_elem
def createRecents(self, posts, dom, root, node): def createRecents(self, posts, dom, root, node):
if self.cur_post == len(posts): if self.cur_post == len(posts):
@ -132,6 +136,8 @@ class Index(DynastieGenerator):
recents_elem.appendChild(list_elem) recents_elem.appendChild(list_elem)
root.replaceChild(recents_elem, node) root.replaceChild(recents_elem, node)
return recents_elem
def generate(self, blog, src, output): def generate(self, blog, src, output):
from dynastie.models import Post, Blog from dynastie.models import Post, Blog

View File

@ -4,9 +4,94 @@ from xml.dom.minidom import parse, parseString
from dynastie.generators.generator import DynastieGenerator, StrictUTF8Writer from dynastie.generators.generator import DynastieGenerator, StrictUTF8Writer
from dynastie.generators.index import Index from dynastie.generators.index import Index
from django.db import models from django.db import models
from dynastie.tree import TreeNode
class Post(Index): class Post(Index):
cur_comment = None
comment_index = {}
def createReplace(self, post, dom, root, replace_elem):
if not replace_elem.hasAttribute('div_name'):
self.addError('No attribute div_name for a replace tag')
return
div_element = replace_elem.cloneNode(True)
div_element.tagName = replace_elem.getAttribute('div_name')
div_element.removeAttribute('div_name')
for key,value in replace_elem.attributes.items():
if key == 'div_name': continue
value = value.replace('dyn:post_id', str(post.id))
if self.cur_comment is None:
value = value.replace('dyn:comment_index', '0')
else:
value = value.replace('dyn:comment_index', str(self.comment_index[self.cur_comment.id]))
if self.cur_comment is None:
value = value.replace('dyn:comment_id', '0')
else:
value = value.replace('dyn:comment_id', str(self.cur_comment.id))
div_element.setAttribute(key, value)
root.replaceChild(div_element, replace_elem)
return div_element
def createComment(self, comment, dom, comment_elem, root):
values = {}
values['comment_index'] = str(self.comment_index[comment.id])
values['comment_author'] = comment.author
values['comment_date'] = comment.date.strftime('%d %B %Y %H:%m')
values['comment_content'] = comment.the_comment
self.simpleTransform(values, dom, comment_elem, root)
def _createComments(self, rootNode, post, dom, root_comment, root):
self.cur_comment = rootNode.value
comment_element = self.createElement(dom, 'comment')
self.createComment(self.cur_comment, dom, comment_element, root)
root_comment.appendChild(comment_element)
# Parse inner HTML
self._parse(self.hooks, post, dom, comment_element)
for commentNode in rootNode.childs:
self._createComments(commentNode, post, dom, comment_element, root)
def createComments(self, post, dom, post_elem, root):
from dynastie.models import Post, Blog, Comment
comments = Comment.objects.filter(post=post).order_by('date')
cur_comment = None
comment_index = {}
index = 1
rootNode = TreeNode('', '')
for comment in comments:
self.comment_index[comment.id] = index
index = index + 1
tnode = TreeNode(comment.id, comment)
if comment.parent is None:
rootNode.addChildNode(tnode)
else:
temp = rootNode.find(comment.parent.id)
if temp is None:
self.addWarning('Error with comments chain')
rootNode.addChildNode(tnode)
else:
temp.addChildNode(tnode)
initial_root_comment = root_comment = self.createElement(dom, 'comments')
for tnode in rootNode.childs:
self._createComments(tnode, post, dom, root_comment, root)
# Empty tag seems to crap rendering
if len(rootNode.childs) == 0:
post_elem.removeChild(root)
return None
else:
post_elem.replaceChild(root_comment, root)
return root_comment
def createMetas(self, post, dom, meta_elem, root): def createMetas(self, post, dom, meta_elem, root):
name = root.getAttribute('name') name = root.getAttribute('name')
if name is None: if name is None:
@ -25,11 +110,17 @@ class Post(Index):
if not new_elem is None: if not new_elem is None:
root.parentNode.replaceChild(new_elem, root) root.parentNode.replaceChild(new_elem, root)
return new_elem
else: else:
self.addError('name attribute \'' + name + '\' unknown for dyn:meta' ) self.addError('name attribute \'' + name + '\' unknown for dyn:meta' )
return None
def _createPost(self, post, dom, post_elem, root): def _createPost(self, post, dom, post_elem, root):
import sys, traceback
self.createPost(post, dom, post_elem, root) self.createPost(post, dom, post_elem, root)
# Post are appended by index. Remove template
post_nodes = dom.getElementsByTagNameNS(self.URI, 'post') post_nodes = dom.getElementsByTagNameNS(self.URI, 'post')
post_elem = post_nodes[0] post_elem = post_nodes[0]
post_elem.parentNode.removeChild(post_elem) post_elem.parentNode.removeChild(post_elem)
@ -42,31 +133,33 @@ class Post(Index):
node.removeChild(node.childNodes[0]) node.removeChild(node.childNodes[0])
node.appendChild(dom.createTextNode(post.title)) node.appendChild(dom.createTextNode(post.title))
def generate(self, blog, src, output): return node
from dynastie.models import Post, Blog
hooks = {'post' : self._createPost, def _generate(self, blog, src, output, posts):
'meta' : self.createMetas} import xml
self.hooks = {'post' : self._createPost,
'meta' : self.createMetas,
'comments' : self.createComments,
'replace' : self.createReplace}
if not os.path.exists(src + '/_post.html'): if not os.path.exists(src + '/_post.html'):
self.addError('No _post.html found, exiting') self.addError('No _post.html found, exiting')
return self.report return self.report
if not os.path.exists(output + '/post'):
os.mkdir(output + '/post')
try: try:
dom = parse(src + '/_post.html') dom = parse(src + '/_post.html')
except xml.dom.DOMException as e: except xml.dom.DOMException as e:
self.addError('Error parsing _post.html : ' + e) self.addError('Error parsing _post.html : ' + e)
return self.report return self.report
if not os.path.exists(output + '/post'):
os.mkdir(output + '/post')
posts = Post.objects.all()
for post in posts: for post in posts:
#print 'Generate ' + filename #print 'Generate ' + filename
nodes = dom.getElementsByTagName("*") nodes = dom.getElementsByTagName("*")
nodes[0] = self.parse(src, hooks, post, dom, nodes[0]) nodes[0] = self.parse(src, self.hooks, post, dom, nodes[0])
filename = output + '/post/' filename = output + '/post/'
filename = filename + post.creation_date.strftime("%Y") + '/' + post.creation_date.strftime("%m") + '/' filename = filename + post.creation_date.strftime("%Y") + '/' + post.creation_date.strftime("%m") + '/'
if not os.path.exists(filename): if not os.path.exists(filename):
@ -80,6 +173,13 @@ class Post(Index):
return self.report return self.report
def generate(self, blog, src, output):
from dynastie.models import Post, Blog
posts = Post.objects.all()
return self._generate(blog, src, output, posts)
def createPreview(self, values, dom, root, node): def createPreview(self, values, dom, root, node):
now = datetime.datetime.now() now = datetime.datetime.now()
@ -105,10 +205,12 @@ class Post(Index):
post_elem = post_nodes[0] post_elem = post_nodes[0]
post_elem.parentNode.removeChild(post_elem) post_elem.parentNode.removeChild(post_elem)
return post_elem
def preview(self, src, values): def preview(self, src, values):
from dynastie.models import Blog from dynastie.models import Blog
hooks = {'post' : self.createPreview} self.hooks = {'post' : self.createPreview}
if not os.path.exists(src + '/_post.html'): if not os.path.exists(src + '/_post.html'):
self.addError('No _post.html found, exiting') self.addError('No _post.html found, exiting')
@ -127,7 +229,7 @@ class Post(Index):
return self.report return self.report
nodes = dom.getElementsByTagName("*") nodes = dom.getElementsByTagName("*")
nodes[0] = self.parse(src, hooks, values, dom, nodes[0]) nodes[0] = self.parse(src, self.hooks, values, dom, nodes[0])
writer = StrictUTF8Writer() writer = StrictUTF8Writer()
nodes[0].writexml(writer) nodes[0].writexml(writer)

View File

@ -141,7 +141,7 @@ class Blog(models.Model):
if not inspect.ismodule(engine): if not inspect.ismodule(engine):
continue continue
for name, obj in inspect.getmembers(engine): for name, obj in inspect.getmembers(engine):
if inspect.isclass(obj) and obj.__module__.startswith("dynastie"): if inspect.isclass(obj) and obj.__module__.startswith("dynastie.generators"):
if obj.__module__ in generated: continue if obj.__module__ in generated: continue
e = obj() e = obj()
r = e.generate(self, self.src_path, self.output_path) r = e.generate(self, self.src_path, self.output_path)
@ -159,6 +159,7 @@ class Category(models.Model):
name_slug = models.CharField(max_length=255) name_slug = models.CharField(max_length=255)
parent = models.ForeignKey('self', blank=True, null=True) parent = models.ForeignKey('self', blank=True, null=True)
description = models.TextField(max_length=255, blank=True) description = models.TextField(max_length=255, blank=True)
blog = models.ForeignKey(Blog)
def slugify(self): def slugify(self):
name = normalize('NFKD', self.name).encode('ascii', 'ignore').replace(' ', '-').lower() name = normalize('NFKD', self.name).encode('ascii', 'ignore').replace(' ', '-').lower()
@ -181,6 +182,7 @@ class Category(models.Model):
class Tag(models.Model): class Tag(models.Model):
name = models.CharField(max_length=255, unique=True) name = models.CharField(max_length=255, unique=True)
blog = models.ForeignKey(Blog)
class Post(models.Model): class Post(models.Model):
title = models.CharField(max_length=255) title = models.CharField(max_length=255)
@ -257,11 +259,12 @@ class Post(models.Model):
class Comment(models.Model): class Comment(models.Model):
post = models.ForeignKey(Post) post = models.ForeignKey(Post)
parent = models.ForeignKey('Comment') parent = models.ForeignKey('self', null=True, blank=True)
date = models.DateField(max_length=255) date = models.DateTimeField()
author = models.CharField(max_length=255) author = models.CharField(max_length=255)
email = models.EmailField(max_length=255) email = models.EmailField(max_length=255, blank=True)
the_comment = models.TextField(max_length=255) the_comment = models.TextField(max_length=255)
ip = models.GenericIPAddressField()
@receiver(post_init, sender=Blog) @receiver(post_init, sender=Blog)
def delete_blog_signal(sender, **kwargs): def delete_blog_signal(sender, **kwargs):

View File

@ -4,7 +4,7 @@
{% block head %} {% endblock %} {% block head %} {% endblock %}
</head> </head>
<body> <body>
<a href="/user">Users</a> <a href="/blog">Blogs</a> <a href="/category">Categories</a> <a href="/disconnect">Disconnect</a><br/><br/> <a href="/user">Users</a> <a href="/blog">Blogs</a> <a href="/disconnect">Disconnect</a><br/><br/>
{% block content %} {% endblock %} {% block content %} {% endblock %}
</body> </body>
</html> </html>

View File

@ -5,12 +5,12 @@
{% if categories|length == 0 %} {% if categories|length == 0 %}
<b>Any category available</b><br/><br/> <b>Any category available</b><br/><br/>
{% else %} {% else %}
<table>
{% for category in categories %} {% for category in categories %}
<hr><hl>{{ category.id }}</hl><hl>{{ category.name }}</hl><hl><a href="/category/edit/{{ category.id }}">Edit</a></hl>{% if user.is_superuser %}<hl><a href="/category/delete/{{ category.id }}">Delete</a></hl>{% endif %}</hr> <tr><td>{{ category.id }}</td><td>{{ category.name }}</td><td><a href="/category/edit/{{ category.id }}">Edit</a></td><td><a href="/category/delete/{{ category.id }}">Delete</a></td></tr>
{% endfor %} {% endfor %}
</table>
{% endif %} {% endif %}
{% if user.is_superuser %} <li><a href="/category/add">Add a category</a></li>
<li><a href="/category/add">Add a category</a></li>
{% endif %}
</table> </table>
{% endblock %} {% endblock %}

View File

@ -4,10 +4,6 @@
<form action="/category/edit/{{ category.id }}" method="post"> <form action="/category/edit/{{ category.id }}" method="post">
{% csrf_token %} {% csrf_token %}
{{ form.as_p }} {{ form.as_p }}
{% if user.is_superuser %} <input type="submit" name="edit" value="Edit" /> <input type="submit" name="cancel" value="Cancel" />
<input type="submit" name="edit" value="Edit" />
{% else %}
<input type="submit" name="cancel" value="Cancel" />
{% endif %}
</form> </form>
{% endblock %} {% endblock %}

View File

@ -0,0 +1,9 @@
{% extends "templates/base.html" %}
{% block content %}
<form action="/comment/edit/{{ comment.id }}" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" name="edit" value="Edit" /><input type="submit" name="cancel" value="Cancel" />
</form>
{% endblock %}

View File

@ -14,4 +14,15 @@
<textarea name="content" class="mceAdvanced">{{ content }}</textarea> <textarea name="content" class="mceAdvanced">{{ content }}</textarea>
<input type="submit" name="edit" value="Edit" /><input type="button" name="preview" value="Preview" onClick="previewPost();"/><input type="submit" name="cancel" value="Cancel" /> <input type="submit" name="edit" value="Edit" /><input type="button" name="preview" value="Preview" onClick="previewPost();"/><input type="submit" name="cancel" value="Cancel" />
</form> </form>
<div class="comments">
{% for comment in comments %}
<div class="comment">
<div class="infos">
<a href="/comment/edit/{{ comment.id }}">#{{ comment.id }}</a> <span class="author">{{ comment.author }}</span> <span class="mail">{{ comment.email|default:"no mail" }}</span> <span class="date">{{ comment.date|date:"D d M Y" }}<span> <a href="/comment/delete/{{ comment.id }}">delete</a>
</div>
<div class="content">
{{ comment.the_comment }}
</div>
{% endfor %}
</div>
{% endblock %} {% endblock %}

View File

@ -1,6 +1,7 @@
{% extends "templates/base.html" %} {% extends "templates/base.html" %}
{% block content %} {% block content %}
<a href="/category/{{ blog.id }}">Categories</a>
{% if user.is_superuser %} {% if user.is_superuser %}
<form action="/blog/edit/{{ blog.id }}" method="post"> <form action="/blog/edit/{{ blog.id }}" method="post">
{% csrf_token %} {% csrf_token %}
@ -24,7 +25,9 @@
{% else %} {% else %}
<table> <table>
{% for post in posts %} {% for post in posts %}
<tr><td><a href="/post/edit/{{ post.id }}">{{ post.id }}</a></td><td>{{ post.title }}</td><td>{{ post.category.name }}</td><td>{{ post.creation_date }}</td><td>{{ post.modification_date }}</td><td>{{ post.published }}</td><td>{{ post.front_page }}</td><td><a href="/post/delete/{{ post.id }}">Delete</a></td></tr> {% with post.id as cur_id %}
<tr><td><a href="/post/edit/{{ post.id }}">{{ post.id }}</a></td><td>{{ post.title }}</td><td>{{ post.category.name }}</td><td>{{ post.creation_date }}</td><td>{{ post.modification_date }}</td><td>{{ post.published }}</td><td>{{ post.front_page }}</td><td>{{ comments|hash:cur_id|default_if_none:"0" }} comment{{ comments|hash:cur_id|pluralize }}</td><td><a href="/post/delete/{{ post.id }}">Delete</a></td></tr>
{% endwith %}
{% endfor %} {% endfor %}
{% endif %} {% endif %}
</table> </table>

View File

@ -1,6 +1,7 @@
{% extends "templates/base.html" %} {% extends "templates/base.html" %}
{% block content %} {% block content %}
<a href="/category/{{ blog.id }}">Categories</a>
{% if user.is_superuser %} {% if user.is_superuser %}
<form action="/blog/edit/{{ blog.id }}" method="post"> <form action="/blog/edit/{{ blog.id }}" method="post">
{% csrf_token %} {% csrf_token %}
@ -17,7 +18,9 @@
{% else %} {% else %}
<table> <table>
{% for post in posts %} {% for post in posts %}
<tr><td><a href="/post/edit/{{ post.id }}">{{ post.id }}</a></td><td>{{ post.title }}</td><td>{{ post.category.name }}</td><td>{{ post.creation_date }}</td><td>{{ post.modification_date }}</td><td>{{ post.published }}</td><td>{{ post.front_page }}</td><td><a href="/post/delete/{{ post.id }}">Delete</a></td></tr> {% with post.id as cur_id %}
<tr><td><a href="/post/edit/{{ post.id }}">{{ post.id }}</a></td><td>{{ post.title }}</td><td>{{ post.category.name }}</td><td>{{ post.creation_date }}</td><td>{{ post.modification_date }}</td><td>{{ post.published }}</td><td>{{ post.front_page }}</td><td>{{ comments|hash:cur_id|default_if_none:"0" }} comment{{ comments|hash:cur_id|pluralize }}</td><td><a href="/post/delete/{{ post.id }}">Delete</a></td></tr>
{% endwith %}
{% endfor %} {% endfor %}
{% endif %} {% endif %}
</table> </table>

21
tree.py Normal file
View File

@ -0,0 +1,21 @@
class TreeNode():
def __init__(self, key, value):
self.childs = []
self.key = key
self.value = value
def addChildNode(self, node):
self.childs.append(node)
def hasChilds(self):
return (len(self.childs) > 0)
def find(self, key):
if key == self.key: return self
for child in self.childs:
r = child.find(key)
if r != None: return r
return None

17
urls.py
View File

@ -13,21 +13,24 @@ urlpatterns = patterns('',
url(r'^user/add$', 'dynastie.views.add_user', name='add_user'), url(r'^user/add$', 'dynastie.views.add_user', name='add_user'),
url(r'^user/edit/(\d+)$', 'dynastie.views.edit_user', name='edit_user'), url(r'^user/edit/(\d+)$', 'dynastie.views.edit_user', name='edit_user'),
url(r'^user/(\d+)$', 'dynastie.views.edit_user', name='view_user'), url(r'^user/(\d+)$', 'dynastie.views.edit_user', name='view_user'),
url(r'^category$', 'dynastie.views.category', name='category'), url(r'^category/(\d+)$', 'dynastie.views.category', name='category'),
url(r'^category/add$', 'dynastie.views.add_category', name='add_category'), url(r'^category/add/(\d+)$', 'dynastie.views.add_category', name='add_category'),
url(r'^category/edit/(\d+)$', 'dynastie.views.edit_category', name='edit_category'), url(r'^category/edit/(\d+)$', 'dynastie.views.edit_category', name='edit_category'),
url(r'^category/delete/(\d+)$', 'dynastie.views.delete_category', name='delete_category'), url(r'^category/delete/(\d+)$', 'dynastie.views.delete_category', name='delete_category'),
url(r'^blog$', 'dynastie.views.blog', name='blog'), url(r'^blog$', 'dynastie.views.blog', name='blog'),
url(r'^blog/add$', 'dynastie.views.add_blog', name='add_blog'), url(r'^blog/add$', 'dynastie.views.add_blog', name='add_blog'),
url(r'^blog/(\d+)$', 'dynastie.views.view_blog', name='view_blog'), url(r'^blog/(\d+)$', 'dynastie.views.view_blog', name='view_blog'),
url(r'^blog/edit/(\d+)$', 'dynastie.views.edit_blog', name='edit_blog'), url(r'^blog/edit/(\d+)$', 'dynastie.views.edit_blog', name='edit_blog'),
url(r'^post/add/(\d+)$', 'dynastie.views.add_post', name='add_post'), url(r'^post/add/(\d+)$', 'dynastie.views.add_post', name='add_post'),
url(r'^post/edit/(\d+)$', 'dynastie.views.edit_post', name='edit_post'), url(r'^post/edit/(\d+)$', 'dynastie.views.edit_post', name='edit_post'),
url(r'^post/delete/(\d+)$','dynastie.views.delete_post', name='delete_post'), url(r'^post/delete/(\d+)$', 'dynastie.views.delete_post', name='delete_post'),
url(r'^generate/(\d+)$', 'dynastie.views.generate', name='generate'), url(r'^generate/(\d+)$', 'dynastie.views.generate', name='generate'),
url(r'^preview/(\d+)$', 'dynastie.views.preview', name='preview'), url(r'^preview/(\d+)$', 'dynastie.views.preview', name='preview'),
url(r'^tinyMCEExternalList/post/add/(\d+)$', 'dynastie.views.tinymcelist_add', name='tinymce'), url(r'^tinyMCEExternalList/post/add/(\d+)$', 'dynastie.views.tinymcelist_add', name='tinymce'),
url(r'^tinyMCEExternalList/post/edit/(\d+)$', 'dynastie.views.tinymcelist_edit', name='tinymce'), url(r'^tinyMCEExternalList/post/edit/(\d+)$', 'dynastie.views.tinymcelist_edit', name='tinymce'),
url(r'^comment/add/(\d+)/(\d+)$', 'dynastie.views.add_comment', name='add_comment'),
url(r'^comment/edit/(\d+)$', 'dynastie.views.edit_comment', name='edit_comment'),
url(r'^comment/delete/(\d+)$','dynastie.views.delete_comment',name='delete_comment'),
# url(r'^dynastie/', include('dynastie.foo.urls')), # url(r'^dynastie/', include('dynastie.foo.urls')),
# Uncomment the admin/doc line below to enable admin documentation: # Uncomment the admin/doc line below to enable admin documentation:

330
views.py
View File

@ -1,13 +1,60 @@
# -*- coding: utf-8 -*-
import os import os
from datetime import datetime, date, time from datetime import datetime, date, time
from django.shortcuts import render from django.shortcuts import render
from django.contrib.auth import authenticate, login, logout from django.contrib.auth import authenticate, login, logout
from django.http import HttpResponseRedirect, HttpResponse, Http404 from django.http import HttpResponseRedirect, HttpResponse, Http404
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.views.decorators.csrf import csrf_exempt
from django.forms.models import inlineformset_factory from django.forms.models import inlineformset_factory
from django.core import mail
from django.core.mail import EmailMultiAlternatives
from dynastie.models import * from dynastie.models import *
from dynastie.forms import * from dynastie.forms import *
from django.template.defaultfilters import register
from django.template import Variable, VariableDoesNotExist
@register.filter
def hash(object, attr):
pseudo_context = { 'object' : object }
try:
value = Variable('object.%s' % attr).resolve(pseudo_context)
except VariableDoesNotExist:
value = None
return value
def have_I_right(request, blog_id=None, post_id=None, must_be_superuser=False):
b = None
p = None
if must_be_superuser and not request.user.is_superuser:
raise Http404
if not post_id is None:
p = Post.objects.get(pk=post_id)
if p is None:
raise Http404
blog_id = p.blog.id
if not blog_id is None:
if not request.user.is_superuser:
b = Blog.objects.filter(pk=blog_id).filter(writers=request.user.id)
if len(b) == 0:
raise Http404
b = b[0]
else:
b = Blog.objects.get(pk=post.blog.id)
if b is None:
raise Http404
return (b, p)
def index(request): def index(request):
if request.user.is_authenticated(): if request.user.is_authenticated():
return HttpResponseRedirect('/blog') return HttpResponseRedirect('/blog')
@ -19,7 +66,10 @@ def index(request):
login_failed = True login_failed = True
else: else:
login(request, user) login(request, user)
return HttpResponseRedirect('/blog') if 'next' in request.GET:
return HttpResponseRedirect(request.GET['next'])
else:
return HttpResponseRedirect('/blog')
c = {'auth_key': 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',\ c = {'auth_key': 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',\
'login_failed' : login_failed} 'login_failed' : login_failed}
@ -99,28 +149,30 @@ def edit_user(request, user_id):
return render(request, 'templates/edit_user.html', c) return render(request, 'templates/edit_user.html', c)
@login_required @login_required
def category(request): def category(request, blog_id):
categories = Category.objects.all() b = have_I_right(request, blog_id)
categories = Category.objects.filter(blog_id=blog_id)
c = {'categories' : categories} c = {'categories' : categories}
return render(request, 'templates/category.html', c) return render(request, 'templates/category.html', c)
@login_required @login_required
def add_category(request): def add_category(request, blog_id):
if not request.user.is_superuser: b = have_I_right(request, blog_id)[0]
return HttpResponseRedirect('/category')
if request.method == 'POST': # If the form has been submitted... if request.method == 'POST': # If the form has been submitted...
if 'add' in request.POST: if 'add' in request.POST:
form = CategoryForm(request.POST) # A form bound to the POST data form = CategoryForm(request.POST) # A form bound to the POST data
form.blog = b
if form.is_valid(): # All validation rules pass if form.is_valid(): # All validation rules pass
form = form.save() form = form.save()
# Process the data in form.cleaned_data # Process the data in form.cleaned_data
# ... # ...
return HttpResponseRedirect('/category') # Redirect after POST return HttpResponseRedirect('/category/' + str(b.id))
else: else:
return HttpResponseRedirect('/category') # Redirect after POST return HttpResponseRedirect('/category/' + str(b.id))
else: else:
form = CategoryForm() # An unbound form form = CategoryForm() # An unbound form
@ -135,16 +187,19 @@ def edit_category(request, category_id):
if category is None: if category is None:
raise Http404 raise Http404
b = have_I_right(request, category.blog.id)[0]
if request.method == 'POST': # If the form has been submitted... if request.method == 'POST': # If the form has been submitted...
if 'cancel' in request.POST: if 'cancel' in request.POST:
return HttpResponseRedirect('/category') return HttpResponseRedirect('/category' + str(b.id))
if 'edit' in request.POST and request.user.is_superuser: if 'edit' in request.POST:
name = category.name name = category.name
form = CategoryForm(request.POST, instance=category) # A form bound to the POST data form = CategoryForm(request.POST, instance=category) # A form bound to the POST data
if form.is_valid(): # All validation rules pass if form.is_valid(): # All validation rules pass
if request.POST['name'] != name: if request.POST['name'] != name:
category.remove() category.remove()
form.save() form.save()
return HttpResponseRedirect('/category/' + str(b.id))
else: else:
form = CategoryForm(instance=category) # An unbound form form = CategoryForm(instance=category) # An unbound form
@ -154,18 +209,17 @@ def edit_category(request, category_id):
@login_required @login_required
def delete_category(request, category_id): def delete_category(request, category_id):
if not request.user.is_superuser:
return HttpResponseRedirect('/category/' + str(category_id))
category = Category.objects.get(pk=category_id) category = Category.objects.get(pk=category_id)
if category is None: if category is None:
raise Http404 raise Http404
b = have_I_right(request, category.blog.id)[0]
category.remove() category.remove()
category.delete() category.delete()
return HttpResponseRedirect('/category') return HttpResponseRedirect('/category/' + str(b.id))
@login_required @login_required
def blog(request): def blog(request):
@ -213,7 +267,16 @@ def view_blog(request, blog_id):
b = Blog.objects.get(pk=blog_id) b = Blog.objects.get(pk=blog_id)
form = BlogForm(instance=b) form = BlogForm(instance=b)
c = {'blog' : b, 'posts' : posts, 'form' : form} comments = Comment.objects.all()
dict_comments = {}
for comment in comments:
key = comment.post.id
if not key in dict_comments:
dict_comments[key] = 1
else:
dict_comments[key] = dict_comments[key] + 1
c = {'blog' : b, 'posts' : posts, 'form' : form, 'comments' : dict_comments}
return render(request, 'templates/view_blog.html', c) return render(request, 'templates/view_blog.html', c)
@ -248,11 +311,7 @@ def edit_blog(request, blog_id):
@login_required @login_required
def add_post(request, blog_id): def add_post(request, blog_id):
if not request.user.is_superuser: (b,) = have_I_right(request, blog_id)
b = Blog.objects.filter(id=blog_id).filter(writers=request.user.id)[0]
if b is None:
raise Http404
if request.method == 'POST': # If the form has been submitted... if request.method == 'POST': # If the form has been submitted...
if 'add' in request.POST: if 'add' in request.POST:
@ -277,22 +336,11 @@ def add_post(request, blog_id):
@login_required @login_required
def edit_post(request, post_id): def edit_post(request, post_id):
(b, post) = have_I_right(request, None, post_id)
post = Post.objects.get(pk=post_id) post = Post.objects.get(pk=post_id)
if post is None:
raise Http404
title = post.title title = post.title
blog_id = b.id
blog_id = post.blog.id
if not request.user.is_superuser:
b = Blog.objects.filter(pk=post.blog.id).filter(writers=request.user.id)[0]
if b is None:
raise Http404
else:
b = Blog.objects.get(pk=post.blog.id)
if request.method == 'POST': # If the form has been submitted... if request.method == 'POST': # If the form has been submitted...
if 'edit' in request.POST: if 'edit' in request.POST:
@ -301,8 +349,8 @@ def edit_post(request, post_id):
if form.is_valid(): # All validation rules pass if form.is_valid(): # All validation rules pass
if title != request.POST['title']: if title != request.POST['title']:
post.remove() post.remove()
post.createPost(request.POST['content'])
form.save() form.save()
post.createPost(request.POST['content'])
# Process the data in form.cleaned_data # Process the data in form.cleaned_data
# ... # ...
return HttpResponseRedirect('/blog/' + str(blog_id)) # Redirect after POST return HttpResponseRedirect('/blog/' + str(blog_id)) # Redirect after POST
@ -321,24 +369,21 @@ def edit_post(request, post_id):
else: else:
content = 'Empty post' content = 'Empty post'
comments = Comment.objects.filter(post=post).order_by('date')
comment_list = []
for comment in comments:
comment_list.append(comment)
return render(request, 'edit_post.html', { return render(request, 'edit_post.html', {
'form': form, 'post_id' : post_id, 'content' : content, 'form': form, 'post_id' : post_id, 'content' : content,
'blog_id' : blog_id 'blog_id' : blog_id, 'comments' : comment_list
}) })
@login_required @login_required
def delete_post(request, post_id): def delete_post(request, post_id):
post = Post.objects.get(pk=post_id) (b, post) = have_I_right(request, None, post_id)
if post is None: blog_id = b.id
raise Http404
b = Blog.objects.filter(writers=request.user.id).filter(pk=post.blog.pk)
if b is None:
raise Http404
blog_id = post.blog.pk
post.delete() post.delete()
@ -346,13 +391,7 @@ def delete_post(request, post_id):
@login_required @login_required
def generate(request, blog_id): def generate(request, blog_id):
if not request.user.is_superuser: (b, post) = have_I_right(request, blog_id)
b = Blog.objects.filter(id=blog_id).filter(writers=request.user.id)[0]
else:
b = Blog.objects.get(pk=blog_id)
if b is None:
raise Http404
b.create_paths() b.create_paths()
report = b.generate() report = b.generate()
@ -361,7 +400,16 @@ def generate(request, blog_id):
b = Blog.objects.get(pk=blog_id) b = Blog.objects.get(pk=blog_id)
form = BlogForm(instance=b) form = BlogForm(instance=b)
c = {'blog' : b, 'posts' : posts, 'form' : form, 'report': report} comments = Comment.objects.all()
dict_comments = {}
for comment in comments:
key = comment.post.id
if not key in dict_comments:
dict_comments[key] = 1
else:
dict_comments[key] = dict_comments[key] + 1
c = {'blog' : b, 'posts' : posts, 'form' : form, 'report': report, 'comments' : dict_comments}
return render(request, 'templates/generate.html', c) return render(request, 'templates/generate.html', c)
@ -374,20 +422,14 @@ def preview(request, blog_id):
'content' : request.POST['content'] 'content' : request.POST['content']
} }
if not request.user.is_superuser: (b, ) = have_I_right(request, blog_id)
b = Blog.objects.filter(id=blog_id).filter(writers=request.user.id)[0]
else:
b = Blog.objects.get(pk=blog_id)
if b is None:
raise Http404
b.create_paths() b.create_paths()
engine = globals()['post'] engine = globals()['post']
for name, obj in inspect.getmembers(engine): for name, obj in inspect.getmembers(engine):
if inspect.isclass(obj) and obj.__module__.startswith("dynastie") \ if inspect.isclass(obj) and obj.__module__.startswith("dynastie.generators") \
and obj.__module__.endswith("post"): and obj.__module__.endswith("post"):
e = obj() e = obj()
content = e.preview(b.src_path, values) content = e.preview(b.src_path, values)
@ -435,34 +477,174 @@ def _tinymcelist(request, b, year, month):
@login_required @login_required
def tinymcelist_add(request, blog_id): def tinymcelist_add(request, blog_id):
from datetime import datetime
now = datetime.now() now = datetime.now()
year = now.year year = now.year
month = now.month month = now.month
b = Blog.objects.filter(pk=blog_id).filter(writers=request.user.id)[0]
if b is None: try:
(b, ) = have_I_right(request, blog_id)
except Http404:
return HttpResponse('', content_type='application/x-javascript') return HttpResponse('', content_type='application/x-javascript')
ret = _tinymcelist(request, b, year, month) ret = _tinymcelist(request, b, year, month)
print 'Ret1 ' + ret
return HttpResponse(ret, content_type='application/x-javascript') return HttpResponse(ret, content_type='application/x-javascript')
@login_required @login_required
def tinymcelist_edit(request, post_id): def tinymcelist_edit(request, post_id):
post = Post.objects.filter(pk=post_id) try:
if post is None: (b, post) = have_I_right(request, None, post_id)
return HttpResponse('', content_type='application/x-javascript') except Http404:
b = Blog.objects.filter(pk=post.blog).filter(writers=request.user.id)[0]
if b is None:
return HttpResponse('', content_type='application/x-javascript') return HttpResponse('', content_type='application/x-javascript')
year = post.creation_date.year() year = post.creation_date.year()
month = post.creation_date.month() month = post.creation_date.month()
ret = _tinymcelist(request, b, year, month) ret = _tinymcelist(request, b, year, month)
print 'Ret2 ' + ret
return HttpResponse(ret, content_type='application/x-javascript') return HttpResponse(ret, content_type='application/x-javascript')
@csrf_exempt
def add_comment(request, post_id, parent_id):
from dynastie.generators import post
ref = request.META['HTTP_REFERER']
post = Post.objects.get(pk=post_id)
if post is None:
print 'no post'
return HttpResponseRedirect(ref)
blog = Blog.objects.get(pk=post.blog_id)
if blog is None:
print 'no blog ' + str(post.blog.id)
return HttpResponseRedirect(ref)
parent_id = int(parent_id)
if parent_id != 0:
parentComment = Comment.objects.get(pk=parent_id)
if parentComment is None:
return HttpResponseRedirect(ref)
else:
parentComment = None
if request.POST['author'] == '' or request.POST['the_comment'] == '':
print 'Error on author or the_comment'
return HttpResponseRedirect(ref)
comment = Comment(post=post, parent=parentComment, date=datetime.now(), author=request.POST['author'],\
email=request.POST['email'], the_comment=request.POST['the_comment'], ip=request.META['REMOTE_ADDR'])
comment.save()
engine = globals()['post']
blog.create_paths()
post_list = [post]
for name, obj in inspect.getmembers(engine):
if inspect.isclass(obj) and obj.__module__.startswith("dynastie.generators") \
and obj.__module__.endswith("post"):
e = obj()
content = e._generate(blog, blog.src_path, blog.output_path, post_list)
break
# Send emails
emails = {}
comments = Comment.objects.filter(post=post).order_by('date')
comment_index = str(len(comments))
for comment in comments:
email = comment.email
if email != '' and not email in emails:
emails[email] = comment.author
if len(emails) > 0:
connection = mail.get_connection(fail_silently=True)
connection.open()
messages = []
subject = '[%s] Nouveau commentaire pour l\'article "%s"' % (blog.name, post.title)
for email,author in emails.items():
text_body = u'Bonjour %s,\n\nUn nouveau commentaire a été posté pour l\'article "%s".\n\n' % (author, post.title)
text_body += u'Pour le consulter, rendez vous sur http://%s%s/#comment_%s\n\n----------------\n\n' % (blog.name, post.getPath(), comment_index)
text_body += comment.the_comment
text_body += '\n'
html_body = u'<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8" /></head><body>'
html_body += u'Bonjour %s,<br/><br/>Un nouveau commentaire a été posté pour l\'article "%s".<br/><br/>' % (author, post.title)
html_body = html_body + u'Pour le consulter, rendez vous sur <a href="http://%s%s#comment_%s">http://%s/%s#comment_%s</a><br/><br/>----------------<br/><pre>' % (blog.name, post.getPath(), comment_index, blog.name, post.getPath(), comment_index)
c = comment.the_comment
# Avoid script injection
c = c.replace('<pre>', '&lt;pre&gt;')
c = c.replace('</pre>', '&lt;/pre&gt;')
html_body += c + '</pre>'
html_body += '</body></html>'
msg = EmailMultiAlternatives(subject, text_body, 'no-reply@%s' % blog.name , [email])
msg.attach_alternative(html_body, "text/html")
messages.append(msg)
connection.send_messages(messages)
connection.close()
response = HttpResponseRedirect(ref)
response.set_cookie('author', request.POST['author'], domain=blog.name, secure=True, httponly=False);
if request.POST['email'] != '':
response.set_cookie('email', request.POST['email'], domain=blog.name, secure=True, httponly=False);
return response
@login_required
def edit_comment(request, comment_id):
comment = Comment.objects.get(pk=comment_id)
if comment is None:
return Http404
(b, post) = have_I_right(request, None, comment.post_id)
post_id = comment.post_id
if request.method == 'POST': # If the form has been submitted...
if 'edit' in request.POST:
form = CommentForm(request.POST, instance=comment) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
form = form.save()
# Process the data in form.cleaned_data
# ...
return HttpResponseRedirect('/post/edit/' + str(post_id))
else:
return HttpResponseRedirect('/post/edit/' + str(post_id))
else:
form = CommentForm(instance=comment) # An unbound form
return render(request, 'edit_comment.html', {
'form': form, 'comment':comment
})
@login_required
def delete_comment(request, comment_id):
comment = Comment.objects.get(pk=comment_id)
if comment is None:
return Http404
(b, post) = have_I_right(request, None, comment.post_id)
post_id = comment.post_id
childs = Comment.objects.filter(parent=comment.id)
try:
parent = comment.parent
except:
parent = None
for child in childs:
child.parent = parent
child.save()
comment.delete()
return HttpResponseRedirect('/post/edit/' + str(post_id))