Youtube and stats modules style improvements
[snf-cloudcms] / cloudcms / forms.py
index 0d127fd..e5cc0dc 100644 (file)
@@ -5,6 +5,7 @@ import tempfile
 import os
 import glob
 import logging
+import StringIO
 
 from django import forms
 from django.conf import settings
@@ -22,6 +23,9 @@ from feincms.content.raw.models import RawContent
 
 logger = logging.getLogger('cloudcms.rstimport')
 
+def slugify(title):
+    return title[:90]
+
 # base filename to service slug map
 DEFAULT_SERVICE_MAP = {
         'cyclades':'cyclades',
@@ -45,7 +49,7 @@ RESIZE_GEOMETRY = getattr(settings, 'CMS_RST_IMPORT_RESIZE_GEOMETRY',
 
 def service_from_filename(rst):
     fname = os.path.basename(rst).replace(".rst","")
-    service_slug = DEFAULT_SERVICE_MAP.get(fname, None)
+    service_slug = SERVICE_MAP.get(fname, None)
     if not service_slug:
         return None
 
@@ -63,7 +67,7 @@ def get_media_category(slug):
     return MediaCategory.objects.get(slug=slug)
 
 
-CATEGORIES_CHOICES = (('faqs', 'FAQs'), ('guide', 'User guide'))
+CATEGORIES_CHOICES = (('faq', 'FAQs'), ('user-guide', 'User guide'))
 
 class RstZipImportForm(forms.Form):
 
@@ -102,12 +106,24 @@ class RstZipImportForm(forms.Form):
         return data
 
     def clean_existing_data(self):
+        logger.warning("Removing all FAQ questions")
         Question.objects.all().delete()
+        logger.warning("Removing all User Guide entries")
         UserGuideEntry.objects.all().delete()
+        logger.warning("Removing all media files in categories %s", [self.FAQ_MEDIA_CATEGORY,
+            self.GUIDE_MEDIA_CATEGORY])
         MediaFile.objects.filter(categories__slug__in=[self.FAQ_MEDIA_CATEGORY, \
             self.GUIDE_MEDIA_CATEGORY]).delete()
 
     def save(self, user, use_dir=None):
+        stream = StringIO.StringIO()
+        stream_handler = logging.StreamHandler(stream)
+        stream_handler.setFormatter(logging.Formatter('<div class="log-entry %(levelname)s"><em>%(levelname)s</em>'
+            '<pre>%(message)s</pre></div>'))
+        logger.addHandler(stream_handler)
+        old_level = logger.level
+        logger.setLevel(logging.DEBUG)
+
         dry_run = self.cleaned_data.get('dry_run')
         clean_data = self.cleaned_data.get('clean_data')
         import_file = self.cleaned_data.get('import_file')
@@ -125,32 +141,42 @@ class RstZipImportForm(forms.Form):
                 subdirs[0])) and subdirs[0] != 'source':
             zipdir = os.path.join(zipdir, subdirs[0])
 
-        #sid = transaction.savepoint()
+        sid = transaction.savepoint()
 
         if clean_data:
             try:
+                logger.warning("Removing exising entries")
                 self.clean_existing_data()
             except Exception, e:
-                return False
+                try:
+                    transaction.savepoint_rollback(sid)
+                    transaction.rollback()
+                except Exception, e:
+                    logger.exception("Can not rollback")
+                logger.exception("Failed to clean existing data")
+                logger.removeHandler(stream_handler)
+                logger.setLevel(old_level)
+                return False, stream.getvalue()
 
         ret = ""
         try:
+            logger.warning("Parsing contents of '%s'", zipdir)
             for data_type, rst, category, slug, title, html_content, \
                     images, stderr in generate_rst_contents_from_dir(zipdir):
 
-                ret += stderr
-                #logger.info("Parsed %s" % (rst, ))
                 if stderr:
-                    pass
-                    #logger.info("Error output: %s" % (stderr, ))
+                    logger.error("Docutils error output for '%s'\n: %s" % (rst, stderr, ))
 
                 service = service_from_filename(rst)
                 if not service:
                     logger.info("Skipping entry for file '%s'. No category found" % rst)
                     continue
 
+                logger.info("Processing, '%s'" % (rst, ))
+
 
                 # first save media files
+                cat = False
                 newimages = []
                 if data_type == 'userguide':
                     cat = get_media_category(self.GUIDE_MEDIA_CATEGORY)
@@ -158,9 +184,12 @@ class RstZipImportForm(forms.Form):
                     cat = get_media_category(self.FAQ_MEDIA_CATEGORY)
 
                 if not cat:
+                    logger.info("Skipping %s, no media category found for '%s'",
+                            rst, data_type)
                     continue
 
                 for imgname, imgpath, imgabspath in images:
