Commits

Frank Becker committed 4f23d9e

added assignment 4

Comments (0)

Files changed (44)

aufgaben/4/workshop/__init__.py

Empty file added.

aufgaben/4/workshop/data.sqlite

Binary file added.

aufgaben/4/workshop/data.sqlite-init

Binary file added.

aufgaben/4/workshop/gallery/__init__.py

Empty file added.

aufgaben/4/workshop/gallery/admin.py

+# -*- coding: utf-8 -*-
+
+"""
+Title
+"""
+__author__ = "Frank Becker <fb@alien8.de>"
+__version__ = "0.1"
+__date__ = "Date: 5/18/11"
+__copyright__ = "Copyright (c) 2011 Frank Becker"
+__license__ = "Python"
+
+
+from django.contrib import admin
+from cms.admin.placeholderadmin import PlaceholderAdmin
+from gallery.models import Gallery, GalleryPicture
+
+class PictureInline(admin.StackedInline):
+    model = GalleryPicture
+
+class GalleryAdmin(admin.ModelAdmin):
+    inlines = [PictureInline]
+
+admin.site.register(Gallery, GalleryAdmin)
+#admin.site.register(GalleryPicture, GalleryAdmin)
+#admin.site.register(GalleryThumbnail, GalleryAdmin)
+
+# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 fileencoding=utf-8 :

aufgaben/4/workshop/gallery/cms_plugins.py

+# -*- coding: utf-8 -*-
+
+"""
+Integrate into django-cms
+"""
+__author__ = "Frank Becker <fb@alien8.de>"
+__version__ = "0.1"
+__date__ = "Date: 5/18/11"
+__copyright__ = "Copyright (c) 2011 Frank Becker"
+__license__ = "Python"
+
+from cms.plugin_base import CMSPluginBase
+from cms.plugin_pool import plugin_pool
+from gallery.models import GalleryPlugin, GalleryPicture
+from django.utils.translation import ugettext as _
+
+class CMSGalleryPlugin(CMSPluginBase):
+    model = GalleryPlugin
+    name = _("Gallery")
+    render_template = "gallery/gallery.html"
+
+    def render(self, context, instance, placeholder):
+        pix = GalleryPicture.objects.filter(gallery=instance.gallery, on_line=True)
+        pix_with_gaps = []
+        if pix:
+            pix_with_gaps.extend([pix[0] if n + 1 == pix[0].sort_number else False for n in xrange(pix[0].sort_number)])
+            pix_with_gaps.extend([pix[n] if dist == 1 else False for n in xrange(1, len(pix)) \
+                         for dist in xrange(pix[n].sort_number - pix[n-1].sort_number, 0, -1)])
+        context.update({
+            'gallery': instance.gallery,
+            'object': instance,
+            'pictures': pix_with_gaps,
+            'placeholder': placeholder,
+        })
+        return context
+
+plugin_pool.register_plugin(CMSGalleryPlugin)

aufgaben/4/workshop/gallery/migrations/0001_initial.py

+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        
+        # Adding model 'Gallery'
+        db.create_table('gallery_gallery', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('title', self.gf('django.db.models.fields.CharField')(max_length=250)),
+            ('description', self.gf('django.db.models.fields.TextField')(blank=True)),
+            ('on_line', self.gf('django.db.models.fields.BooleanField')(default=True)),
+            ('sort_date', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime(2011, 8, 24, 22, 56, 31, 775644), blank=True)),
+        ))
+        db.send_create_signal('gallery', ['Gallery'])
+
+        # Adding model 'GalleryPicture'
+        db.create_table('gallery_gallerypicture', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('name', self.gf('django.db.models.fields.CharField')(max_length=80)),
+            ('caption', self.gf('django.db.models.fields.CharField')(max_length=80)),
+            ('sort_number', self.gf('django.db.models.fields.IntegerField')(unique=True)),
+            ('gallery', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['gallery.Gallery'], blank=True)),
+            ('on_line', self.gf('django.db.models.fields.BooleanField')(default=True)),
+            ('picture', self.gf('django.db.models.fields.files.ImageField')(max_length=100)),
+            ('upload_date', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+        ))
+        db.send_create_signal('gallery', ['GalleryPicture'])
+
+        # Adding model 'GalleryPlugin'
+        db.create_table('cmsplugin_galleryplugin', (
+            ('cmsplugin_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['cms.CMSPlugin'], unique=True, primary_key=True)),
+            ('gallery', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['gallery.Gallery'])),
+        ))
+        db.send_create_signal('gallery', ['GalleryPlugin'])
+
+
+    def backwards(self, orm):
+        
+        # Deleting model 'Gallery'
+        db.delete_table('gallery_gallery')
+
+        # Deleting model 'GalleryPicture'
+        db.delete_table('gallery_gallerypicture')
+
+        # Deleting model 'GalleryPlugin'
+        db.delete_table('cmsplugin_galleryplugin')
+
+
+    models = {
+        'cms.cmsplugin': {
+            'Meta': {'object_name': 'CMSPlugin'},
+            'creation_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'language': ('django.db.models.fields.CharField', [], {'max_length': '15', 'db_index': 'True'}),
+            'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['cms.CMSPlugin']", 'null': 'True', 'blank': 'True'}),
+            'placeholder': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['cms.Placeholder']", 'null': 'True'}),
+            'plugin_type': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'}),
+            'position': ('django.db.models.fields.PositiveSmallIntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
+        },
+        'cms.placeholder': {
+            'Meta': {'object_name': 'Placeholder'},
+            'default_width': ('django.db.models.fields.PositiveSmallIntegerField', [], {'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'slot': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'})
+        },
+        'gallery.gallery': {
+            'Meta': {'ordering': "['-sort_date']", 'object_name': 'Gallery'},
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'on_line': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'sort_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2011, 8, 24, 22, 56, 31, 783309)', 'blank': 'True'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '250'})
+        },
+        'gallery.gallerypicture': {
+            'Meta': {'object_name': 'GalleryPicture'},
+            'caption': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
+            'gallery': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gallery.Gallery']", 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
+            'on_line': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'picture': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}),
+            'sort_number': ('django.db.models.fields.IntegerField', [], {'unique': 'True'}),
+            'upload_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
+        },
+        'gallery.galleryplugin': {
+            'Meta': {'object_name': 'GalleryPlugin', 'db_table': "'cmsplugin_galleryplugin'", '_ormbases': ['cms.CMSPlugin']},
+            'cmsplugin_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['cms.CMSPlugin']", 'unique': 'True', 'primary_key': 'True'}),
+            'gallery': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gallery.Gallery']"})
+        }
+    }
+
+    complete_apps = ['gallery']

aufgaben/4/workshop/gallery/migrations/0002_auto__add_gallerythumbnail__add_field_gallerypicture_thumbnail.py

