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: self.engines.append(globals()[line.strip()]) f.close() else: self.engines.append(globals()['index']) self.engines.append(globals()['categories']) self.engines.append(globals()['archives']) 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 + '
\n' shutil.copy2(srcname, dstname) else: self.report = self.report + 'Add ' + dstname + '
\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 = '

Generation of ' + datetime.now().strftime("%d/%m/%Y at %H:%M:%S") + '
\n' self.load_generators() self.copytree(self.src_path, self.output_path) for engine in self.engines: for name, obj in inspect.getmembers(engine): if inspect.isclass(obj): e = obj() 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): name = models.CharField(max_length=255, unique=True) class Category(models.Model): name = models.CharField(max_length=255, unique=True) parent = models.ForeignKey('self', blank=True, null=True) description = models.TextField(max_length=255, blank=True) 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.DateField() 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 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') 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()