+                    logger.debug("Checking image (%s, %s, %s)", imgname, imgpath, imgabspath)
                     newalt, newpath = create_or_update_media_file(cat, \
                             imgname, imgabspath)
 
@@ -169,70 +198,102 @@ class RstZipImportForm(forms.Form):
                 # now html contains correct image links, we are ready to save
                 # the faq/guide content
                 if data_type == 'faq':
-                    cat = add_or_update_faq_category(category[0], category[1])
+                    logger.info('Processing FAQ entry, %s, %s, %s', service, slug, title)
+                    cat = add_or_update_faq_category(unicode(category[0]),
+                            unicode(category[1]))
                     question = add_or_update_faq_question(user, service, cat, slug, \
                             title, html_content)
 
                 if data_type == 'userguide':
+                    logger.info('Processing USER GUIDE entry, %s, %s, %s', service, slug, title)
                     guide_entry = add_or_update_guide_entry(user, service, slug, \
                             title, html_content)
 
 
         except Exception, e:
+            print e, "EXCEPTION"
             logger.exception("RST import failed")
-            #transaction.savepoint_rollback(sid)
-            return False
+            logger.removeHandler(stream_handler)
+            logger.setLevel(old_level)
+            try:
+                transaction.savepoint_rollback(sid)
+                transaction.rollback()
+            except Exception, e:
+                logger.exception("Can not rollback")
+
+            return False, stream.getvalue()
 
         if dry_run:
-            pass
-            #transaction.savepoint_rollback(sid)
+            try:
+                transaction.savepoint_rollback(sid)
+                transaction.rollback()
+            except Exception, e:
+                logger.exception("Can not rollback")
+
         else:
-            pass
-            #transaction.savepoint_commit(sid)
+            transaction.savepoint_commit(sid)
+
+        return True, stream.getvalue()
 
 
 def create_or_update_media_file(category, name, path):
+    logger.info("Create or update media file, %s, %s, [category: %s]", name,
+            path, category)
     name = category.title + " " + name
 
     try:
         # TODO: Check language ?????
-        mf = MediaFile.objects.get(categories=category, translations__caption=name)
+        mf = MediaFile.objects.get(categories__in=[category], translations__caption=name)
+        logger.info("Media file found")
     except MediaFile.DoesNotExist:
+        logger.info("Media file not found, creating...")
         mf = MediaFile()
-        mf.category = category
         mf.file = File(open(path))
         mf.save()
         mf.translations.create(caption=name)
+        mf.categories.clear()
+        mf.categories = [category]
+        mf.save()
 
     # TODO: Check language ?????
     return mf.translations.all()[0].caption, mf.get_absolute_url()
 
 
 def add_or_update_faq_category(slug, name):
+    logger.info("Create or update faq subcategory, %s, %s", slug,
+            name)
     try:
         category = FaqCategory.objects.get(translations__slug=slug)
+        logger.info("FAQ category found")
     except FaqCategory.DoesNotExist:
+        logger.info("FAQ category not found, creating...")
         category = FaqCategory()
         category.save()
         category.translations.create(slug=slug, title=name)
 
     return category
 
+
 def add_or_update_faq_question(author, service, category, slug,\
         title, html_content):
+    logger.info("Create or update faq question, %s, %s, %s, %s", service,
+            category, slug, title)
 
     try:
         q = Question.objects.get(slug=slug)
+        logger.info("Question found, updating...")
     except:
+        logger.info("Question not found, creating...")
         q = Question()
 
     q.author = author
     q.is_active = True
     q.category = category
     q.service = service
-    q.slug = slug
-    q.title = title
+    q.slug = slugify(slug)
+    q.title = unicode(title)
     q.save()
+
     q.application = [Application.current()]
     q.save()
 
@@ -248,16 +309,20 @@ def add_or_update_faq_question(author, service, category, slug,\
     return q
 
 def add_or_update_guide_entry(author, service, slug, title, html_content):
+    logger.info("Create or update user guide entry, %s, %s, %s", service,
+            slug, title)
     try:
+        logger.info("Guide entry found, updating...")
         guide = UserGuideEntry.objects.get(slug=slug)
     except:
+        logger.info("Guide entry not found, creating...")
         guide = UserGuideEntry()
 
     guide.author = author
     guide.is_active = True
     guide.service = service
-    guide.slug = slug
-    guide.title = title
+    guide.slug = slugify(slug)
+    guide.title = unicode(title)
     guide.save()
 
     RawContentModel = UserGuideEntry.content_type_for(RawContent)
@@ -271,3 +336,4 @@ def add_or_update_guide_entry(author, service, slug, title, html_content):
 
     return guide
 
+