Dynastie/models.py

248 lines
8.5 KiB
Python

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
from django.db.models.signals import post_init, post_delete, post_save
from django.dispatch import receiver
from dynastie.generators import *
class Blog(models.Model):
name = models.CharField(max_length=255, unique=True)
title = models.CharField(max_length=255)
description = models.TextField(max_length=255, blank=True)
keywords = models.TextField(blank=True)
writers = models.ManyToManyField(User)
engines = list()
src_path = ''
output_path = ''
report = ''
def create_paths(self):
self.src_path = 'sites/' + self.name
self.output_path = 'sites/' + self.name + '_output'
def create(self):
self.create_paths()
if not os.path.exists('sites'):
os.mkdir('sites')
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)
if os.path.exists(self.output_path):
shutil.rmtree(self.output_path)
def load_generators(self):
if os.path.exists(self.src_path + '/_generators'):
f = open(self.src_path + '/_generators', 'r')
for line in f:
if line.startswith("#"):
continue
self.engines.append(globals()[line.strip()])
f.close()
else:
self.engines.append(globals()['article'])
self.engines.append(globals()['index'])
self.engines.append(globals()['category'])
self.engines.append(globals()['archive'])
def copytree(self, src, dst):
names = os.listdir(src)
errors = []
for name in names:
if name.startswith('_') or name.endswith('~'):
continue
srcname = os.path.join(src, name)
dstname = os.path.join(dst, name)
try:
if os.path.islink(srcname) and not os.path.exists(dstname):
linkto = os.readlink(srcname)
os.symlink(linkto, dstname)
if os.path.isdir(srcname):
if not os.path.exists(dstname):
os.makedirs(dstname)
self.copytree(srcname, dstname)
else:
if os.path.exists(dstname):
src_md5 = hashlib.md5()
f = open(srcname,'rb')
src_md5.update(f.read())
f.close()
dst_md5 = hashlib.md5()
f = open(dstname,'rb')
dst_md5.update(f.read())
f.close()
if src_md5.digest() != dst_md5.digest():
self.report = self.report + 'Update ' + dstname + '<br/>\n'
shutil.copy2(srcname, dstname)
else:
self.report = self.report + 'Add ' + dstname + '<br/>\n'
shutil.copy2(srcname, dstname)
# XXX What about devices, sockets etc.?
except (IOError, os.error), why:
errors.append((srcname, dstname, str(why)))
# catch the Error from the recursive copytree so that we can
# continue with other files
except Exception, err:
errors.extend(err.args[0])
if errors:
raise Exception(errors)
def generate(self):
self.report = '<br/><br/>Generation of ' + datetime.now().strftime("%d/%m/%Y at %H:%M:%S") + '<br/>\n'
self.load_generators()
self.copytree(self.src_path, self.output_path)
generated = []
for engine in self.engines:
if not inspect.ismodule(engine):
continue
for name, obj in inspect.getmembers(engine):
if inspect.isclass(obj) and obj.__module__.startswith("dynastie"):
if obj.__module__ in generated: continue
e = obj()
r = e.generate(self, self.src_path, self.output_path)
generated.append(obj.__module__)
if not r is None:
self.report = self.report + '<br/>\n' + r
return self.report
class Editor(models.Model):
name = models.CharField(max_length=255, unique=True)
class Category(models.Model):
name = models.CharField(max_length=255, unique=True)
name_slug = models.CharField(max_length=255)
parent = models.ForeignKey('self', blank=True, null=True)
description = models.TextField(max_length=255, blank=True)
def slugify(self):
name = normalize('NFKD', self.name).encode('ascii', 'ignore').replace(' ', '-').lower()
#remove `other` characters
name = sub('[^a-zA-Z0-9_-]', '', name)
#nomalize dashes
name = sub('-+', '-', name)
self.name_slug = name
def save(self):
self.slugify()
super(Category, self).save()
def remove(self, blog):
blog.create_paths()
output = blog.output_path + '/category/' + self.name_slug
shutil.rmtree(output)
class Tag(models.Model):
name = models.CharField(max_length=255, unique=True)
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.DateTimeField()
front_page = models.BooleanField()
author = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
description = models.TextField(max_length=255, blank=True)
keywords = models.TextField(blank=True)
tags = models.ManyToManyField(Tag, blank=True, null=True)
blog = models.ForeignKey(Blog)
def getPath(self):
filename = '/article/'
filename = filename + self.creation_date.strftime("%Y") + '/' + self.creation_date.strftime("%m") + '/'
filename = filename + self.title_slug + '.html'
return filename
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 + self.getPath()
if os.path.exists(filename):
os.unlink(filename)
filename = filename + '.gz'
if os.path.exists(filename):
os.unlink(filename)
filename = output + '/article/'
filename = filename + self.creation_date.strftime("%Y") + '/' + self.creation_date.strftime("%m") + '/'
if len(os.listdir(filename)) == 0:
os.rmdir(filename)
filename = output + '/article/'
filename = filename + self.creation_date.strftime("%Y") + '/'
if len(os.listdir(filename)) == 0:
os.rmdir(filename)
class Comment(models.Model):
article = models.ForeignKey(Article)
parent = models.ForeignKey('Comment')
date = models.DateField(max_length=255)
author = models.CharField(max_length=255)
email = models.EmailField(max_length=255)
the_comment = models.TextField(max_length=255)
@receiver(post_init, sender=Blog)
def delete_blog_signal(sender, **kwargs):
sender.create_paths()
@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()