+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        
+        # Adding model 'GalleryThumbnail'
+        db.create_table('gallery_gallerythumbnail', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('name', self.gf('django.db.models.fields.CharField')(max_length=80)),
+            ('on_line', self.gf('django.db.models.fields.BooleanField')(default=True)),
+            ('picture', self.gf('django.db.models.fields.files.ImageField')(max_length=100)),
+            ('upload_date', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+        ))
+        db.send_create_signal('gallery', ['GalleryThumbnail'])
+
+        # Adding field 'GalleryPicture.thumbnail'
+        db.add_column('gallery_gallerypicture', 'thumbnail', self.gf('django.db.models.fields.files.ImageField')(max_length=100, null=True, blank=True), keep_default=False)
+
+
+    def backwards(self, orm):
+        
+        # Deleting model 'GalleryThumbnail'
+        db.delete_table('gallery_gallerythumbnail')
+
+        # Deleting field 'GalleryPicture.thumbnail'
+        db.delete_column('gallery_gallerypicture', 'thumbnail')
+
+
+    models = {
+        'cms.cmsplugin': {
+            'Meta': {'object_name': 'CMSPlugin'},
+            'creation_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'language': ('django.db.models.fields.CharField', [], {'max_length': '15', 'db_index': 'True'}),
+            'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['cms.CMSPlugin']", 'null': 'True', 'blank': 'True'}),
+            'placeholder': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['cms.Placeholder']", 'null': 'True'}),
+            'plugin_type': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'}),
+            'position': ('django.db.models.fields.PositiveSmallIntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
+        },
+        'cms.placeholder': {
+            'Meta': {'object_name': 'Placeholder'},
+            'default_width': ('django.db.models.fields.PositiveSmallIntegerField', [], {'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'slot': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'})
+        },
+        'gallery.gallery': {
+            'Meta': {'ordering': "['-sort_date']", 'object_name': 'Gallery'},
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'on_line': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'sort_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2011, 8, 26, 0, 18, 53, 893106)', 'blank': 'True'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '250'})
+        },
+        'gallery.gallerypicture': {
+            'Meta': {'object_name': 'GalleryPicture'},
+            'caption': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
+            'gallery': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'gallery'", 'blank': 'True', 'to': "orm['gallery.Gallery']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
+            'on_line': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'picture': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}),
+            'sort_number': ('django.db.models.fields.IntegerField', [], {'unique': 'True'}),
+            'thumbnail': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+            'upload_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
+        },
+        'gallery.galleryplugin': {
+            'Meta': {'object_name': 'GalleryPlugin', 'db_table': "'cmsplugin_galleryplugin'", '_ormbases': ['cms.CMSPlugin']},
+            'cmsplugin_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['cms.CMSPlugin']", 'unique': 'True', 'primary_key': 'True'}),
+            'gallery': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gallery.Gallery']"})
+        },
+        'gallery.gallerythumbnail': {
+            'Meta': {'object_name': 'GalleryThumbnail'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
+            'on_line': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'picture': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}),
+            'upload_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
+        }
+    }
+
+    complete_apps = ['gallery']

aufgaben/4/workshop/gallery/migrations/0003_auto__del_gallerythumbnail.py

+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        
+        # Deleting model 'GalleryThumbnail'
+        db.delete_table('gallery_gallerythumbnail')
+
+
+    def backwards(self, orm):
+        
+        # Adding model 'GalleryThumbnail'
+        db.create_table('gallery_gallerythumbnail', (
+            ('picture', self.gf('django.db.models.fields.files.ImageField')(max_length=100)),
+            ('name', self.gf('django.db.models.fields.CharField')(max_length=80)),
+            ('upload_date', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+            ('on_line', self.gf('django.db.models.fields.BooleanField')(default=True)),
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+        ))
+        db.send_create_signal('gallery', ['GalleryThumbnail'])
+
+
+    models = {
+        'cms.cmsplugin': {
+            'Meta': {'object_name': 'CMSPlugin'},
+            'creation_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'language': ('django.db.models.fields.CharField', [], {'max_length': '15', 'db_index': 'True'}),
+            'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['cms.CMSPlugin']", 'null': 'True', 'blank': 'True'}),
+            'placeholder': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['cms.Placeholder']", 'null': 'True'}),
+            'plugin_type': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'}),
+            'position': ('django.db.models.fields.PositiveSmallIntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
+        },
+        'cms.placeholder': {
+            'Meta': {'object_name': 'Placeholder'},
+            'default_width': ('django.db.models.fields.PositiveSmallIntegerField', [], {'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'slot': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'})
+        },
+        'gallery.gallery': {
+            'Meta': {'ordering': "['-sort_date']", 'object_name': 'Gallery'},
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'on_line': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'sort_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2011, 8, 28, 0, 55, 30, 619252)', 'blank': 'True'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '250'})
+        },
+        'gallery.gallerypicture': {
+            'Meta': {'ordering': "['sort_number']", 'object_name': 'GalleryPicture'},
+            'caption': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
+            'gallery': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'gallery'", 'blank': 'True', 'to': "orm['gallery.Gallery']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
+            'on_line': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'picture': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}),
+            'sort_number': ('django.db.models.fields.IntegerField', [], {'unique': 'True'}),
+            'thumbnail': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+            'upload_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
+        },
+        'gallery.galleryplugin': {
+            'Meta': {'object_name': 'GalleryPlugin', 'db_table': "'cmsplugin_galleryplugin'", '_ormbases': ['cms.CMSPlugin']},
+            'cmsplugin_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['cms.CMSPlugin']", 'unique': 'True', 'primary_key': 'True'}),
+            'gallery': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gallery.Gallery']"})
+        }
+    }
+
+    complete_apps = ['gallery']

aufgaben/4/workshop/gallery/migrations/0004_auto__del_unique_gallerypicture_sort_number__add_unique_gallerypicture.py

+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        
+        # Removing unique constraint on 'GalleryPicture', fields ['sort_number']
+        db.delete_unique('gallery_gallerypicture', ['sort_number'])
+
+        # Adding unique constraint on 'GalleryPicture', fields ['gallery', 'sort_number']
+        db.create_unique('gallery_gallerypicture', ['gallery_id', 'sort_number'])
+
+
+    def backwards(self, orm):
+        
+        # Removing unique constraint on 'GalleryPicture', fields ['gallery', 'sort_number']
+        db.delete_unique('gallery_gallerypicture', ['gallery_id', 'sort_number'])
+
+        # Adding unique constraint on 'GalleryPicture', fields ['sort_number']
+        db.create_unique('gallery_gallerypicture', ['sort_number'])
+
+
+    models = {
+        'cms.cmsplugin': {
+            'Meta': {'object_name': 'CMSPlugin'},
+            'creation_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'language': ('django.db.models.fields.CharField', [], {'max_length': '15', 'db_index': 'True'}),
+            'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['cms.CMSPlugin']", 'null': 'True', 'blank': 'True'}),
+            'placeholder': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['cms.Placeholder']", 'null': 'True'}),
+            'plugin_type': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'}),
+            'position': ('django.db.models.fields.PositiveSmallIntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
+        },
+        'cms.placeholder': {
+            'Meta': {'object_name': 'Placeholder'},
+            'default_width': ('django.db.models.fields.PositiveSmallIntegerField', [], {'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'slot': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'})
+        },
+        'gallery.gallery': {
+            'Meta': {'ordering': "['-sort_date']", 'object_name': 'Gallery'},
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'on_line': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'sort_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2011, 8, 31, 18, 11, 42, 405993)', 'blank': 'True'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '250'})
+        },
+        'gallery.gallerypicture': {
+            'Meta': {'ordering': "['sort_number']", 'unique_together': "(('sort_number', 'gallery'),)", 'object_name': 'GalleryPicture'},
+            'caption': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
+            'gallery': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'gallery'", 'blank': 'True', 'to': "orm['gallery.Gallery']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
+            'on_line': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'picture': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}),
+            'sort_number': ('django.db.models.fields.IntegerField', [], {}),
+            'thumbnail': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+            'upload_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
+        },
+        'gallery.galleryplugin': {
+            'Meta': {'object_name': 'GalleryPlugin', 'db_table': "'cmsplugin_galleryplugin'", '_ormbases': ['cms.CMSPlugin']},
+            'cmsplugin_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['cms.CMSPlugin']", 'unique': 'True', 'primary_key': 'True'}),
+            'gallery': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gallery.Gallery']"})
+        }
+    }
+
+    complete_apps = ['gallery']

aufgaben/4/workshop/gallery/migrations/__init__.py

Empty file added.

aufgaben/4/workshop/gallery/models.py

+# -*- coding: utf-8 -*-
+from datetime import datetime
+from django.db import models
+from cms.models import CMSPlugin
+from django.utils.translation import ugettext_lazy as _
+
+
+class Gallery(models.Model):
+    """Gallery class to gather multiple GalleryPicture()
+    """
+
+    title = models.CharField(
+        verbose_name=_(u"Titel"),
+        blank=False,
+        max_length = 250,
+        )
+
+    description = models.TextField(
+        verbose_name=_(u"Beschreibung"),
+        blank=True,
+        )
+
+    on_line = models.BooleanField(
+        verbose_name=_(u"Online"),
+        blank=False,
+        default=True,
+        )
+
+    sort_date = models.DateTimeField(
+        verbose_name=_("Sortierdatum"),
+        blank=True,
+        default=lambda: datetime.now(),
+        #auto_now_add=True,   # set on NewsEntry() first save()
+        #default=datetime.datetime.now()
+    )
+
+    class Meta:
+        ordering = ['-sort_date']
+        verbose_name_plural = "Gallery"
+
+    def __unicode__(self):
+        return u'%s' % (self.title,)
+
+    @models.permalink
+    def get_absolute_url(self):
+        return ('gallery_detail', (), {
+            'object_id': self.pk
+        })
+
+
+class GalleryPicture(models.Model):
+    """Pictures for gallery
+    """
+    SORT_NUMBER = ((i, "Bildnummer" + " %s" % (i,)) for i in range(1, 200))
+
+    name = models.CharField(
+        verbose_name=_(u"Name"),
+        blank=False,
+        max_length = 80,
+        )
+
+    caption = models.CharField(
+        verbose_name=_(u"Beschreibung"),
+        blank=False,
+        max_length = 80,
+        )
+
+    sort_number = models.IntegerField(
+        verbose_name=_(u"Sortiernummer"),
+        blank=False,
+        choices=SORT_NUMBER,
+        )
+
+    thumbnail = models.ImageField(
+        verbose_name=_(u"Vorschaubilddatei"),
+        upload_to='pix/%Y/%m',
+        blank=True,
+        null=True,
+        )
+
+    gallery = models.ForeignKey(
+        Gallery,
+        related_name='gallery',
+        blank=True,
+        #limit_choices_to = {'upload_date__lte': datetime.now},
+        )
+
+    on_line = models.BooleanField(
+        verbose_name=_(u"Online"),
+        blank=False,
+        default=True,
+        )
+
+    picture = models.ImageField(
+        verbose_name=_(u"Bilddatei"),
+        blank=False,
+        upload_to='pix/%Y/%m',
+        )
+
+    upload_date = models.DateTimeField(
+        verbose_name=_("Upload Datum"),
+        blank=True,
+        #default=lambda: datetime.now(),
+        auto_now_add=True,
+        )
+
+    class Meta:
+        ordering = ['sort_number']
+        unique_together = ("sort_number", "gallery")
+
+    def __unicode__(self):
+        return u'%s' % (self.name,)
+
+    @models.permalink
+    def get_absolute_url(self):
+        return ('picture', (), {
+            'object_id': self.pk
+        })
+
+class GalleryPlugin(CMSPlugin):
+    gallery = models.ForeignKey(Gallery)

aufgaben/4/workshop/gallery/templates/gallery/gallery.html

+{% load thumbnail %}
+{% load pagination_tags %}
+<div id="gallery">
+    <table>
+        {# for image in gallery.gallerypicture_set.all #}
+    {% autopaginate pictures 9 %}
+        {% for image in pictures %}
+        {% if forloop.counter0|divisibleby:3 %}<tr>{% endif %}
+            <td>
+                {% if image %}
+                <a href="{{ image.picture.url }}">
+                    <img class="pix" src="{% if image.thumbnail %}{{ image.thumbnail.url }}{% else %}{% thumbnail image.picture 130x150 crop %}{% endif %}" alt="{{ image.name }} - {{ image.caption }}" title="{{ image.name }}{{ image.caption }}">
+                </a>
+                {% else %}
+                    <div class="pix"></div>
+                {% endif %}
+            </td>
+        {% if forloop.counter|divisibleby:3 or forloop.last %}</tr>{% endif %}
+        {% endfor %}
+    </table>
+    {% comment %}
+    {% autopaginate pictures 9 %}
+    {% for image in pictures %}
+        {% if forloop.counter0|divisibleby:3 %}<ul>{% endif %}
+        <li>
+            {% if image %}
+                <a href="{{ image.picture.url }}">
+                    <img class="pix" src="{% if image.thumbnail %}{{ image.thumbnail.url }}{% else %}{% thumbnail image.picture 130x150 crop %}{% endif %}" alt="{{ image.name }} - {{ image.caption }}" title="{{ image.name }}{{ image.caption }}">
+                </a>
+            {% else %}
+                <div class="pix"></div>
+            {% endif %}
+        </li>
+        {% if forloop.counter|divisibleby:3 or forloop.last %}</ul>{% endif %}
+    {% endfor %}
+    {% endcomment %}
+</div>
+{% paginate %}

aufgaben/4/workshop/local_settings.py

+import os
+
+DEBUG = True
+SANDBOX = True
+TEMPLATE_DEBUG = DEBUG
+
+BASEDIR = os.path.dirname(__file__)
+
+ADMINS = (
+    # ('Your Name', 'your_email@domain.com'),
+)
+
+MANAGERS = ADMINS
+
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.sqlite3',
+        'NAME': os.path.join(BASEDIR, 'data.sqlite'),
+    }
+}
+
+STATICFILES_DIRS = (
+    ('css/workshop', BASEDIR + '/templates/css/workshop'),
+    ('js/workshop', BASEDIR + '/templates/js/workshop'),
+    ('img/workshop', BASEDIR + '/templates/img/workshop'),
+)
+
+#EMAIL_HOST = 'smtp.gmail.com'
+#EMAIL_HOST_USER = 'username@googlemail.com'
+#EMAIL_HOST_PASSWORD = 'xxxxxxxx'
+#EMAIL_USE_TLS = True
+#EMAIL_PORT = 587
+
+# Absolute path to the directory that holds the project sources
+# Make sure to use a training slash
+STATIC_FILES_ROOT = '../../'
+APP_NAME = 'django'
+STATIC_APP_NAME = 'static'
+MEDIA_APP_NAME = 'media'
+
+SECRET_KEY = 'GNzqBomJ=uDe%4))Dx^o!vk+fIF@V5<2O4n94_SQl>HcPFZFTo'
+
+#CMS_MODERATOR = True
+#CMS_SHOW_START_DATE = True
+#CMS_SHOW_END_DATE = True

aufgaben/4/workshop/manage.py

+#!/usr/bin/env python
+from django.core.management import execute_manager
+try:
+    import settings # Assumed to be in the same directory.
+except ImportError:
+    import sys
+    sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
+    sys.exit(1)
+
+if __name__ == "__main__":
+    execute_manager(settings)

aufgaben/4/workshop/settings.py

+import os
+from local_settings import *
+
+gettext = lambda s: s
+
+# Absolute path to the directory that holds media.
+# Example: "/home/media/media.lawrence.com/"
+STATIC_ROOT = STATIC_FILES_ROOT + STATIC_APP_NAME + '/'
+MEDIA_ROOT = STATIC_FILES_ROOT + MEDIA_APP_NAME + '/'
+
+# URL that handles the media served from MEDIA_ROOT. Make sure to use a
+# trailing slash if there is a path component (optional in other cases).
+# Examples: "http://media.lawrence.com", "http://example.com/media/"
+STATIC_URL = '/static/'
+MEDIA_URL = '/media/'
+
+# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
+# trailing slash.
+# Examples: "http://foo.com/media/", "/media/".
+ADMIN_MEDIA_PREFIX = '/static/admin/'
+
+ROOT_URLCONF = ".".join([BASEDIR.split(os.sep)[-1], "urls"])
+
+TEMPLATE_DIRS = (
+    # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
+    # Always use forward slashes, even on Windows.
+    # Don't forget to use absolute paths, not relative paths.
+    #PROJECT_ROOT + APP_NAME + '/templates'
+    BASEDIR + '/templates',
+)
+
+# Django settings for project.
+SEND_BROKEN_LINK_EMAILS = True
+IGNORABLE_404_STARTS = ('/static/cms/wymeditor/lang/',)
+
+# Local time zone for this installation. Choices can be found here:
+# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
+# although not all choices may be available on all operating systems.
+# If running in a Windows environment this must be set to the same as your
+# system time zone.
+TIME_ZONE = 'Europe/Berlin'
+
+# Language code for this installation. All choices can be found here:
+# http://www.i18nguy.com/unicode/language-identifiers.html
+LANGUAGE_CODE = 'de-DE'
+
+LANGUAGES = (
+    ('de', gettext('German')),
+)
+
+SITE_ID = 1
+
+# If you set this to False, Django will make some optimizations so as not
+# to load the internationalization machinery.
+USE_I18N = True
+
+# List of callables that know how to import templates from various sources.
+TEMPLATE_LOADERS = (
+    'django.template.loaders.filesystem.load_template_source',
+    'django.template.loaders.app_directories.load_template_source',
+    'django.template.loaders.eggs.load_template_source',
+)
+
+TEMPLATE_CONTEXT_PROCESSORS = (
+    'django.core.context_processors.auth',
+    #'django.core.context_processors.debug',
+    'django.core.context_processors.request',
+    'django.core.context_processors.media',
+    'django.core.context_processors.static',
+    'cms.context_processors.media',
+    'django.core.context_processors.i18n',
+    'sekizai.context_processors.sekizai',
+)
+
+MIDDLEWARE_CLASSES = (
+    #'django.middleware.cache.UpdateCacheMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    #'cms.middleware.multilingual.MultilingualURLMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.middleware.common.CommonMiddleware',
+    'cms.middleware.page.CurrentPageMiddleware',
+    'cms.middleware.user.CurrentUserMiddleware',
+    #'cms.middleware.media.PlaceholderMediaMiddleware',
+    #'django.middleware.cache.FetchFromCacheMiddleware',
+    'django.middleware.csrf.CsrfViewMiddleware',
+    'django.contrib.messages.middleware.MessageMiddleware',
+    'cms.middleware.toolbar.ToolbarMiddleware',
+    'pagination.middleware.PaginationMiddleware',
+)
+
+THUMBNAIL_PROCESSORS = (
+    'easy_thumbnails.processors.colorspace',
+    'easy_thumbnails.processors.autocrop',
+    #'easy_thumbnails.processors.scale_and_crop',
+    'filer.thumbnail_processors.scale_and_crop_with_subject_location',
+    'easy_thumbnails.processors.filters',
+)
+
+STATICFILES_FINDERS = (
+    'django.contrib.staticfiles.finders.FileSystemFinder',
+    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
+    'compressor.finders.CompressorFinder',
+)
+
+CMS_TEMPLATES = (
+    ('start.html', gettext('start')),
+    ('standard.html', gettext('Standard')),
+    ('bright.html', gettext('heller Hintergrund')),
+)
+
+CMS_FRONTEND_LANGUAGES = ("de",)
+
+CMS_SEO_FIELDS = True
+
+CMS_PLACEHOLDER_CONF = {
+    'links': {
+        'plugins': ('FilePlugin', 'LinkPlugin', 'PicturePlugin', 'TextPlugin',
+                    'SnippetPlugin'),
+        'name': gettext("linke Spalte")
+    },
+
+    'mitte': {
+        'plugins': ('PicturePlugin', 'TextPlugin', 'SnippetPlugin',
+                    'CMSGalleryPlugin'),
+        'name': gettext("mittlere Spalte")
+    },
+
+    'rechts': {
+        'plugins': ('PicturePlugin', 'TextPlugin', 'SnippetPlugin',
+                    'CMSGalleryPlugin'),
+        'name': gettext("rechte Spalte")
+    },
+}
+
+COMPRESS_PRECOMPILERS = (
+    ('text/x-scss', 'pyscss -o {outfile} {infile}'),
+)
+
+COMPRESS_CSS_FILTERS = ['compressor.filters.csstidy.CSSTidyFilter',]
+
+INSTALLED_APPS = (
+    # Django related apps
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.sites',
+    'django.contrib.admin',
+    'django.contrib.staticfiles',
+    # django-cms related apps
+    'cms',
+    'cms.plugins.text',
+    'cms.plugins.picture',
+    'cms.plugins.link',
+    'cms.plugins.file',
+    'cms.plugins.snippet',
+    'cms.plugins.googlemap',
+    'cms.plugins.inherit',
+    'mptt',
+    'sekizai',
+    'publisher',
+    'menus',
+    # useful 3rd party apps
+    'compressor',
+    'easy_thumbnails',
+    'filer',
+    'south',
+    'pagination',
+    'tinymce',
+    # your own apps
+    'gallery',
+)
+TINYMCE_JS_URL = STATIC_URL + 'js/tiny_mce/tiny_mce.js'
+TINYMCE_DEFAULT_CONFIG = {
+    # General options
+   "mode": "exact",
+   "elements": "elm1",
+   "theme": "advanced",
+   "plugins": "safari,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template,inlinepopups",
+
+    # Theme options
+   "theme_advanced_buttons1": "save,newdocument,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,styleselect,formatselect,fontselect,fontsizeselect",
+   "theme_advanced_buttons2": "cut,copy,paste,pastetext,pasteword,|,search,replace,|,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,|,sub,sup,|,charmap,emotions,iespell,media,advhr,|,print,|,ltr,rtl,|,fullscreen",
+   "theme_advanced_buttons4": "insertlayer,moveforward,movebackward,absolute,|,styleprops,|,cite,abbr,acronym,del,ins,attribs,|,visualchars,nonbreaking,template,pagebreak",
+   "theme_advanced_toolbar_location": "top",
+   "theme_advanced_toolbar_align": "left",
+   "theme_advanced_statusbar_location": "bottom",
+   "theme_advanced_resizing":"True",
+    'theme': "advanced",
+    'language': "de",
+    'width': "100%",
+    'height': "100%",
+    'body_class': "mceForceColors",
+    # Skin options
+    'skin' : "default",
+    'content_css' : "/static/css/layout.css",
+}
+TINYMCE_DEFAULT_CONFIG = {
+    "mode" : "textareas",
+    "elements": "elm1",
+    "theme" : "advanced",
+    "language": "de",
+    "width": "100%",
+    "height": "600",
+    "content_css": "/static/css/layout.css",
+    "theme_advanced_toolbar_location" : "top",
+    "theme_advanced_toolbar_align" : "left",
+    "theme_advanced_buttons1" : "fullscreen,separator,preview,separator,bold,italic,underline,strikethrough,separator,bullist,numlist,outdent,indent,separator,undo,redo,separator,link,unlink,anchor,separator,image,cleanup,help,separator,code",
+    "theme_advanced_buttons2" : "",
+    "theme_advanced_buttons3" : "",
+    "auto_cleanup_word" : 'true',
+    "plugins" : "table,save,advhr,advimage,advlink,emotions,iespell,insertdatetime,preview,zoom,flash,searchreplace,print,contextmenu,fullscreen",
+    "plugin_insertdate_dateFormat" : "%d.%m/%Y",
+    "plugin_insertdate_timeFormat" : "%H:%M:%S",
+    "extended_valid_elements" : "a[name|href|target=_blank|title|onclick],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]",
+    "fullscreen_settings" : {
+        "theme_advanced_path_location" : "top",
+        "theme_advanced_buttons1" : "fullscreen,separator,preview,separator,cut,copy,paste,separator,undo,redo,separator,search,replace,separator,code,separator,cleanup,separator,bold,italic,underline,strikethrough,separator,forecolor,backcolor,separator,justifyleft,justifycenter,justifyright,justifyfull,separator,help",
+        "theme_advanced_buttons2" : "removeformat,styleselect,formatselect,fontselect,fontsizeselect,separator,bullist,numlist,outdent,indent,separator,link,unlink,anchor",
+        "theme_advanced_buttons3" : "sub,sup,separator,image,insertdate,inserttime,separator,tablecontrols,separator,hr,advhr,visualaid,separator,charmap,emotions,iespell,flash,separator,print"
+    }
+}
+
+if DEBUG:
+    import traceback
+    import logging
+
+    # Define a class that logs unhandled errors
+    class LogUncatchedErrors:
+        def process_exception(self, request, exception):
+            logging.error("Unhandled Exception on request for %s\n%s" %
+                                 (request.build_absolute_uri(),
+                                  traceback.format_exc()))
+    # And add it to the middleware classes
+    MIDDLEWARE_CLASSES += ('settings.LogUncatchedErrors',)
+
+    # set shown level of logging output to debug
+    logging.basicConfig(level=logging.DEBUG)

aufgaben/4/workshop/templates/404.html

+<!doctype html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Page Not Found :(</title> 
+  <style>
+	  body { text-align: center;}
+	  h1 { font-size: 50px; text-align: center }
+	  span[frown] { transform: rotate(90deg); display:inline-block; color: #bbb; }
+	  body { font: 20px Constantia, 'Hoefler Text',  "Adobe Caslon Pro", Baskerville, Georgia, Times, serif; color: #999; text-shadow: 2px 2px 2px rgba(200, 200, 200, 0.5); }
+	  ::-moz-selection{ background:#FF5E99; color:#fff; }
+	  ::selection { background:#FF5E99; color:#fff; } 
+	  article {display:block; text-align: left; width: 500px; margin: 0 auto; }
+	  
+	  a { color: rgb(36, 109, 56); text-decoration:none; }
+	  a:hover { color: rgb(96, 73, 141) ; text-shadow: 2px 2px 2px rgba(36, 109, 56, 0.5); }
+  </style>
+</head>
+<body>
+     <article>
+	  <h1>Not found <span frown>:(</span></h1>
+	   <div>
+	       <p>Sorry, but the page you were trying to view does not exist.</p>
+	       <p>It looks like this was the result of either:</p>
+	       <ul>
+		   <li>a mistyped address</li>
+		   <li>an out-of-date link</li>
+	       </ul>
+	   </div>
+	    
+	    <script>
+	    var GOOG_FIXURL_LANG = (navigator.language || '').slice(0,2),
+		GOOG_FIXURL_SITE = location.host;
+	    </script>
+	    <script src="http://linkhelp.clients.google.com/tbproxy/lh/wm/fixurl.js"></script>
+     </article>
+</body>
+</html>

aufgaben/4/workshop/templates/500.html

Empty file added.

aufgaben/4/workshop/templates/base.html

+{% load cms_tags menu_tags compress sekizai_tags %}
+<!doctype html>
+<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en"> <![endif]-->
+<!--[if IE 7]>    <html class="no-js ie7 oldie" lang="en"> <![endif]-->
+<!--[if IE 8]>    <html class="no-js ie8 oldie" lang="en"> <![endif]-->
+<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
+<head>
+    <meta charset="utf-8">
+    <title>{% page_attribute page_title %}</title>
+    <meta name="description" content="{% page_attribute meta_description %}">
+    <meta name="author" content="">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <link rel="shortcut icon" href="{{ STATIC_URL }}img/favicon.ico">
+    <link rel="apple-touch-icon" href="{{ STATIC_URL }}img/apple-touch-icon.png">
+    <link rel="stylesheet" href="{{ STATIC_URL }}css/boilerplate.css" type="text/css">
+    <link rel="stylesheet" href="{{ STATIC_URL }}css/1140.css" type="text/css" media="screen" />
+    <!--[if lte IE 9]>
+        <link rel="stylesheet" href="{{ STATIC_URL }}css/ie.css" type="text/css" media="screen" />
+    <![endif]-->
+    {% comment %}
+    <link rel="stylesheet" href="{{ STATIC_URL }}css/workshop/styles.css" type="text/css" media="screen">
+    {% endcomment %}
+    {% compress css %}
+        <link rel="stylesheet" href="{{ STATIC_URL }}css/workshop/styles.scss" type="text/x-scss">
+        <link rel="stylesheet" href="{{ STATIC_URL }}css/boilerplate_media.css" type="text/css">
+    {% endcompress %}
+    {% render_block "css" %}
+    <link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}css/workshop/jquery.thumbox.1.3.css" />
+    <script src="{{ STATIC_URL }}js/libs/modernizr-2.0.6.min.js"></script>
+</head>
+
+<body>
+
+<div id="container" class="container">
+    <div id="middle">
+            <header>
+                <div class="row">
+                    <div id="label" class="sixcol last">
+                        <p>
+                            <a href="/">Aufgabe 4: Plugin</a>
+                        </p>
+                    </div>
+                </div>
+            </header>
+        <div id="inner">
+            <div id="main" role="main">
+                <div class="row">
+                    <div class="twelvecol content-padding"></div>
+                </div>
+                <div class="row">
+                    <div id="content-left" class="threecol content">
+                        {% block left %}
+                            <div id="main-menu">
+                                <ul>
+                                    {% show_menu 0 0 0 0 "menu/menu.html" %}
+                                </ul>
+                            </div>
+                            {% placeholder links %}
+                        {% endblock left %}
+                    </div>
+                    <div id="content-middle" class="sixcol content">
+                        {% block middle %}
+                            <p>Six columns</p>
+                        {% endblock middle %}
+                    </div>
+                    <div id="content-right" class="threecol content last">
+                            <div id="main-menu">
+                                <ul>
+                                    {% show_menu 1 0 0 1 "menu/menu.html" %}
+                                    {# show_sub_menu 1 "menu/menu.html" #}
+                                </ul>
+                            </div>
+                        {% block right %}
+                            <p>Three columns</p>
+                        {% endblock right %}
+                    </div>
+                </div>
+                <div class="row">
+                    <div class="twelvecol content-padding"></div>
+                </div>
+                <img id="stamp" src="{{ STATIC_URL }}img/workshop/django-cms-logo-small.jpg" alt="">
+            </div>
+
+{% comment %}
+            <footer>
+                <div class="row">
+                    <div class="twelvecol">
+                        <p>Twelve columns</p>
+                    </div>
+                </div>
+            </footer>
+{% endcomment %}
+        </div>
+    </div>
+</div>
+
+<div id="background">
+    <div>
+        <table cellpadding="0" cellspacing="0">
+            <tbody>
+            <tr>
+                <td>
+                    <img alt="" src="{{ STATIC_URL }}img/workshop/background_1.jpg">
+                </td>
+            </tr>
+            </tbody>
+        </table>
+    </div>
+</div>
+  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
+  {% compress js %}
+  <script>window.jQuery || document.write('<script src="{{ STATIC_URL }}js/libs/jquery-1.6.2.min.js"><\/script>')</script>
+  <script src="{{ STATIC_URL }}js/script.js" type="text/javascript"></script>
+  <!--
+  <script type="text/javascript">
+    var _gaq = _gaq || [];
+    _gaq.push(['_setAccount','XX-XXXXXXX-XX']);
+    _gaq.push(['_gat._anonymizeIp']);
+    _gaq.push(['_trackPageview']);
+    (function() {
+      var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+      ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+      var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+    })();
+  </script>
+  -->
+  {% endcompress %}
+  <script type="text/javascript" src="{{ STATIC_URL }}js/workshop/jquery.tools.min.js"></script>
+  {% render_block "js" %}
+  {% block replace_js %}
+      <script type="text/javascript" src="{{ STATIC_URL }}js/workshop/jquery.easing.1.3.js"></script>
+      <script type="text/javascript" src="{{ STATIC_URL }}js/workshop/jquery.thumbox.1.3.js"></script>
+<script type="text/javascript">
+    $(function(){
+        $('#gallery').thumbox();
+        $("#gallery img[title]").tooltip();
+    })
+</script>
+  {% endblock replace_js %}
+
+</body>
+</html>

aufgaben/4/workshop/templates/bright.html

+{% extends "base.html" %}
+
+{% load cms_tags menu_tags thumbnail compress sekizai_tags %}
+{% block middle %}
+    {% placeholder mitte %}
+    {% addtoblock "css" %}
+        {% compress css %}
+        <link rel="stylesheet" href="{{ STATIC_URL }}css/workshop/styles-bright.scss" type="text/x-scss">
+        {% endcompress %}
+    {% endaddtoblock %}
+{% endblock middle %}
+{% block right %}
+    {% placeholder rechts %}
+{% endblock right %}
+{% addtoblock "js" %}
+{% endaddtoblock %}

aufgaben/4/workshop/templates/css/workshop/jquery.thumbox.1.3.css

+/** 
+  * 
+  * Thumbox - plugin para galeria de imagens
+  *
+  *  @author     Jose Raimundo de Sousa Neto <sputinykster@gmail.com>
+  *  @version    1.3
+  *  @link       http://www.jneto.net.br
+  *  @since      1.0
+  *  
+  **/
+#thumbox-dock *, #thumbox-overlay, #thumbox-image, #thumbox-border, #thumbox-loader, #thumbox-close, #thumbox-buttonNext, #thumbox-buttonPrev, #thumbox-label{
+	margin:0;
+	padding:0;
+	border:0;
+}
+#thumbox-dock{
+	position:absolute;
+	z-index:9996;
+	background:#000;
+	top:-5000px;
+	left:-5000px
+}
+#thumbox-dock .thumbox-scrollerpages{
+	overflow:hidden;
+	float:left;
+	position: relative;
+}
+#thumbox-dock .thumbox-pages{
+	position:relative;
+	width:100%;
+	left:0;
+}
+#thumbox-dock .thumbox-page{
+	text-align:center;
+	float:left;
+}
+#thumbox-dock .thumbox-page img{
+	margin:10px;
+	cursor:pointer;
+	border:4px #333 solid;
+        -moz-border-radius: 3px;
+        border-radius: 3px;
+}
+#thumbox-dock .thumbox-arrowdock{
+	width:20px;
+	cursor:pointer;
+	float:left;
+	background:#333 no-repeat center center;
+}
+#thumbox-dock .thumbox-leftarrow{
+	background-image:url(../../img/workshop/thumbox-prev.png);
+}
+#thumbox-dock .thumbox-rightarrow{
+	background-image:url(../../img/workshop/thumbox-next.png);
+}
+#thumbox-overlay{
+	position:absolute;
+	z-index:9995;
+	top:0;
+	left:0;
+  	-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
+  	filter: alpha(opacity=0);
+  	-moz-opacity: 0.0;
+  	-khtml-opacity: 0.0;
+  	opacity: 0.0;
+}
+.thumbox-hoverImage, .thumbox-currentImage{
+	border-color:#DDD !important;
+}
+#thumbox-image{
+	position:absolute;
+	z-index:9998;
+}
+#thumbox-border{
+	position:absolute;
+	z-index:9997;
+	background:#FFF;
+        -moz-border-radius: 8px;
+        border-radius: 8px;
+}
+
+#thumbox-loader{
+	position:absolute;
+	z-index:9999;
+	width:128px;
+	height:15px;
+	background:url(../../img/workshop/thumbox-loader.gif)
+}
+#thumbox-close{
+	position:absolute;
+	z-index:9999;
+	width:30px;
+	height:30px;
+	background:url(../../img/workshop/thumbox-close.png);
+	cursor:pointer;
+}
+#thumbox-buttonNext, #thumbox-buttonPrev{
+	width:41px;
+	height:66px;
+	position:absolute;
+	z-index:9999;
+	cursor:pointer;
+}
+#thumbox-buttonNext{
+	background:url(../../img/workshop/thumbox-nextImg.png);
+}
+#thumbox-buttonPrev{
+	background:url(../../img/workshop/thumbox-prevImg.png);
+}
+#thumbox-label{
+	background:url(../../img/workshop/thumbox-bgLabel.png);
+	position:absolute;
+	z-index:9999;
+	color:#FFF;
+	font-size:15px;
+	font-family:"Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
+	padding:5px;
+        -moz-border-radius: 5px;
+        border-radius: 5px;
+}

aufgaben/4/workshop/templates/css/workshop/styles-bright.scss

+@option compress: no;
+$content_background_color: #b5a894;
+$content_foreground_color: #211309;
+$font_name: Ubuntu;
+
+@font-face {
+    font-family: $font_name;
+    src: url("/static/img/workshop/Ubuntu-B.ttf");
+}
+
+html,body,#background,#background table,#background td,#container {
+    width:100%;
+    height:100%;
+    overflow:hidden;
+}
+
+body{
+    font-family: $font_name,"Trebuchet MS",Helvetica,Verdana,Arial,sans-serif;
+    font-size:1.5em;
+    cursor:default;
+    /* background:url(loading.gif); */
+    color:#000
+}
+
+.sixcol {
+    width: 47%;
+}
+
+header {
+    color: $content_background_color;
+    a, a:visited, a:link {
+        text-decoration: none;
+        color: $content_background_color;
+    }
+}
+
+#container {
+    position:absolute;
+    overflow:hidden;
+    z-index:10;
+}
+.container {
+    padding-left:0px;
+    padding-right:0px;
+}
+#container[id] {
+    display: table;
+    /* position: static; */
+}
+
+#label {
+    font-variant: small-caps;
+    font-size: 2em;
+}
+
+.content-padding {
+    height: 55px;
+}
+
+.content {
+    min-height: 480px;
+}
+
+#content-left {
+  border-right: 2px dashed #608b9c;
+  margin-right: 3.8%;
+  padding-right: 3.8%;
+  width: 18.2%;
+}
+
+#content-middle {
+    color: $content_foreground_color;
+}
+
+#content-right {
+  border-left: 2px dashed #608b9c;
+  padding-left: 3.8%;
+  width: 18.2%;
+}
+
+#main-menu {
+    text-align: right;
+    text-decoration: none;
+    text-transform: uppercase;
+    ul li.selected a {
+            color: #f34013;
+    }
+    ul li {
+        list-style-type: none;
+        line-height: 1.8em;
+        a {
+            color: #d4e7eb;
+            text-decoration: none;
+        }
+    }
+}
+#fixed-menu {
+    margin-top:20%;
+    text-align: right;
+    text-decoration: none;
+    text-transform: uppercase;
+    ul li.selected a {
+            color: #f34013;
+    }
+    ul li {
+        list-style-type: none;
+        line-height: 1.8em;
+        a {
+            color: $content_foreground_color;
+            text-decoration: none;
+        }
+    }
+}
+
+#background {
+  div {position:absolute;width:200%;height:200%;top:-50%;left:-50%;}
+  td {vertical-align:middle;text-align:center;}
+  img {min-height:50%;min-width:50%;margin:0 auto;}
+}
+
+#middle {
+    position: static;
+    top: 50%;
+}
+
+#middle[id] {
+    display: table-cell;
+    vertical-align: middle;
+    width: 100%;
+}
+#inner {
+    position: relative;
+    top: -50%;
+    color: $content_foreground_color;
+    background: $content_background_color;
+    min-height: 590px;
+}
+
+img#stamp {
+    position: absolute;
+    right: 0;
+    bottom: 55px;
+}
+
+#gallery {
+	overflow: hidden;
+}
+#gallery table {
+    width: 100%;
+}
+
+#gallery table tbody tr td {
+	align: center;
+
+}
+
+#gallery {
+    overflow: hidden;
+    table tbody {
+	    align: center;
+        tr {
+	        align: center;
+            td {
+	            align: center;
+                img {
+                    width: 150px;
+                    height: 130px;
+                    margin-right: 10%;
+                    margin-left: 10%;
+                    margin-bottom: 20%;
+                    -moz-box-shadow: 0 0 5px #888;
+                    -webkit-box-shadow: 0 0 5px#888;
+                    box-shadow: 0 0 5px #888;
+                }
+                .pix {
+                    width: 150px;
+                    height: 130px;
+                    margin-right: 10%;
+                    margin-left: 10%;
+                    margin-bottom: 20%;
+                }
+            }
+        }
+    }
+}
+
+.tooltip {
+	display:none;
+	background:transparent url(/static/img/workshop/black_arrow.png);
+    background-size: 100%;
+    background-repeat: no-repeat;
+    background-origin: content;
+    src: url("/static/img/workshop/CtRo.ttf") format("truetype");
+	font-size:12px;
+	min-height:70px;
+	width:160px;
+	padding:25px;
+	color:#fff;
+    z-index:15;
+}
+
+#scrollable {
+   /* required settings */
+	position:relative;
+	overflow:hidden;
+	/* width: 610px; */
+	min-height:480px;
+   .items {
+       	/* this cannot be too large */
+	    width:20000em;
+	    position:absolute;
+	    div {
+	        float:left;
+	        img {
+	            min-height:400px;
+	            max-height:580px;
+	            min-width:300px;
+	            max-width:600px;
+	        }
+	    }
+   }
+}
+
+.hide {
+    visibility:hidden;
+}
+
+.pagination {
+    text-align: right;
+	text-transform: uppercase;
+    .disabled {
+        visibility: hidden;
+    }
+    a {
+        text-decoration: none;
+	    color: #608b9c;
+    }
+}
+

aufgaben/4/workshop/templates/css/workshop/styles.css

+@font-face {
+  font-family: Ubuntu;
+  src: url("/static/img/workshop/Ubuntu-B.ttf");
+}
+#background, #background table, #background td, #container, body,
+html {
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+}
+body {
+  font-family: Ubuntu, "Trebuchet MS", Helvetica, Verdana, Arial, sans-serif;
+  font-size: 1.5em;
+  cursor: default;
+  color: #000;
+}
+.sixcol {
+  width: 47%;
+}
+header {
+  color: #608b9c;
+}
+header a, header a:link, header a:visited {
+  text-decoration: none;
+  color: #608b9c;
+}
+#container {
+  position: absolute;
+  overflow: hidden;
+  z-index: 10;
+}
+.container {
+  padding-left: 0px;
+  padding-right: 0px;
+}
+#container[id] {
+  display: table;
+}
+#label {
+  font-variant: small-caps;
+  font-size: 2em;
+}
+.content-padding {
+  height: 55px;
+}
+.content {
+  min-height: 480px;
+}
+#content-left {
+  border-right: 2px dashed #608b9c;
+  margin-right: 3.8%;
+  padding-right: 3.8%;
+  width: 18.2%;
+}
+#content-middle {
+  color: #ffffff;
+}
+#content-right {
+  border-left: 2px dashed #608b9c;
+  padding-left: 3.8%;
+  width: 18.2%;
+}
+#main-menu {
+  text-align: right;
+  text-decoration: none;
+  text-transform: uppercase;
+}
+#main-menu ul li.selected a {
+  color: #f34013;
+}
+#main-menu ul li.ancestor a {
+  color: #f34013;
+}
+#main-menu ul li {
+  list-style-type: none;
+  line-height: 1.8em;
+}
+#main-menu ul li a {
+  color: #d4e7eb;
+  text-decoration: none;
+}
+#fixed-menu {
+  margin-top: 20%;
+  text-align: right;
+  text-decoration: none;
+  text-transform: uppercase;
+}
+#fixed-menu ul li.selected a {
+  color: #f34013;
+}
+#fixed-menu ul li {
+  list-style-type: none;
+  line-height: 1.8em;
+}
+#fixed-menu ul li a {
+  color: #608b9c;
+  text-decoration: none;
+}
+#background div {
+  position: absolute;
+  width: 200%;
+  height: 200%;
+  top: -50%;
+  left: -50%;
+}
+#background td {
+  vertical-align: middle;
+  text-align: center;
+}
+#background img {
+  min-height: 50%;
+  min-width: 50%;
+  margin: 0 auto;
+}
+#middle {
+  position: static;
+  top: 50%;
+}
+#middle[id] {
+  display: table-cell;
+  vertical-align: middle;
+  width: 100%;
+}
+#inner {
+  position: relative;
+  top: -50%;
+  color: #608b9c;
+  background: #163009;
+  min-height: 590px;
+}
+img#stamp {
+  position: absolute;
+  right: 0;
+  bottom: 55px;
+}
+#gallery {
+  overflow: hidden;
+}
+#gallery table {
+  width: 100%;
+}
+#gallery table tbody tr td {
+  align: center;
+}
+#gallery {
+  overflow: hidden;
+}
+#gallery table tbody {
+  align: center;
+}
+#gallery table tbody tr {
+  align: center;
+}
+#gallery table tbody tr td {
+  align: center;
+}
+#gallery table tbody tr td img {
+  width: 150px;
+  height: 130px;
+  margin-right: 10%;
+  margin-left: 10%;
+  margin-bottom: 20%;
+  -moz-box-shadow: 0 0 5px #888;
+  -webkit-box-shadow: 0 0 5px#888;
+  box-shadow: 0 0 5px #888;
+}
+#gallery table tbody tr td .pix {
+  width: 150px;
+  height: 130px;
+  margin-right: 10%;
+  margin-left: 10%;
+  margin-bottom: 20%;
+}
+.tooltip {
+  display: none;
+  background: transparent url(/static/img/bal/black_arrow.png);
+  background-size: 100%;
+  background-repeat: no-repeat;
+  background-origin: content;
+  src: url("/static/img/bal/CtRo.ttf") format("truetype");
+  font-size: 12px;
+  min-height: 70px;
+  width: 160px;
+  padding: 25px;
+  color: #fff;
+  z-index: 15;
+}
+#scrollable {
+  position: relative;
+  overflow: hidden;
+  min-height: 480px;
+}
+#scrollable .items {
+  width: 20000em;
+  position: absolute;
+}
+#scrollable .items div {
+  float: left;
+}
+#scrollable .items div img {
+  min-height: 400px;
+  max-height: 580px;
+  min-width: 300px;
+  max-width: 600px;
+}
+.hide {
+  visibility: hidden;
+}
+.pagination {
+  text-align: right;
+  text-transform: uppercase;
+}
+.pagination .disabled {
+  visibility: hidden;
+}
+.pagination a {
+  text-decoration: none;
+  color: #608b9c;
+}
+

aufgaben/4/workshop/templates/css/workshop/styles.scss

+@option compress: no;
+
+$content_background_color: #163009;
+$content_foreground_color: #608b9c;
+$font_name: Ubuntu;
+
+@font-face {
+    font-family: $font_name;
+    src: url("/static/img/workshop/Ubuntu-B.ttf");
+}
+
+html,body,#background,#background table,#background td,#container {
+    width:100%;
+    height:100%;
+    overflow:hidden;
+}
+
+body{
+    font-family: $font_name,"Trebuchet MS",Helvetica,Verdana,Arial,sans-serif;
+    font-size:1.5em;
+    cursor:default;
+    /* background:url(loading.gif); */
+    color:#000;
+}
+
+.sixcol {
+    width: 47%;
+}
+
+header {
+    color: $content_foreground_color;
+    a, a:visited, a:link {
+        text-decoration: none;
+        color: $content_foreground_color;
+    }
+}
+
+#container {
+    position:absolute;
+    overflow:hidden;
+    z-index:10;
+}
+.container {
+    padding-left:0px;
+    padding-right:0px;
+}
+#container[id] {
+    display: table;
+    /* position: static; */
+}
+
+#label {
+    font-variant: small-caps;
+    font-size: 2em;
+}
+
+.content-padding {
+    height: 55px;
+}
+
+.content {
+    min-height: 480px;
+}
+
+#content-left {
+  border-right: 2px dashed #608b9c;
+  margin-right: 3.8%;
+  padding-right: 3.8%;
+  width: 18.2%;
+}
+
+#content-middle {
+    color: white;
+}
+
+#content-right {
+  border-left: 2px dashed #608b9c;
+  padding-left: 3.8%;
+  width: 18.2%;
+}
+
+#main-menu {
+    text-align: right;
+    text-decoration: none;
+    text-transform: uppercase;
+    ul li.selected a {
+            color: #f34013;
+    }
+    ul li.ancestor a {
+            color: #f34013;
+    }
+    ul li {
+        list-style-type: none;
+        line-height: 1.8em;
+        a {
+            color: #d4e7eb;
+            text-decoration: none;
+        }
+    }
+}