Compare commits

..

No commits in common. "e2d166e4379d7b512324d7f142ebfd132e0d0b54" and "df22b838fa291aee74aead09d54784647a4e2d49" have entirely different histories.

222 changed files with 11081 additions and 1180 deletions

9
.buildpath Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<buildpath>
<buildpathentry kind="src" path=""/>
<buildpathentry kind="con" path="org.eclipse.dltk.mod.launching.INTERPRETER_CONTAINER"/>
<buildpathentry kind="con" path="org.eclipse.vjet.eclipse.core.JSNATIVE_CONTAINER/JS Native Types"/>
<buildpathentry kind="con" path="org.eclipse.vjet.eclipse.core.BROWSER_CONTAINER/Browser SDK"/>
<buildpathentry kind="con" path="org.eclipse.vjet.eclipse.core.VJO_CONTAINER/VJO LIB"/>
</buildpath>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="false"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_DISABLED_BUILDER" value="org.eclipse.vjet.eclipse.core.builder"/>
<mapAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
</launchConfiguration>

2
.gitignore vendored
View File

@ -4,5 +4,3 @@
/.idea /.idea
/._bootstrapTemplates /._bootstrapTemplates
/env /env
/venv
/bower_components

View File

@ -1,24 +0,0 @@
# docker build -t "blechreiz_website" .
FROM ubuntu:20.04
RUN apt-get update \
&& apt-get install -y python3 python3-venv python3-wheel \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
ADD . /blechreiz
ENV BLECHREIZ_DATA /data
ENV PYTHONUNBUFFERED 1
ENV PYTHONPATH /blechreiz
RUN cd /blechreiz \
&& python3 -m venv env \
&& . /blechreiz/env/bin/activate \
&& rm -r /blechreiz/blechreiz/data \
&& /blechreiz/env/bin/pip install -r requirements.txt
EXPOSE 8000
CMD /blechreiz/env/bin/python3 /blechreiz/manage.py collectstatic --noinput \
&& /blechreiz/env/bin/gunicorn -b 0.0.0.0:8000 blechreiz.wsgi

4
Todo.txt Normal file
View File

@ -0,0 +1,4 @@
- Email benachrichtigung bei Foreneintrag!
- Gallery

View File

@ -0,0 +1 @@
{"_module": "oauth2client.client", "token_expiry": "2014-06-20T09:36:07Z", "access_token": "ya29.LgA4Q4jhQqjEoBwAAABv_luKCAgrb2C-s1IcYmGZ8nZViS_QHvHKT-IkSo31RQ", "token_uri": "https://accounts.google.com/o/oauth2/token", "invalid": false, "token_response": {"access_token": "ya29.LgA4Q4jhQqjEoBwAAABv_luKCAgrb2C-s1IcYmGZ8nZViS_QHvHKT-IkSo31RQ", "token_type": "Bearer", "expires_in": 3600}, "client_id": "34462582242-4kpdvvbi27ajt4u22uitqurpve9o8ipj.apps.googleusercontent.com", "id_token": null, "client_secret": "y4t9XBrJdCODPTO5UvtONWWn", "revoke_uri": "https://accounts.google.com/o/oauth2/revoke", "_class": "OAuth2Credentials", "refresh_token": "1/7-6-m_lLAKX8IeD7OuGtkcIiprty_nZUSxhMunSC5b0", "user_agent": null}

View File

@ -1 +0,0 @@
{"_module": "oauth2client.client", "token_expiry": "2018-12-18T12:55:20Z", "access_token": "ya29.Gl12BuJlFBtRZSBtMkxubhfG8rYDsLUgc1yKMpO9_aE3tmi4sLFGLq_Djq5R9zr1919oZAobX0oaD6bTj3s4i9kqWfw0gpOGKJKRHM1Y9gHc0JsCe2kChNszu_RCAaE", "token_uri": "https://accounts.google.com/o/oauth2/token", "invalid": false, "token_response": {"access_token": "ya29.Gl12BuJlFBtRZSBtMkxubhfG8rYDsLUgc1yKMpO9_aE3tmi4sLFGLq_Djq5R9zr1919oZAobX0oaD6bTj3s4i9kqWfw0gpOGKJKRHM1Y9gHc0JsCe2kChNszu_RCAaE", "scope": "https://www.googleapis.com/auth/calendar", "expires_in": 3600, "token_type": "Bearer"}, "client_id": "34462582242-4kpdvvbi27ajt4u22uitqurpve9o8ipj.apps.googleusercontent.com", "id_token": null, "client_secret": "y4t9XBrJdCODPTO5UvtONWWn", "revoke_uri": "https://accounts.google.com/o/oauth2/revoke", "_class": "OAuth2Credentials", "refresh_token": "1/txixroRJyyVmuENPpaXyB_bGeXa1XV-pClAxqKHk_5-JW1qGFE0Gl-WlgCu1Eizq", "user_agent": null}

Binary file not shown.

0
blechreiz/logfile Normal file
View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 271 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 271 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 B

View File

@ -2,8 +2,7 @@ from django.http import HttpResponseRedirect
from django.conf import settings from django.conf import settings
import re import re
class EnforceLoginMiddleware(object):
class EnforceLoginMiddleware:
""" """
Middlware class which requires the user to be authenticated for all urls except Middlware class which requires the user to be authenticated for all urls except
those defined in PUBLIC_URLS in settings.py. PUBLIC_URLS should be a tuple of regular those defined in PUBLIC_URLS in settings.py. PUBLIC_URLS should be a tuple of regular
@ -15,28 +14,27 @@ class EnforceLoginMiddleware:
validation on these set SERVE_STATIC_TO_PUBLIC to False. validation on these set SERVE_STATIC_TO_PUBLIC to False.
""" """
def __init__(self, get_response): def __init__(self):
self.login_url = getattr(settings, 'LOGIN_URL', '/accounts/login/') self.login_url = getattr(settings, 'LOGIN_URL', '/accounts/login/' )
self.get_response = get_response
if hasattr(settings, 'PUBLIC_URLS'): if hasattr(settings,'PUBLIC_URLS'):
public_urls = [re.compile(url) for url in settings.PUBLIC_URLS] public_urls = [re.compile(url) for url in settings.PUBLIC_URLS]
else: else:
public_urls = [(re.compile("^%s/?$" % (self.login_url[1:])))] public_urls = [(re.compile("^%s/?$" % ( self.login_url[1:] )))]
if getattr(settings, 'SERVE_STATIC_TO_PUBLIC', True): if getattr(settings, 'SERVE_STATIC_TO_PUBLIC', True ):
root_urlconf = __import__(settings.ROOT_URLCONF) root_urlconf = __import__(settings.ROOT_URLCONF)
public_urls.extend([re.compile(url.regex) public_urls.extend([ re.compile(url.regex)
for url in root_urlconf.urls.urlpatterns for url in root_urlconf.urls.urlpatterns
if url.__dict__.get('_callback_str') == 'django.views.static.serve' if url.__dict__.get('_callback_str') == 'django.views.static.serve'
]) ])
self.public_urls = tuple(public_urls) self.public_urls = tuple(public_urls)
def __call__(self, request): def process_request(self, request):
""" """
Redirect anonymous users to login_url from non public urls Redirect anonymous users to login_url from non public urls
""" """
try: try:
if request.user.is_anonymous: if request.user.is_anonymous():
for url in self.public_urls: for url in self.public_urls:
if url.match(request.path[1:]): if url.match(request.path[1:]):
return None return None
@ -44,20 +42,14 @@ class EnforceLoginMiddleware:
except AttributeError: except AttributeError:
return HttpResponseRedirect("%s?next=%s" % (self.login_url, request.path)) return HttpResponseRedirect("%s?next=%s" % (self.login_url, request.path))
return self.get_response(request)
class DetectDevice: class DetectDevice(object):
def __init__(self, get_response): def process_request(self, request):
self.get_response = get_response
def __call__(self, request):
device = self.mobile(request) device = self.mobile(request)
request.device = device request.device = device
response = self.get_response(request)
return response
def mobile(self, request): def mobile(self, request):
device = {} device = {}
@ -82,10 +74,10 @@ class DetectDevice:
if ua.find("iemobile") > 0: if ua.find("iemobile") > 0:
device['winmo'] = "winmo" device['winmo'] = "winmo"
if not device: # either desktop, or something we don't care about. if not device: # either desktop, or something we don't care about.
device['baseline'] = "baseline" device['baseline'] = "baseline"
# spits out device names for CSS targeting, to be applied to <html> or <body>. # spits out device names for CSS targeting, to be applied to <html> or <body>.
device['classes'] = " ".join(v for (k, v) in device.items()) device['classes'] = " ".join(v for (k,v) in device.items())
return device return device

View File

@ -1,10 +1,8 @@
# Setting the path # Setting the path
import os import os
gettext = lambda s: s gettext = lambda s: s
PROJECT_PATH = os.path.abspath(os.path.dirname(__file__)) PROJECT_PATH = os.path.abspath(os.path.dirname(__file__))
DATA_PATH = os.environ.get('BLECHREIZ_DATA', default=os.path.join(PROJECT_PATH, "data"))
# Django settings for blechreiz project. # Django settings for blechreiz project.
@ -18,19 +16,21 @@ ADMINS = (
MANAGERS = ADMINS MANAGERS = ADMINS
DATABASES = { DATABASES = {
'default': { 'default': {
'ENGINE': 'django.db.backends.sqlite3', 'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(DATA_PATH, 'database.sqlite'), 'NAME': os.path.join(PROJECT_PATH, 'database.sqlite'),
} }
} }
# Email # Email
EMAIL_HOST = 'smtp.blechreiz.com' EMAIL_HOST='smtp.gmail.com'
EMAIL_HOST_USER = 'm02b721a' EMAIL_HOST_USER='martinbauer86@gmail.com'
EMAIL_HOST_PASSWORD = '9Hp4WG5bZ2WVPX5z' EMAIL_HOST_PASSWORD=''
EMAIL_USE_TLS = False EMAIL_USE_TLS=True
# Hosts/domain names that are valid for this site; required if DEBUG is False # Hosts/domain names that are valid for this site; required if DEBUG is False
# See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts # See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts
@ -61,7 +61,7 @@ USE_TZ = True
# Absolute filesystem path to the directory that will hold user-uploaded files. # Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/var/www/example.com/media/" # Example: "/var/www/example.com/media/"
MEDIA_ROOT = PROJECT_PATH + "/media" MEDIA_ROOT = PROJECT_PATH + "/media/"
# URL that handles the media served from MEDIA_ROOT. Make sure to use a # URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash. # trailing slash.
@ -78,12 +78,12 @@ STATIC_ROOT = PROJECT_PATH + '/static_collection'
# Example: "http://example.com/static/", "http://static.example.com/" # Example: "http://example.com/static/", "http://static.example.com/"
STATIC_URL = '/static/' STATIC_URL = '/static/'
LOGIN_URL = "/musicians/login" LOGIN_URL="/musicians/login"
PUBLIC_URLS = ("^musicians/login/?$", "^musicians/login/usernames/?$", "^eventplanner_gcal/gcalApiCallback*") PUBLIC_URLS=( "^musicians/login/?$", "^musicians/login/usernames/?$", "^eventplanner_gcal/gcalApiCallback*")
# Additional locations of static files # Additional locations of static files
STATICFILES_DIRS = ( STATICFILES_DIRS = (
#PROJECT_PATH + '/static', PROJECT_PATH + '/static',
# Put strings here, like "/home/html/static" or "C:/www/django/static". # Put strings here, like "/home/html/static" or "C:/www/django/static".
# Always use forward slashes, even on Windows. # Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths. # Don't forget to use absolute paths, not relative paths.
@ -94,43 +94,26 @@ STATICFILES_DIRS = (
STATICFILES_FINDERS = ( STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
# 'django.contrib.staticfiles.finders.DefaultStorageFinder', # 'django.contrib.staticfiles.finders.DefaultStorageFinder',
) )
# Make this unique, and don't share it with anybody. # Make this unique, and don't share it with anybody.
SECRET_KEY = 'x$8&9s6t%eeg=wyhar87934wh_s$dbpm(73g4ho&n)9_wogj6p' SECRET_KEY = 'x$8&9s6t%eeg=wyhar87934wh_s$dbpm(73g4ho&n)9_wogj6p'
TEMPLATES = [ # List of callables that know how to import templates from various sources.
{ TEMPLATE_LOADERS = (
'BACKEND': 'django.template.backends.django.DjangoTemplates', 'django.template.loaders.filesystem.Loader',
'DIRS': [ 'django.template.loaders.app_directories.Loader',
PROJECT_PATH + '/templates', # 'django.template.loaders.eggs.Loader',
], )
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
# Insert your TEMPLATE_CONTEXT_PROCESSORS here or use this
# list if you haven't customized them:
'django.contrib.auth.context_processors.auth',
'django.template.context_processors.i18n',
'django.template.context_processors.request',
'django.template.context_processors.media',
'django.template.context_processors.static',
'sekizai.context_processors.sekizai',
],
},
},
]
MIDDLEWARE = ( MIDDLEWARE_CLASSES = (
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.middleware.MessageMiddleware',
#'blechreiz.middleware.EnforceLoginMiddleware', 'blechreiz.middleware.EnforceLoginMiddleware',
'blechreiz.middleware.DetectDevice', 'blechreiz.middleware.DetectDevice',
# Uncomment the next line for simple clickjacking protection: # Uncomment the next line for simple clickjacking protection:
# 'django.middleware.clickjacking.XFrameOptionsMiddleware', # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
@ -142,6 +125,20 @@ ROOT_URLCONF = 'blechreiz.urls'
WSGI_APPLICATION = 'blechreiz.wsgi.application' WSGI_APPLICATION = 'blechreiz.wsgi.application'
TEMPLATE_DIRS = (
PROJECT_PATH + '/templates',
)
TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth',
'django.core.context_processors.i18n',
'django.core.context_processors.request',
'django.core.context_processors.media',
'django.core.context_processors.static',
'sekizai.context_processors.sekizai',
)
INSTALLED_APPS = ( INSTALLED_APPS = (
'django.contrib.auth', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.contenttypes',
@ -151,41 +148,44 @@ INSTALLED_APPS = (
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'django.contrib.admin', 'django.contrib.admin',
'django.contrib.admindocs', 'django.contrib.admindocs',
'crispy_forms', # better looking forms ( bootstrap ) 'crispy_forms', # better looking forms ( bootstrap )
'sekizai', # for the addtoblock directive in templates 'sekizai', # for the addtoblock directive in templates
'rest_framework', # for event management api 'rest_framework', # for event management api
'south',
# Own Things # Own Things
'bootstrapTheme', # Theme 'bootstrapTheme', # Theme
'website', # Blechreiz Website in general 'website', # Blechreiz Website in general
'musicians', # User Management 'musicians', # User Management
'eventplanner', # Event Management 'eventplanner', # Event Management
'eventplanner_gcal', # Event Management Sync with Google Calendar 'eventplanner_gcal', # Event Management Sync with Google Calendar
'simpleforum', # Messages ( Forum ) 'simpleforum', # Messages ( Forum )
'location_field', # custom location field used in Event Management 'location_field', # custom location field used in Event Management
'scoremanager', # manager of scores, repertoire etc. 'scoremanager', # manager of scores, repertoire etc.
# 'imagestore', #'imagestore',
# 'sorl.thumbnail', #'sorl.thumbnail',
# 'tagging' #'tagging'
) )
IMAGESTORE_TEMPLATE = "website/base.html" IMAGESTORE_TEMPLATE = "website/base.html"
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAuthenticated',), 'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAuthenticated',),
'PAGINATE_BY': 10 'PAGINATE_BY': 10
} }
GCAL_COUPLING = { GCAL_COUPLING = {
'eventPrefix': 'Blechreiz: ', 'eventPrefix' : 'Blechreiz: ',
'developerKey': 'blechreiz-homepage', 'developerKey' : 'blechreiz-homepage',
'clientId': '34462582242-4kpdvvbi27ajt4u22uitqurpve9o8ipj.apps.googleusercontent.com', 'clientId' : '34462582242-4kpdvvbi27ajt4u22uitqurpve9o8ipj.apps.googleusercontent.com',
'client_secret': 'y4t9XBrJdCODPTO5UvtONWWn', 'client_secret' : 'y4t9XBrJdCODPTO5UvtONWWn',
'credentials_file': DATA_PATH + '/calendarCredentials.dat', 'credentials_file' : PROJECT_PATH + '/calendarCredentials.dat',
'push_url': "https://blechreiz.bauer.technology/eventplanner_gcal/gcalApiCallback", 'push_url' : "https://test.bauer.technology/eventplanner_gcal/gcalApiCallback",
#'push_url' : "https://test.bauer.technology/callbackTest2.php",
} }
GOOGLE_MAPS_API_KEY = 'AIzaSyCf9Lm5ckjmVd08scTOd7fB1dC_UCoumKg'
GCAL_SYNC_ENABLED = True
CRISPY_TEMPLATE_PACK = 'bootstrap' CRISPY_TEMPLATE_PACK = 'bootstrap'
@ -199,21 +199,11 @@ CRISPY_TEMPLATE_PACK = 'bootstrap'
LOGGING = { LOGGING = {
'version': 1, 'version': 1,
'disable_existing_loggers': False, 'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '{levelname} {asctime} {module} {message}',
'style': '{',
},
'simple': {
'format': '{levelname} {asctime} {message}',
'style': '{',
},
},
'handlers': { 'handlers': {
'file': { 'file': {
'level': 'DEBUG', 'level': 'DEBUG',
'class': 'logging.FileHandler', 'class': 'logging.FileHandler',
'filename': DATA_PATH + '/eventplanner.log', 'filename': PROJECT_PATH + '/eventplanner.log',
}, },
}, },
'loggers': { 'loggers': {
@ -226,7 +216,7 @@ LOGGING = {
'handler': ['file'], 'handler': ['file'],
'level': 'DEBUG', 'level': 'DEBUG',
'propagate': True, 'propagate': True,
} }
}, },
} }

View File

@ -1,4 +1,4 @@
from django.conf.urls import include, url from django.conf.urls import patterns, include, url
from django.contrib import admin from django.contrib import admin
@ -6,23 +6,26 @@ import simpleforum.views
import eventplanner.urls import eventplanner.urls
import musicians.urls import musicians.urls
#import imagestore.urls
import website.urls import website.urls
import scoremanager.urls import scoremanager.urls
import eventplanner_gcal.urls import eventplanner_gcal.urls
from . import settings
import settings
from django.conf.urls.static import static from django.conf.urls.static import static
admin.autodiscover() admin.autodiscover()
urlpatterns = [ urlpatterns = patterns('',
url(r'^', include(website.urls)), url(r'^', include( website.urls ) ),
url(r'^events/', include(eventplanner.urls.urlpatterns)), url(r'^events/', include( eventplanner.urls.urlpatterns) ),
url(r'^musicians/', include(musicians.urls.urlpatterns)), url(r'^musicians/', include( musicians.urls.urlpatterns) ),
url(r'^scores/', include(scoremanager.urls.urlpatterns)), url(r'^scores/', include( scoremanager.urls.urlpatterns) ),
url(r'^messages/$', simpleforum.views.message_view), url(r'^messages/$', simpleforum.views.message_view ),
url(r'^admin/', admin.site.urls), url(r'^admin/', include( admin.site.urls ) ),
url(r'^location_field/', include('location_field.urls')), url(r'^location_field/', include( 'location_field.urls' ) ),
url(r'^eventplanner_gcal/', include(eventplanner_gcal.urls)), url(r'^eventplanner_gcal/', include( eventplanner_gcal.urls) ),
# url(r'^gallery/', include(imagestore.urls, namespace='imagestore') ), #url(r'^gallery/', include(imagestore.urls, namespace='imagestore') ),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) ) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

View File

@ -15,6 +15,13 @@ framework.
""" """
import os import os
import site
import sys
site.addsitedir('/srv/test/env/lib/python2.7/site-packages')
sys.path.append('/srv/test')
# We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks # We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks
# if running multiple sites in the same mod_wsgi process. To fix this, use # if running multiple sites in the same mod_wsgi process. To fix this, use
# mod_wsgi daemon mode with each site in its own daemon process, or use # mod_wsgi daemon mode with each site in its own daemon process, or use

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,566 @@
/*!
* jQuery UI CSS Framework 1.8.21
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Theming/API
*/
/* Layout helpers
----------------------------------*/
.ui-helper-hidden { display: none; }
.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
.ui-helper-clearfix:after { clear: both; }
.ui-helper-clearfix { zoom: 1; }
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
/* Interaction Cues
----------------------------------*/
.ui-state-disabled { cursor: default !important; }
/* Icons
----------------------------------*/
/* states and ../img */
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
/* Misc visuals
----------------------------------*/
/* Overlays */
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
/*!
* jQuery UI CSS Framework 1.8.21
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Theming/API
*
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
*/
/* Component containers
----------------------------------*/
.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
.ui-widget .ui-widget { font-size: 1em; }
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(../img/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
.ui-widget-content a { color: #222222; }
.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(../img/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
.ui-widget-header a { color: #222222; }
/* Interaction states
----------------------------------*/
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(../img/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; }
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; }
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(../img/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; }
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(../img/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; }
.ui-widget :active { outline: none; }
/* Interaction Cues
----------------------------------*/
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(../img/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(../img/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
/* Icons
----------------------------------*/
/* states and ../img */
.ui-icon { width: 16px; height: 16px; background-image: url(../img/ui-icons_222222_256x240.png); }
.ui-widget-content .ui-icon {background-image: url(../img/ui-icons_222222_256x240.png); }
.ui-widget-header .ui-icon {background-image: url(../img/ui-icons_222222_256x240.png); }
.ui-state-default .ui-icon { background-image: url(../img/ui-icons_888888_256x240.png); }
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(../img/ui-icons_454545_256x240.png); }
.ui-state-active .ui-icon {background-image: url(../img/ui-icons_454545_256x240.png); }
.ui-state-highlight .ui-icon {background-image: url(../img/ui-icons_2e83ff_256x240.png); }
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(../img/ui-icons_cd0a0a_256x240.png); }
/* positioning */
.ui-icon-carat-1-n { background-position: 0 0; }
.ui-icon-carat-1-ne { background-position: -16px 0; }
.ui-icon-carat-1-e { background-position: -32px 0; }
.ui-icon-carat-1-se { background-position: -48px 0; }
.ui-icon-carat-1-s { background-position: -64px 0; }
.ui-icon-carat-1-sw { background-position: -80px 0; }
.ui-icon-carat-1-w { background-position: -96px 0; }
.ui-icon-carat-1-nw { background-position: -112px 0; }
.ui-icon-carat-2-n-s { background-position: -128px 0; }
.ui-icon-carat-2-e-w { background-position: -144px 0; }
.ui-icon-triangle-1-n { background-position: 0 -16px; }
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
.ui-icon-triangle-1-e { background-position: -32px -16px; }
.ui-icon-triangle-1-se { background-position: -48px -16px; }
.ui-icon-triangle-1-s { background-position: -64px -16px; }
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
.ui-icon-triangle-1-w { background-position: -96px -16px; }
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
.ui-icon-arrow-1-n { background-position: 0 -32px; }
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
.ui-icon-arrow-1-e { background-position: -32px -32px; }
.ui-icon-arrow-1-se { background-position: -48px -32px; }
.ui-icon-arrow-1-s { background-position: -64px -32px; }
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
.ui-icon-arrow-1-w { background-position: -96px -32px; }
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
.ui-icon-arrow-4 { background-position: 0 -80px; }
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
.ui-icon-extlink { background-position: -32px -80px; }
.ui-icon-newwin { background-position: -48px -80px; }
.ui-icon-refresh { background-position: -64px -80px; }
.ui-icon-shuffle { background-position: -80px -80px; }
.ui-icon-transfer-e-w { background-position: -96px -80px; }
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
.ui-icon-folder-collapsed { background-position: 0 -96px; }
.ui-icon-folder-open { background-position: -16px -96px; }
.ui-icon-document { background-position: -32px -96px; }
.ui-icon-document-b { background-position: -48px -96px; }
.ui-icon-note { background-position: -64px -96px; }
.ui-icon-mail-closed { background-position: -80px -96px; }
.ui-icon-mail-open { background-position: -96px -96px; }
.ui-icon-suitcase { background-position: -112px -96px; }
.ui-icon-comment { background-position: -128px -96px; }
.ui-icon-person { background-position: -144px -96px; }
.ui-icon-print { background-position: -160px -96px; }
.ui-icon-trash { background-position: -176px -96px; }
.ui-icon-locked { background-position: -192px -96px; }
.ui-icon-unlocked { background-position: -208px -96px; }
.ui-icon-bookmark { background-position: -224px -96px; }
.ui-icon-tag { background-position: -240px -96px; }
.ui-icon-home { background-position: 0 -112px; }
.ui-icon-flag { background-position: -16px -112px; }
.ui-icon-calendar { background-position: -32px -112px; }
.ui-icon-cart { background-position: -48px -112px; }
.ui-icon-pencil { background-position: -64px -112px; }
.ui-icon-clock { background-position: -80px -112px; }
.ui-icon-disk { background-position: -96px -112px; }
.ui-icon-calculator { background-position: -112px -112px; }
.ui-icon-zoomin { background-position: -128px -112px; }
.ui-icon-zoomout { background-position: -144px -112px; }
.ui-icon-search { background-position: -160px -112px; }
.ui-icon-wrench { background-position: -176px -112px; }
.ui-icon-gear { background-position: -192px -112px; }
.ui-icon-heart { background-position: -208px -112px; }
.ui-icon-star { background-position: -224px -112px; }
.ui-icon-link { background-position: -240px -112px; }
.ui-icon-cancel { background-position: 0 -128px; }
.ui-icon-plus { background-position: -16px -128px; }
.ui-icon-plusthick { background-position: -32px -128px; }
.ui-icon-minus { background-position: -48px -128px; }
.ui-icon-minusthick { background-position: -64px -128px; }
.ui-icon-close { background-position: -80px -128px; }
.ui-icon-closethick { background-position: -96px -128px; }
.ui-icon-key { background-position: -112px -128px; }
.ui-icon-lightbulb { background-position: -128px -128px; }
.ui-icon-scissors { background-position: -144px -128px; }
.ui-icon-clipboard { background-position: -160px -128px; }
.ui-icon-copy { background-position: -176px -128px; }
.ui-icon-contact { background-position: -192px -128px; }
.ui-icon-image { background-position: -208px -128px; }
.ui-icon-video { background-position: -224px -128px; }
.ui-icon-script { background-position: -240px -128px; }
.ui-icon-alert { background-position: 0 -144px; }
.ui-icon-info { background-position: -16px -144px; }
.ui-icon-notice { background-position: -32px -144px; }
.ui-icon-help { background-position: -48px -144px; }
.ui-icon-check { background-position: -64px -144px; }
.ui-icon-bullet { background-position: -80px -144px; }
.ui-icon-radio-off { background-position: -96px -144px; }
.ui-icon-radio-on { background-position: -112px -144px; }
.ui-icon-pin-w { background-position: -128px -144px; }
.ui-icon-pin-s { background-position: -144px -144px; }
.ui-icon-play { background-position: 0 -160px; }
.ui-icon-pause { background-position: -16px -160px; }
.ui-icon-seek-next { background-position: -32px -160px; }
.ui-icon-seek-prev { background-position: -48px -160px; }
.ui-icon-seek-end { background-position: -64px -160px; }
.ui-icon-seek-start { background-position: -80px -160px; }
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
.ui-icon-seek-first { background-position: -80px -160px; }
.ui-icon-stop { background-position: -96px -160px; }
.ui-icon-eject { background-position: -112px -160px; }
.ui-icon-volume-off { background-position: -128px -160px; }
.ui-icon-volume-on { background-position: -144px -160px; }
.ui-icon-power { background-position: 0 -176px; }
.ui-icon-signal-diag { background-position: -16px -176px; }
.ui-icon-signal { background-position: -32px -176px; }
.ui-icon-battery-0 { background-position: -48px -176px; }
.ui-icon-battery-1 { background-position: -64px -176px; }
.ui-icon-battery-2 { background-position: -80px -176px; }
.ui-icon-battery-3 { background-position: -96px -176px; }
.ui-icon-circle-plus { background-position: 0 -192px; }
.ui-icon-circle-minus { background-position: -16px -192px; }
.ui-icon-circle-close { background-position: -32px -192px; }
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
.ui-icon-circle-zoomin { background-position: -176px -192px; }
.ui-icon-circle-zoomout { background-position: -192px -192px; }
.ui-icon-circle-check { background-position: -208px -192px; }
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
.ui-icon-circlesmall-close { background-position: -32px -208px; }
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
.ui-icon-squaresmall-close { background-position: -80px -208px; }
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
/* Misc visuals
----------------------------------*/
/* Corner radius */
.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -khtml-border-top-left-radius: 4px; border-top-left-radius: 4px; }
.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -khtml-border-top-right-radius: 4px; border-top-right-radius: 4px; }
.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
/* Overlays */
.ui-widget-overlay { background: #aaaaaa url(../img/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(../img/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*!
* jQuery UI Resizable 1.8.21
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Resizable#theming
*/
.ui-resizable { position: relative;}
.ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; }
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*!
* jQuery UI Selectable 1.8.21
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Selectable#theming
*/
.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
/*!
* jQuery UI Accordion 1.8.21
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Accordion#theming
*/
/* IE/Win - Fix animation bug - #4615 */
.ui-accordion { width: 100%; }
.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
.ui-accordion .ui-accordion-li-fix { display: inline; }
.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
.ui-accordion .ui-accordion-content-active { display: block; }
/*!
* jQuery UI Autocomplete 1.8.21
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Autocomplete#theming
*/
.ui-autocomplete { position: absolute; cursor: default; }
/* workarounds */
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
/*
* jQuery UI Menu 1.8.21
*
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Menu#theming
*/
.ui-menu {
list-style:none;
padding: 2px;
margin: 0;
display:block;
float: left;
}
.ui-menu .ui-menu {
margin-top: -3px;
}
.ui-menu .ui-menu-item {
margin:0;
padding: 0;
zoom: 1;
float: left;
clear: left;
width: 100%;
}
.ui-menu .ui-menu-item a {
text-decoration:none;
display:block;
padding:.2em .4em;
line-height:1.5;
zoom:1;
}
.ui-menu .ui-menu-item a.ui-state-hover,
.ui-menu .ui-menu-item a.ui-state-active {
font-weight: normal;
margin: -1px;
}
/*!
* jQuery UI Button 1.8.21
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Button#theming
*/
.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
.ui-button-icons-only { width: 3.4em; }
button.ui-button-icons-only { width: 3.7em; }
/*button text element */
.ui-button .ui-button-text { display: block; line-height: 1.4; }
.ui-button-text-only .ui-button-text { padding: .4em 1em; }
.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
/* no icon support for input elements, provide padding by default */
input.ui-button { padding: .4em 1em; }
/*button icon element(s) */
.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
/*button sets*/
.ui-buttonset { margin-right: 7px; }
.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
/* workarounds */
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
/*!
* jQuery UI Dialog 1.8.21
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Dialog#theming
*/
.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
.ui-draggable .ui-dialog-titlebar { cursor: move; }
/*!
* jQuery UI
1.8.21
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Slider#theming
*/
.ui-slider { position: relative; text-align: left; }
.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
.ui-slider-horizontal { height: .8em; }
.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
.ui-slider-horizontal .ui-slider-range-max { right: 0; }
.ui-slider-vertical { width: .8em; height: 100px; }
.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
.ui-slider-vertical .ui-slider-range-max { top: 0; }/*!
* jQuery UI Tabs 1.8.21
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Tabs#theming
*/
.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
.ui-tabs .ui-tabs-hide { display: none !important; }
/*!
* jQuery UI Datepicker 1.8.21
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Datepicker#theming
*/
.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
.ui-datepicker .ui-datepicker-prev { left:2px; }
.ui-datepicker .ui-datepicker-next { right:2px; }
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
.ui-datepicker select.ui-datepicker-month,
.ui-datepicker select.ui-datepicker-year { width: 49%;}
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
.ui-datepicker td { border: 0; padding: 1px; }
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
/* with multiple calendars */
.ui-datepicker.ui-datepicker-multi { width:auto; }
.ui-datepicker-multi .ui-datepicker-group { float:left; }
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
/* RTL support */
.ui-datepicker-rtl { direction: rtl; }
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
.ui-datepicker-cover {
display: none; /*sorry for IE5*/
display/**/: block; /*sorry for IE5*/
position: absolute; /*must have*/
z-index: -1; /*must have*/
filter: mask(); /*must have*/
top: -4px; /*must have*/
left: -4px; /*must have*/
width: 200px; /*must have*/
height: 200px; /*must have*/
}/*!
* jQuery UI Progressbar 1.8.21
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Progressbar#theming
*/
.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }

View File

@ -0,0 +1,513 @@
/* Higher than 1200 (desktop devices)
====================================================================== */
@media (min-width: 1200px) {
#content {
-webkit-box-shadow: -3px -1px 2px rgba(0,0,0,0.95);
-moz-box-shadow: -3px -1px 2px rgba(0,0,0,0.95);
box-shadow: -3px -1px 2px rgba(0,0,0,0.95);
background: url(../img/bg.jpg) repeat;
filter: none;
padding: 25px 0px 25px 40px;
margin: -25px -4px;
position: relative;
z-index: 1;
min-height: 100%;
}
.sidebar-nav > ul{
margin: 20px 0px 0px -20px;
border-top: 1px solid #0a0c0e !important;
border-bottom: 1px solid #212121 !important;
border-left: none;
border-right: none;
padding-bottom: 1px;
}
.sidebar-nav > ul > li > ul {
margin: 0px;
padding: 5px 0px 5px 25px;
background: rgba(0,0,0,.45);
list-style: none;
display: none;
}
.sidebar-nav > ul > li > ul > li {
padding: 5px 0px 5px 0px;
}
.sidebar-nav > ul > li > ul > li > a:hover {
color: #fff;
text-decoration: none;
}
.nav-tabs.nav-stacked > li > a {
margin: 1px 0px 0px 0px;
padding-left: 20px;
color: #ddd;
border-top: 1px solid #212121;
border-bottom: 1px solid #0a0c0e;
border-left: none;
border-right: none;
background: transparent;
filter: none;
text-shadow: 0px 1px 1px #000;
-webkit-border-radius: 0px;
-moz-border-radius: 0px;
border-radius: 0px;
}
.nav-tabs.nav-stacked > li > a > i {
opacity: .4;
}
.nav-tabs.nav-stacked > li > a:hover > i {
opacity: .8;
}
.nav-tabs.nav-stacked > li > a:hover {
margin: 1px 0px 0px 0px;
color: #fff;
border-top: 1px solid transparent;
border-bottom: 1px solid #0a0c0e;
border-left: none;
border-right: none;
background: rgba(0,0,0,.25);
filter: none;
text-shadow: 0px 1px 1px #000;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.45), inset 0 0px 1px rgba(0,0,0,0.25);
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,0.45), inset 0 0px 1px rgba(0,0,0,0.25);
box-shadow: inset 0 1px 1px rgba(0,0,0,0.45), inset 0 0px 1px rgba(0,0,0,0.25);
-webkit-border-radius: 0px;
-moz-border-radius: 0px;
border-radius: 0px;
}
.nav-tabs.nav-stacked > li.active > a {
margin: 1px 0px 0px 0px;
border-top: 1px solid transparent;
border-bottom: 1px solid #0a0c0e;
border-left: none;
border-right: none;
color: #fff;
background: rgba(0,0,0,.45);
text-shadow: 0px 1px 1px #000;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.45), inset 0 0px 1px rgba(0,0,0,0.25);
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,0.45), inset 0 0px 1px rgba(0,0,0,0.25);
box-shadow: inset 0 1px 1px rgba(0,0,0,0.45), inset 0 0px 1px rgba(0,0,0,0.25);
-webkit-border-radius: 0px;
-moz-border-radius: 0px;
border-radius: 0px;
}
.nav-tabs.nav-stacked > li:first-child > a {
margin: 0px 0px 0px 0px;
-webkit-border-radius: 0px;
-moz-border-radius: 0px;
border-radius: 0px;
}
.nav-tabs.nav-stacked > li:last-child > a {
-webkit-border-radius: 0px;
-moz-border-radius: 0px;
border-radius: 0px;
}
footer {
margin: -20px -20px 0px -20px;
padding: 10px 20px;
position: relative;
z-index: 2;
}
}
/* Higher than 960 (desktop devices)
====================================================================== */
@media only screen and (min-width: 980px) and (max-width: 1199px){
#content {
-webkit-box-shadow: -3px -1px 2px rgba(0,0,0,0.95);
-moz-box-shadow: -3px -1px 2px rgba(0,0,0,0.95);
box-shadow: -3px -1px 2px rgba(0,0,0,0.95);
background: url(../img/bg.jpg) repeat;
filter: none;
padding: 25px 0px 25px 40px;
margin: -25px -4px;
position: relative;
z-index: 1px;
}
.sidebar-nav > ul {
margin: 20px 0px 0px -20px;
border-top: 1px solid #0a0c0e !important;
border-bottom: 1px solid #212121 !important;
border-left: none;
border-right: none;
padding-bottom: 1px;
}
.sidebar-nav > ul > li > ul {
margin: 0px;
padding: 5px 0px 5px 25px;
background: rgba(0,0,0,.45);
list-style: none;
display: none;
}
.sidebar-nav > ul > li > ul > li {
padding: 5px 0px 5px 0px;
}
.sidebar-nav > ul > li > ul > li > a:hover {
color: #fff;
text-decoration: none;
}
.nav-tabs.nav-stacked > li > a {
margin: 1px 0px 0px 0px;
padding-left: 20px;
color: #ddd;
border-top: 1px solid #212121;
border-bottom: 1px solid #0a0c0e;
border-left: none;
border-right: none;
background: transparent;
text-shadow: 0px 1px 1px #000;
-webkit-border-radius: 0px;
-moz-border-radius: 0px;
border-radius: 0px;
}
.nav-tabs.nav-stacked > li > a > i {
opacity: .4;
}
.nav-tabs.nav-stacked > li > a:hover > i {
opacity: .8;
}
.nav-tabs.nav-stacked > li > a:hover {
margin: 1px 0px 0px 0px;
color: #fff;
border-top: 1px solid transparent;
border-bottom: 1px solid #0a0c0e;
border-left: none;
border-right: none;
background: rgba(0,0,0,.25);
filter: none;
text-shadow: 0px 1px 1px #000;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.45), inset 0 0px 1px rgba(0,0,0,0.25);
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,0.45), inset 0 0px 1px rgba(0,0,0,0.25);
box-shadow: inset 0 1px 1px rgba(0,0,0,0.45), inset 0 0px 1px rgba(0,0,0,0.25);
-webkit-border-radius: 0px;
-moz-border-radius: 0px;
border-radius: 0px;
}
.nav-tabs.nav-stacked > li.active > a {
margin: 1px 0px 0px 0px;
border-top: 1px solid transparent;
border-bottom: 1px solid #0a0c0e;
border-left: none;
border-right: none;
color: #fff;
background: rgba(0,0,0,.45);
text-shadow: 0px 1px 1px #000;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.45), inset 0 0px 1px rgba(0,0,0,0.25);
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,0.45), inset 0 0px 1px rgba(0,0,0,0.25);
box-shadow: inset 0 1px 1px rgba(0,0,0,0.45), inset 0 0px 1px rgba(0,0,0,0.25);
-webkit-border-radius: 0px;
-moz-border-radius: 0px;
border-radius: 0px;
}
.nav-tabs.nav-stacked > li:first-child > a {
margin: 0px 0px 0px 0px;
-webkit-border-radius: 0px;
-moz-border-radius: 0px;
border-radius: 0px;
}
.nav-tabs.nav-stacked > li:last-child > a {
-webkit-border-radius: 0px;
-moz-border-radius: 0px;
border-radius: 0px;
}
.sparkLineStats li .number {
font-size: 16px;
font-weight: 700;
padding:0 5px;
color: #FA5833;
}
footer {
margin: -20px -20px 0px -20px;
padding: 10px 20px;
position: relative;
z-index: 2;
}
}
/* Tablet Portrait (devices and browsers)
====================================================================== */
@media only screen and (min-width: 768px) and (max-width: 979px) {
#content {
-webkit-box-shadow: -2px -1px 2px rgba(0,0,0,0.95);
-moz-box-shadow: -2px -1px 2px rgba(0,0,0,0.95);
box-shadow: -2px -1px 2px rgba(0,0,0,0.95);
background: url(../img/bg.jpg) repeat;
filter: none;
padding: 25px 0px 25px 40px;
margin: -25px -4px;
position: relative;
z-index: 1px;
}
.noMargin {
margin-left: 0px !important;
}
.btn-navbar {
display: none !important;
}
.nav-collapse,
.nav-collapse.collapse {
height: auto !important;
overflow: visible !important;
margin-left: -20px !important;
}
.sidebar-nav{
padding:0;
margin-bottom:0;
}
.sidebar-nav > ul{
margin: 20px 0px 0px -20px;
border-top: 1px solid #0a0c0e !important;
border-bottom: 1px solid #212121 !important;
border-left: none;
border-right: none;
padding-bottom: 1px;
}
.sidebar-nav > ul > li > ul {
margin: 0px;
padding: 0px 0px 0px 20px;
background: rgba(0,0,0,.45);
list-style: none;
display: none;
}
.sidebar-nav > ul > li > ul > li {
padding: 5px 0px 5px 0px;
}
.sidebar-nav > ul > li > ul > li > a:hover {
color: #fff;
text-decoration: none;
}
.nav-tabs.nav-stacked > li > a {
margin: 1px 0px 0px 0px;
padding-left: 20px;
color: #ddd;
border-top: 1px solid #212121;
border-bottom: 1px solid #0a0c0e;
border-left: none;
border-right: none;
background: transparent;
text-shadow: 0px 1px 1px #000;
-webkit-border-radius: 0px;
-moz-border-radius: 0px;
border-radius: 0px;
}
.nav-tabs.nav-stacked > li > a > i {
opacity: .4;
}
.nav-tabs.nav-stacked > li > a:hover > i {
opacity: .8;
}
.nav-tabs.nav-stacked > li > a:hover {
margin: 1px 0px 0px 0px;
color: #fff;
border-top: 1px solid transparent;
border-bottom: 1px solid #0a0c0e;
border-left: none;
border-right: none;
background: rgba(0,0,0,.25);
filter: none;
text-shadow: 0px 1px 1px #000;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.45), inset 0 0px 1px rgba(0,0,0,0.25);
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,0.45), inset 0 0px 1px rgba(0,0,0,0.25);
box-shadow: inset 0 1px 1px rgba(0,0,0,0.45), inset 0 0px 1px rgba(0,0,0,0.25);
-webkit-border-radius: 0px;
-moz-border-radius: 0px;
border-radius: 0px;
}
.nav-tabs.nav-stacked > li.active > a {
margin: 1px 0px 0px 0px;
border-top: 1px solid transparent;
border-bottom: 1px solid #0a0c0e;
border-left: none;
border-right: none;
color: #fff;
background: rgba(0,0,0,.45);
text-shadow: 0px 1px 1px #000;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.45), inset 0 0px 1px rgba(0,0,0,0.25);
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,0.45), inset 0 0px 1px rgba(0,0,0,0.25);
box-shadow: inset 0 1px 1px rgba(0,0,0,0.45), inset 0 0px 1px rgba(0,0,0,0.25);
-webkit-border-radius: 0px;
-moz-border-radius: 0px;
border-radius: 0px;
}
.nav-tabs.nav-stacked > li:first-child > a {
margin: 0px 0px 0px 0px;
-webkit-border-radius: 0px;
-moz-border-radius: 0px;
border-radius: 0px;
}
.nav-tabs.nav-stacked > li:last-child > a {
-webkit-border-radius: 0px;
-moz-border-radius: 0px;
border-radius: 0px;
}
.box-small-link {
font-size: 20px;
}
.sparkLineStats li .number {
font-size: 14px;
font-weight: 700;
padding:0 5px;
color: #FA5833;
}
footer {
margin: -20px -20px 0px -20px;
padding: 10px 20px;
position: relative;
z-index: 2;
}
}
/* All Mobile Sizes (devices and browser)
====================================================================== */
@media only screen and (max-width: 767px) {
}
/* Mobile Landscape Size to Tablet Portrait (devices and browsers)
====================================================================== */
@media only screen and (min-width: 480px) and (max-width: 767px) {
body {
background: url(../img/bg.jpg) repeat;
}
#overlay ul {
margin: 150px auto 0;
}
#content {
background: transparent;
}
.quick-button,
.quick-button-small {
margin-bottom: 20px;
}
.pull-right {
width: 100%;
margin: 10px auto;
text-align: center;
}
.fc-button-today,
.fc-button-month,
.fc-button-agendaWeek,
.fc-button-agendaDay {
display: none;
}
footer {
padding: 10px 20px;
position: relative;
z-index: 2;
}
}
/* Mobile Portrait Size to Mobile Landscape Size (devices and browsers)
=================================================================== */
@media only screen and (max-width: 479px) {
#overlay ul {
margin: 150px auto 0;
}
body {
background: url(../img/bg.jpg) repeat;
}
#content {
background: transparent;
}
.quick-button,
.quick-button-small {
margin-bottom: 20px;
}
.pull-right {
width: 100%;
margin: 10px auto;
text-align: center;
}
.fc-button-today,
.fc-button-month,
.fc-button-agendaWeek,
.fc-button-agendaDay {
display: none;
}
table,
.pagination {
font-size: 10px;
}
.pagination {
padding: 5px;
}
footer {
padding: 10px 20px;
position: relative;
z-index: 2;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,37 +1,17 @@
/* German initialisation for the jQuery UI date picker plugin. */ /**
/* Written by Milian Wolff (mail@milianw.de). */ * German translation for bootstrap-datepicker
( function( factory ) { * Sam Zurcher <sam@orelias.ch>
if ( typeof define === "function" && define.amd ) { */
;(function($){
// AMD. Register as an anonymous module. $.fn.datepicker.dates['de'] = {
define( [ "../widgets/datepicker" ], factory ); days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"],
} else { daysShort: ["Son", "Mon", "Die", "Mit", "Don", "Fre", "Sam", "Son"],
daysMin: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"],
// Browser globals months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"],
factory( jQuery.datepicker ); monthsShort: ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"],
} today: "Heute",
}( function( datepicker ) { clear: "Löschen",
weekStart: 1,
datepicker.regional.de = { format: "dd.mm.yyyy"
closeText: "Schließen", };
prevText: "&#x3C;Zurück", }(jQuery));
nextText: "Vor&#x3E;",
currentText: "Heute",
monthNames: [ "Januar","Februar","März","April","Mai","Juni",
"Juli","August","September","Oktober","November","Dezember" ],
monthNamesShort: [ "Jan","Feb","Mär","Apr","Mai","Jun",
"Jul","Aug","Sep","Okt","Nov","Dez" ],
dayNames: [ "Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag" ],
dayNamesShort: [ "So","Mo","Di","Mi","Do","Fr","Sa" ],
dayNamesMin: [ "So","Mo","Di","Mi","Do","Fr","Sa" ],
weekHeader: "KW",
dateFormat: "dd.mm.yy",
firstDay: 1,
isRTL: false,
showMonthAfterYear: false,
yearSuffix: "" };
datepicker.setDefaults( datepicker.regional.de );
return datepicker.regional.de;
} ) );

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,11 +1,11 @@
{% load sekizai_tags staticfiles %} {% load sekizai_tags staticfiles %}
{% addtoblock "css" strip %} <link rel="stylesheet" href="{{STATIC_URL}}css/bootstrap.min.css" > {% endaddtoblock %} {% addtoblock "css" strip %} <link rel="stylesheet" href="{{STATIC_URL}}/css/bootstrap.min.css" > {% endaddtoblock %}
{% addtoblock "css" strip %} <link rel="stylesheet" href="{{STATIC_URL}}css/bootstrap-responsive.min.css" > {% endaddtoblock %} {% addtoblock "css" strip %} <link rel="stylesheet" href="{{STATIC_URL}}/css/bootstrap-responsive.min.css" > {% endaddtoblock %}
{% addtoblock "css" strip %} <link rel="stylesheet" href="{{STATIC_URL}}css/bootstrap-overrides.css"> {% endaddtoblock %} {% addtoblock "css" strip %} <link rel="stylesheet" href="{{STATIC_URL}}/css/bootstrap-overrides.css"> {% endaddtoblock %}
{% addtoblock "css" strip %} <link rel="stylesheet" href="{{STATIC_URL}}css/theme.css" type="text/css"> {% endaddtoblock %} {% addtoblock "css" strip %} <link rel="stylesheet" href="{{STATIC_URL}}/css/theme.css" type="text/css"> {% endaddtoblock %}
{% addtoblock "css" strip %} <link rel="stylesheet" href="{{STATIC_URL}}css/index.css" type="text/css" media="screen" /> {% endaddtoblock %} {% addtoblock "css" strip %} <link rel="stylesheet" href="{{STATIC_URL}}/css/index.css" type="text/css" media="screen" /> {% endaddtoblock %}
{% addtoblock "css" strip %} <link href='https://fonts.googleapis.com/css?family=Lato:300,400,700,900,300italic,400italic,700italic,900italic' rel='stylesheet' type='text/css'>{% endaddtoblock %} {% addtoblock "css" strip %} <link href='https://fonts.googleapis.com/css?family=Lato:300,400,700,900,300italic,400italic,700italic,900italic' rel='stylesheet' type='text/css'>{% endaddtoblock %}
{% addtoblock "css" %} {% addtoblock "css" %}
@ -16,12 +16,12 @@
{% addtoblock "js" strip %} <script src="{{STATIC_URL}}js/jquery-2.0.3.min.js"></script> {% endaddtoblock %} {% addtoblock "js" strip %} <script src="{{STATIC_URL}}/js/jquery-2.0.3.min.js"></script> {% endaddtoblock %}
{% addtoblock "js" strip %} <script src="{{STATIC_URL}}js/bootstrap.min.js"></script> {% endaddtoblock %} {% addtoblock "js" strip %} <script src="{{STATIC_URL}}/js/bootstrap.min.js"></script> {% endaddtoblock %}
{% addtoblock "js" strip %} <script src="{{STATIC_URL}}js/jquery.countdown.min.js"></script> {% endaddtoblock %} {% addtoblock "js" strip %} <script src="{{STATIC_URL}}/js/jquery.countdown.min.js"></script> {% endaddtoblock %}
{% addtoblock "js" strip %} <script src="{{STATIC_URL}}js/theme.js"></script> {% endaddtoblock %} {% addtoblock "js" strip %} <script src="{{STATIC_URL}}/js/theme.js"></script> {% endaddtoblock %}
{% addtoblock "js" strip %} <script src="{{STATIC_URL}}js/index-slider.js" type="text/javascript" ></script>{% endaddtoblock %} {% addtoblock "js" strip %} <script src="{{STATIC_URL}}/js/index-slider.js" type="text/javascript" ></script>{% endaddtoblock %}
{% addtoblock "js" strip %} <script src="{{STATIC_URL}}js/bindWithDelay.js" type="text/javascript" ></script>{% endaddtoblock %} {% addtoblock "js" strip %} <script src="{{STATIC_URL}}/js/bindWithDelay.js" type="text/javascript" ></script>{% endaddtoblock %}
{% addtoblock "js" %} {% addtoblock "js" %}

View File

@ -1,20 +1,20 @@
#from django.contrib import admin from django.contrib import admin
#from eventplanner.models import Event, EventParticipation from eventplanner.models import Event, EventParticipation
#
#
#class EventParticipationInline(admin.TabularInline): class EventParticipationInline(admin.TabularInline):
# model = EventParticipation model = EventParticipation
# extra = 1 extra = 1
# readonly_fields = ('user',) readonly_fields = ('user',)
# fields = ('user', 'status', 'comment',) fields = ( 'user', 'status', 'comment', )
# has_add_permission = lambda self, req: False has_add_permission = lambda self, req : False
# has_delete_permission = lambda self, req, obj: False has_delete_permission = lambda self, req, obj : False
#
# template = "eventplanner/admin_tabular.html" template = "eventplanner/admin_tabular.html"
#
#
#class EventAdmin(admin.ModelAdmin): class EventAdmin(admin.ModelAdmin):
# inlines = (EventParticipationInline,) inlines = ( EventParticipationInline, )
#
#
#admin.site.register(Event, EventAdmin) admin.site.register( Event, EventAdmin )

View File

@ -0,0 +1,112 @@
# -*- coding: 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 'Event'
db.create_table(u'eventplanner_event', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('type', self.gf('django.db.models.fields.CharField')(default='Reh', max_length=6)),
('short_desc', self.gf('django.db.models.fields.CharField')(max_length=100, null=True, blank=True)),
('location', self.gf('django.db.models.fields.TextField')()),
('map_location', self.gf('location_field.models.PlainLocationField')(max_length=63)),
('desc', self.gf('django.db.models.fields.TextField')(blank=True)),
('date', self.gf('django.db.models.fields.DateField')()),
('time', self.gf('django.db.models.fields.TimeField')(null=True, blank=True)),
('meeting_time', self.gf('django.db.models.fields.TimeField')(null=True, blank=True)),
('end_date', self.gf('django.db.models.fields.DateField')(null=True)),
))
db.send_create_signal(u'eventplanner', ['Event'])
# Adding model 'EventParticipation'
db.create_table(u'eventplanner_eventparticipation', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('event', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['eventplanner.Event'])),
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
('status', self.gf('django.db.models.fields.CharField')(default='?', max_length=3)),
('comment', self.gf('django.db.models.fields.CharField')(max_length=64, blank=True)),
))
db.send_create_signal(u'eventplanner', ['EventParticipation'])
# Adding unique constraint on 'EventParticipation', fields ['event', 'user']
db.create_unique(u'eventplanner_eventparticipation', ['event_id', 'user_id'])
def backwards(self, orm):
# Removing unique constraint on 'EventParticipation', fields ['event', 'user']
db.delete_unique(u'eventplanner_eventparticipation', ['event_id', 'user_id'])
# Deleting model 'Event'
db.delete_table(u'eventplanner_event')
# Deleting model 'EventParticipation'
db.delete_table(u'eventplanner_eventparticipation')
models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'eventplanner.event': {
'Meta': {'object_name': 'Event'},
'date': ('django.db.models.fields.DateField', [], {}),
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'end_date': ('django.db.models.fields.DateField', [], {'null': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'location': ('django.db.models.fields.TextField', [], {}),
'map_location': ('location_field.models.PlainLocationField', [], {'max_length': '63'}),
'meeting_time': ('django.db.models.fields.TimeField', [], {'null': 'True', 'blank': 'True'}),
'participants': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.User']", 'through': u"orm['eventplanner.EventParticipation']", 'symmetrical': 'False'}),
'short_desc': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'time': ('django.db.models.fields.TimeField', [], {'null': 'True', 'blank': 'True'}),
'type': ('django.db.models.fields.CharField', [], {'default': "'Reh'", 'max_length': '6'})
},
u'eventplanner.eventparticipation': {
'Meta': {'unique_together': "(('event', 'user'),)", 'object_name': 'EventParticipation'},
'comment': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
'event': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['eventplanner.Event']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'status': ('django.db.models.fields.CharField', [], {'default': "'?'", 'max_length': '3'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
}
}
complete_apps = ['eventplanner']

View File

View File

@ -1,56 +1,62 @@
from django.db import models from django.db import models
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.contrib.auth.models import User, Permission from django.contrib.auth.models import User, Permission
from django.db.models import Q
from datetime import datetime from datetime import datetime
from location_field.models import PlainLocationField from location_field.models import PlainLocationField
from django.db.models import Q
from django.dispatch import Signal
class NoNextEventException(Exception):
class NoNextEventException( Exception ):
def __str__(self): def __str__(self):
return "No event scheduled for the future" return ("No event scheduled for the future")
class Event(models.Model): class Event ( models.Model ):
EVENT_TYPES = ( EVENT_TYPES = (
('Reh', _('Rehearsal')), ( 'Reh', _('Rehearsal') ),
('Conc', _('Concert')), ( 'Conc', _('Concert') ),
('Party', _('Party')), ( 'Party', _('Party') ),
('Travel', _('Travel')), ( 'Travel', _('Travel') ),
('Option', _('Option')), ( 'Option', _('Option') ),
) )
type = models.CharField(max_length=6, choices=EVENT_TYPES, default='Reh', verbose_name=_("type")) type = models.CharField( max_length=6, choices=EVENT_TYPES, default='Reh', verbose_name= _("type") )
short_desc = models.CharField(null=True, max_length=100, blank=True, verbose_name=_("Short Description")) short_desc = models.CharField( null=True, max_length=100, blank = True, verbose_name= _("Short Description") )
location = models.TextField(blank=True, verbose_name=_("location")) location = models.TextField( blank=True, verbose_name=_("location") )
map_location = PlainLocationField(blank=True, based_field=location, zoom=7, verbose_name=_("Location on map")) map_location = PlainLocationField(blank=True, based_field = location, zoom=7, verbose_name=_("Location on map") )
desc = models.TextField(blank=True, verbose_name=_("description")) desc = models.TextField( blank=True, verbose_name=_("description") )
date = models.DateField(verbose_name=_("date")) date = models.DateField( verbose_name= _("date") )
time = models.TimeField(null=True, blank=True, verbose_name=_("time")) time = models.TimeField( null=True, blank=True, verbose_name = _("time") )
meeting_time = models.TimeField(null=True, blank=True, verbose_name=_("meeting_time")) meeting_time = models.TimeField( null=True, blank=True, verbose_name = _("meeting_time") )
end_date = models.DateField(null=True, blank=True, verbose_name=_("End Date")) end_date = models.DateField( null=True, blank = True, verbose_name = _("End Date") )
participants = models.ManyToManyField(User, through='EventParticipation', verbose_name=_("participants")) participants = models.ManyToManyField( User, through='EventParticipation', verbose_name=_("participants") )
def __unicode__(self): def __unicode__(self):
return self.title return self.title
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
# Call the "real" save() method # Call the "real" save() method
super(Event, self).save(*args, **kwargs) super(Event, self).save(*args, **kwargs)
# Create a "Don't Know" participation for each Musician # Create a "Don't Know" participation for each Musician
for u in User.objects.all(): for u in User.objects.all():
if not u in self.participants.all(): if not u in self.participants.all():
EventParticipation.objects.create(event=self, user=u, status='-', comment='') EventParticipation.objects.create( event=self, user = u, status='?', comment = '' )
@property @property
def title(self): def title(self):
res = self.get_type_display() res = self.get_type_display()
if self.short_desc: if ( self.short_desc ):
res += " (" + self.short_desc + ") " res += " (" + self.short_desc + ") "
return res return res
@ -65,44 +71,43 @@ class Event(models.Model):
@property @property
def displaydatetime(self): def displaydatetime(self):
if not self.displaytime == None: if not self.displaytime == None:
return datetime.combine(self.date, self.displaytime) return datetime.combine( self.date, self.displaytime )
else: else:
return datetime.combine(self.date, datetime.min.time()) return datetime.combine( self.date, datetime.min.time() )
@staticmethod @staticmethod
def getNextEvent(eventType="", includePreviousFromToday=True): def getNextEvent( eventType = "", includePreviousFromToday = True ):
"""Return the next event, of the given type. If type is the empty string the next event is returned """Return the next event, of the given type. If type is the empty string the next event is returned
regardless of its type. regardless of its type.
if includePreviousFromToday the nextEvent returned could also have been today with a startime < now """ if includePreviousFromToday the nextEvent returned could also have been today with a startime < now """
if includePreviousFromToday: if includePreviousFromToday:
if eventType == "": if eventType == "":
nextEvents = Event.objects.filter(date__gte=datetime.now()).order_by('date')[:1] nextEvents = Event.objects.filter( date__gte = datetime.now() ).order_by('date')[:1]
else: else:
nextEvents = Event.objects.filter(date__gte=datetime.now(), type=eventType).order_by('date')[:1] nextEvents = Event.objects.filter( date__gte = datetime.now(), type = eventType ).order_by('date')[:1]
if len(nextEvents) == 0: if len( nextEvents ) == 0:
raise NoNextEventException() raise NoNextEventException()
return nextEvents[0] return nextEvents[0]
else: else:
maximalNumberOfEventsOnSameDay = 4 maximalNumberOfEventsOnSameDay = 4
nextEvents = [] nextEvents = []
if eventType == "": if eventType =="":
nextEvents = Event.objects.filter(date__gte=datetime.now()).order_by('date')[ nextEvents = Event.objects.filter( date__gte = datetime.now() ).order_by('date')[:maximalNumberOfEventsOnSameDay]
:maximalNumberOfEventsOnSameDay]
else: else:
nextEvents = Event.objects.filter(date__gte=datetime.now(), type=eventType).order_by('date')[ nextEvents = Event.objects.filter( date__gte = datetime.now(), type = eventType ).order_by('date')[:maximalNumberOfEventsOnSameDay]
:maximalNumberOfEventsOnSameDay]
if len(nextEvents) == 0: if len(nextEvents) == 0:
raise NoNextEventException() raise NoNextEventException()
i = 0 i = 0
nextEvent = nextEvents[0] nextEvent = nextEvents[0]
# nextEvent is not necessarily events[0] since events[0] may have been previously today # nextEvent is not necessarily events[0] since events[0] may have been previously today
while nextEvent.displaydatetime < datetime.now(): while nextEvent.displaydatetime < datetime.now():
if len(nextEvents) <= i: if len(nextEvents ) <= i:
raise NoNextEventException() raise NoNextEventException()
else: else:
i += 1 i += 1
@ -111,69 +116,76 @@ class Event(models.Model):
return nextEvent return nextEvent
class EventParticipation(models.Model):
OPTIONS = (('?', _('?')),
('Yes', _('Yes')),
('No', _('No')),
('-', _('-'))
)
event = models.ForeignKey(Event, verbose_name=_("event"), on_delete=models.PROTECT) class EventParticipation( models.Model ):
user = models.ForeignKey(User, verbose_name=_("user"), on_delete=models.PROTECT) OPTIONS = ( ('?' , _('?' )),
status = models.CharField(max_length=3, choices=OPTIONS, default='?', verbose_name=_("status")) ('Yes', _('Yes')),
comment = models.CharField(max_length=64, blank=True, verbose_name=_("comment")) ('No' , _('No' )),
('-' , _( '-' ))
)
event = models.ForeignKey( Event, verbose_name=_("event") )
user = models.ForeignKey( User, verbose_name=_("user") )
status = models.CharField ( max_length=3, choices = OPTIONS, default='?', verbose_name=_("status") )
comment = models.CharField ( max_length=64, blank=True, verbose_name=_("comment") )
def get_username(self): def get_username(self):
return self.user.username return self.user.username
def save(self, *args, **kwargs): def save( self, *args, **kwargs ):
prev = EventParticipation.objects.filter(event=self.event, user=self.user) prev = EventParticipation.objects.filter( event = self.event, user = self.user )
if len(prev) == 0: if len(prev) == 0:
super(EventParticipation, self).save(*args, **kwargs) super(EventParticipation,self).save( *args,**kwargs)
else: else:
prev = prev[0] prev = prev[0]
if prev.status != self.status or prev.comment != self.comment: if prev.status != self.status or prev.comment != self.comment:
super(EventParticipation, self).save(*args, **kwargs) super(EventParticipation,self).save( *args,**kwargs)
@staticmethod @staticmethod
def hasUserSetParticipationForAllEvents(user): def hasUserSetParticipationForAllEvents( user ):
if not EventParticipation.isMember(user): if not EventParticipation.isMember(user):
return True return True
futurePart = EventParticipation.objects.filter(event__date__gte=datetime.now()) futurePart = EventParticipation.objects.filter( event__date__gte = datetime.now() )
notYetEntered = futurePart.filter(user=user).filter(status='-') notYetEntered = futurePart.filter( user = user ).filter( status = '-' )
if len(notYetEntered) > 0: if len( notYetEntered ) > 0:
return False return False
else: else:
return True return True
@staticmethod @staticmethod
def isMember(user): def isMember( user ):
return user.has_perm('eventplanner.member') return user.has_perm('eventplanner.member')
@staticmethod @staticmethod
def isAdmin(user): def isAdmin( user ):
return user.has_perm('eventplanner.admin') return user.has_perm('eventplanner.admin')
@staticmethod @staticmethod
def members(): def members():
perm = Permission.objects.get(codename='member') perm = Permission.objects.get( codename='member' )
f = User.objects.filter(Q(groups__permissions=perm) | Q(user_permissions=perm)).distinct() f = User.objects.filter(Q(groups__permissions=perm) | Q(user_permissions=perm) ).distinct()
return f.order_by('musician__position') return f.order_by('musician__position')
@staticmethod @staticmethod
def get_or_create(user, event): def get_or_create( user , event ):
try: try:
result = EventParticipation.objects.get(event=event, user=user) result = EventParticipation.objects.get( event = event, user = user )
except EventParticipation.DoesNotExist: except EventParticipation.DoesNotExist:
result = EventParticipation.objects.create(event=event, user=user, status='-', comment='') result = EventParticipation.objects.create( event = event, user = user, status='-', comment = '' )
return result return result
class Meta: class Meta:
unique_together = ("event", "user") unique_together = ("event", "user")
permissions = ( permissions = (
("admin", _("Admin")), ("admin", _("Admin") ),
("member", _("Member")), ("member", _("Member") ),
) )

View File

@ -1,11 +1,13 @@
from rest_framework import serializers from rest_framework import serializers
from .models import EventParticipation, Event from models import EventParticipation
class ParticipationSerializer(serializers.ModelSerializer): class ParticipationSerializer(serializers.ModelSerializer):
event = serializers.PrimaryKeyRelatedField(many=False, read_only=False, queryset=Event.objects.all()) event = serializers.PrimaryKeyRelatedField( many=False, read_only = False )
user = serializers.Field(source='get_username') user = serializers.Field( source='get_username' )
status = serializers.CharField(source='status', required=False) status = serializers.CharField( source='status', required=False )
def get_identity(self, data): def get_identity(self, data):
""" This hook is required for bulk update. """ """ This hook is required for bulk update. """
@ -17,3 +19,6 @@ class ParticipationSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = EventParticipation model = EventParticipation
fields = ('event', 'user', 'status', 'comment') fields = ('event', 'user', 'status', 'comment')

View File

@ -1,36 +1,38 @@
from datetime import datetime from datetime import datetime
from .models import Event, EventParticipation, NoNextEventException from models import Event, EventParticipation, NoNextEventException
from musicians.models import Musician from musicians.models import Musician
def addEventCountdownForNextEventToContext(context, username, eventType=""):
def addEventCountdownForNextEventToContext( context, username, eventType = "" ):
"""Returns an object that has to be added to the render context on the page where the countdown """Returns an object that has to be added to the render context on the page where the countdown
should be displayed . The username is required to also supply participation information.""" should be displayed . The username is required to also supply participation information."""
try: try:
nextEvent = Event.getNextEvent(eventType, False) nextEvent = Event.getNextEvent( eventType, False )
except NoNextEventException: except NoNextEventException:
return return
countdown = dict() countdown = dict()
if EventParticipation.isMember(username): if EventParticipation.isMember( username ):
part = EventParticipation.objects.filter(user=username).filter(event=nextEvent) part = EventParticipation.objects.filter( user = username ).filter( event = nextEvent )
countdown['participation'] = part[0].status countdown['participation'] = part[0].status
eventTime = nextEvent.displaydatetime eventTime = nextEvent.displaydatetime
countdown['event'] = nextEvent countdown['event'] = nextEvent
countdown['epoch'] = int((eventTime - datetime.now()).total_seconds() * 1000) countdown['epoch'] = int( (eventTime - datetime.now() ).total_seconds() * 1000 )
context["countdown"] = countdown context["countdown"] = countdown
def addEventRouteForNextEventToContext(context, username, eventType=""): def addEventRouteForNextEventToContext( context, username, eventType = ""):
"""Returns an object that has to be added to the render context on the page where the route """Returns an object that has to be added to the render context on the page where the route
should be displayed . The starting address of the route will be the home of the specified user""" should be displayed . The starting address of the route will be the home of the specified user"""
try: try:
nextEvent = Event.getNextEvent(eventType, True) nextEvent = Event.getNextEvent( eventType, True )
except NoNextEventException: except NoNextEventException:
return return
@ -38,13 +40,16 @@ def addEventRouteForNextEventToContext(context, username, eventType=""):
routeInfo['event'] = nextEvent routeInfo['event'] = nextEvent
musician = Musician.objects.get(user=username); musician = Musician.objects.get( user = username );
routeInfo['origin'] = musician.street + ", " + str(musician.zip_code) + " " + musician.city routeInfo['origin'] = musician.street + ", " + str( musician.zip_code ) + " " + musician.city
if nextEvent.map_location: if nextEvent.map_location:
# map_location has format "lat,longitute,zoomlevel" # map_location has format "lat,longitute,zoomlevel"
routeInfo['destination'] = ",".join(nextEvent.map_location.split(",")[:2]) routeInfo['destination'] = ",".join( nextEvent.map_location.split(",")[:2] )
else: else:
routeInfo['destination'] = nextEvent.location routeInfo['destination'] = nextEvent.location
context["route"] = routeInfo context["route"] = routeInfo

View File

@ -2,8 +2,8 @@
{% addtoblock "css" strip %}<link rel="stylesheet" type="text/css" href="{{STATIC_URL}}css/lib/animate.css" media="screen, projection">{% endaddtoblock %} {% addtoblock "css" strip %}<link rel="stylesheet" type="text/css" href="{{STATIC_URL}}/css/lib/animate.css" media="screen, projection">{% endaddtoblock %}
{% addtoblock "css" strip %}<link rel="stylesheet" href="{{STATIC_URL}}css/coming-soon.css" type="text/css" media="screen" />{% endaddtoblock %} {% addtoblock "css" strip %}<link rel="stylesheet" href="{{STATIC_URL}}/css/coming-soon.css" type="text/css" media="screen" />{% endaddtoblock %}
{% if countdown %} {% if countdown %}

View File

@ -7,6 +7,7 @@
{% block content %} {% block content %}
{{ form.media }}
<div class="container"> <div class="container">
<div class="row"> <div class="row">
@ -25,28 +26,30 @@
<!-- Datepicker --> <!-- Datepicker -->
{% addtoblock "css" strip %}
<link rel="stylesheet" href="{{STATIC_URL}}css/jquery-ui-1.12.1.min.css" type="text/css" media="screen" /> {% addtoblock "css" strip %}<link rel="stylesheet" href="{{STATIC_URL}}/css/datepicker.css" type="text/css" media="screen" /> {% endaddtoblock %}
{% endaddtoblock %} {% addtoblock "css" strip %}<link rel="stylesheet" href="{{STATIC_URL}}/css/timepicker.css" type="text/css" media="screen" /> {% endaddtoblock %}
{% addtoblock "css" strip %}<link rel="stylesheet" href="{{STATIC_URL}}/css/jquery-ui-1.8.21.custom.css" type="text/css" media="screen" /> {% endaddtoblock %}
{% addtoblock "js" %} {% addtoblock "js" %}
<script src="{{STATIC_URL}}js/jquery-ui-1.12.1.min.js"></script> <script src="{{STATIC_URL}}/js/bootstrap-timepicker.js"></script>
<script src="{{STATIC_URL}}js/bootstrap-datepicker.de.js"></script> <script src="{{STATIC_URL}}/js/bootstrap-datepicker.js"></script>
<script src="{{STATIC_URL}}/js/bootstrap-datepicker.de.js"></script>
<script> <script>
$(document).ready(function(){ $(document).ready(function(){
$.datepicker.setDefaults( $('.dateinput').datepicker({
$.extend( format: "dd.mm.yyyy",
{'dateFormat':'dd-mm-yy'}, weekStart: 1,
$.datepicker.regional['de'] todayBtn: "linked",
) language: "de",
); todayHighlight: true,
startDate: "{% now "SHORT_DATE_FORMAT" %}",
});
$('.dateinput').datepicker();
/*
$('.timeinput').addClass('input-small').wrap('<div class="input-append bootstrap-timepicker">') $('.timeinput').addClass('input-small').wrap('<div class="input-append bootstrap-timepicker">')
$(".input-append").append( '<span class="add-on"><i class="icon-time"></i></span>' ) $(".input-append").append( '<span class="add-on"><i class="icon-time"></i></span>' )
@ -56,7 +59,6 @@ $(document).ready(function(){
showMeridian: false, showMeridian: false,
defaultTime: false defaultTime: false
}); });
*/
$('form').submit(function() { $('form').submit(function() {
if ( $("#id_type").val() != "Option" && $("#id_location").val().trim() == "" ) { if ( $("#id_type").val() != "Option" && $("#id_location").val().trim() == "" ) {
@ -132,6 +134,7 @@ $(document).ready(function(){
{% endblock %} {% endblock %}

View File

@ -130,7 +130,7 @@
$(function(){ $(function(){
$(".event-comment").bindWithDelay("keyup", function() { $(".event-comment").bindWithDelay("keypress", function() {
$("#saving").html("Speichere.."); $("#saving").html("Speichere..");
putObject = [ { "event": $(this).data("event-id"), putObject = [ { "event": $(this).data("event-id"),
@ -181,6 +181,14 @@
<div class="span12"> <div class="span12">
<div class="alert alert-info">
Es gibt jetzt einen vierten Zustand "nicht eingetragen", angezeigt durch nur
blaue Buttons.<br>
"?" bedeutet jetzt: Ich habe mich eingetragen weiss aber noch nicht ob ich komme.
Bitte nur selten benutzen!
</div>
<div class="box-content"> <div class="box-content">
<table id="eventTable" class="table table-striped"> <table id="eventTable" class="table table-striped">

View File

@ -28,8 +28,6 @@
.with_comment { .with_comment {
font-style: italic; font-style: italic;
font-weight: 900;
font-size: 11px;
} }
.usernameHeader { .usernameHeader {
font-size:10px; font-size:10px;
@ -143,6 +141,13 @@
<h2>Termine</h2> <h2>Termine</h2>
<div class="alert alert-info">
Es gibt jetzt einen vierten Zustand "nicht eingetragen", angezeigt durch "-".<br>
"?" bedeutet jetzt: Ich habe mich eingetragen weiss aber noch nicht ob ich komme.
Bitte nur selten benutzen!
</div>
<div class="box-content"> <div class="box-content">
<table class="table table-striped"> <table class="table table-striped">
@ -205,16 +210,11 @@
<span class="badge badge-important eventButton" title="{{p.comment}}" data-status="{{p.status}}"> <span class="badge badge-important eventButton" title="{{p.comment}}" data-status="{{p.status}}">
<span class="text {% if p.comment %}with_comment{% endif %}">Nein</span> <span class="text {% if p.comment %}with_comment{% endif %}">Nein</span>
</span> </span>
{% elif p.status == "?" %} {% else %}
<span class="badge badge-warning eventButton" title="{{p.comment}}" data-status="{{p.status}}"> <span class="badge badge-warning eventButton" title="{{p.comment}}" data-status="{{p.status}}">
<span class="text {% if p.comment %}with_comment{% endif %}">?</span> <span class="text {% if p.comment %}with_comment{% endif %}">?</span>
</span> </span>
{% else %}
<span class="badge eventButton" title="{{p.comment}}" data-status="{{p.status}}">
<span class="text {% if p.comment %}with_comment{% endif %}">-</span>
</span>
{% endif %} {% endif %}
</td> </td>
{% endif %} {% endif %}

View File

@ -17,8 +17,8 @@
{% if route %} {% if route %}
{% addtoblock "css" strip %}<link rel="stylesheet" href="{{STATIC_URL}}css/concert_route.css" type="text/css" media="screen" />{% endaddtoblock %} {% addtoblock "css" strip %}<link rel="stylesheet" href="{{STATIC_URL}}/css/concert_route.css" type="text/css" media="screen" />{% endaddtoblock %}
{% addtoblock "js" strip %}<script type="text/javascript" src="//maps.google.com/maps/api/js?key={{GOOGLE_MAPS_API_KEY}}&amp;sensor=false&amp;language=de"></script>{% endaddtoblock %} {% addtoblock "js" strip %}<script type="text/javascript" src="//maps.google.com/maps/api/js?sensor=false&amp;language=de"></script>{% endaddtoblock %}
{% addtoblock "js" %} {% addtoblock "js" %}

View File

@ -1,15 +1,18 @@
from django.conf.urls import url from django.conf.urls import patterns, url
from django.contrib.auth.decorators import permission_required from django.contrib.auth.decorators import permission_required
from eventplanner.views import events_grid, eventplanning, event_api, EventUpdate, EventCreate, deleteEvent
urlpatterns = [ from eventplanner.views import events_grid, eventplanning,event_api,EventUpdate,EventCreate,deleteEvent
url(r'^$', eventplanning),
url(r'^grid$', events_grid),
url(r'^planning$', eventplanning), urlpatterns = patterns('',
url(r'^(?P<pk>\d+)$', permission_required('eventplanner.change_event')(EventUpdate.as_view())), url(r'^$', eventplanning ),
url(r'^add$', permission_required('eventplanner.add_event')(EventCreate.as_view())), url(r'^grid$', events_grid ),
url(r'^(?P<pk>\d+)/delete$', permission_required('eventplanner.delete_event')(deleteEvent)), url(r'^planning$', eventplanning ),
url(r'^api/', event_api, name="event_api"), url(r'^(?P<pk>\d+)$', permission_required('eventplanner.change_event')( EventUpdate.as_view() ) ),
url(r'^api/(\w+)/$', event_api, name="event_api_per_user"), url(r'^add$', permission_required('eventplanner.add_event' )( EventCreate.as_view() ) ),
url(r'^api/(\w+)/(\d+)$', event_api, name="event_api_per_user_event"), url(r'^(?P<pk>\d+)/delete$', permission_required('eventplanner.delete_event')( deleteEvent ) ),
] url(r'^api/', event_api, name="event_api" ),
url(r'^api/(\w+)/$', event_api, name="event_api_per_user" ),
url(r'^api/(\w+)/(\d+)$', event_api, name="event_api_per_user_event" ),
)

View File

@ -1,11 +1,12 @@
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from django.http import HttpResponse from django.http import HttpResponse
from django.forms.models import ModelForm from django.forms.models import ModelForm
from django.forms import TextInput, TimeInput from django.forms import TextInput
from .models import Event, EventParticipation from models import Event, EventParticipation
from .serializers import ParticipationSerializer from serializers import ParticipationSerializer
import datetime import datetime
@ -13,6 +14,7 @@ from rest_framework.decorators import api_view
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework import status from rest_framework import status
from crispy_forms.helper import FormHelper from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit from crispy_forms.layout import Submit
@ -20,75 +22,78 @@ from crispy_forms.layout import Submit
# ---------------------------------------- API --------------------------------------------------------- # ---------------------------------------- API ---------------------------------------------------------
@api_view(['GET', 'PUT']) @api_view( ['GET', 'PUT'] )
def event_api(request, username=None, eventId=None): def event_api( request, username = None, eventId = None ):
try: try:
participationQs = EventParticipation.objects.filter(event__date__gte=datetime.date.today()) participationQs = EventParticipation.objects.filter( event__date__gte = datetime.date.today() )
if username: if username:
participationQs = EventParticipation.objects.filter(user__username=username) participationQs = EventParticipation.objects.filter( user__username = username )
if eventId: if eventId:
participationQs = participationQs.filter(event__pk=eventId) participationQs = participationQs.filter( event__pk = eventId )
except EventParticipation.DoesNotExist: except EventParticipation.DoesNotExist:
return HttpResponse(status=404) return HttpResponse( status=404 )
if request.method == 'GET': if request.method == 'GET':
serializer = ParticipationSerializer(participationQs) serializer = ParticipationSerializer( participationQs )
return Response(serializer.data) return Response( serializer.data )
elif request.method == 'PUT': elif request.method == 'PUT':
serializer = ParticipationSerializer(participationQs, data=request.DATA, many=True) serializer = ParticipationSerializer ( participationQs, data = request.DATA, many=True )
if serializer.is_valid(): if serializer.is_valid():
for serializedObject in serializer.object: for serializedObject in serializer.object:
if not (EventParticipation.isMember(request.user) or EventParticipation.isAdmin(request.user)): if not ( EventParticipation.isMember( request.user ) or EventParticipation.isAdmin( request.user ) ):
return Response(status=status.HTTP_403_FORBIDDEN) return Response( status = status.HTTP_403_FORBIDDEN )
if serializedObject.user != request.user: if serializedObject.user != request.user:
if not EventParticipation.isAdmin(request.user): if not EventParticipation.isAdmin( request.user ):
return Response(status=status.HTTP_403_FORBIDDEN) return Response( status = status.HTTP_403_FORBIDDEN )
serializer.save() serializer.save()
return Response(serializer.data) return Response( serializer.data )
else: else:
return Response(status=status.HTTP_400_BAD_REQUEST) return Response( status = status.HTTP_400_BAD_REQUEST )
# ------------------------------------ Normal Views ---------------------------------------------------- # ------------------------------------ Normal Views ----------------------------------------------------
def eventplanning(request): def eventplanning( request ):
""" """
View for a specific user, to edit his events View for a specific user, to edit his events
""" """
# non-members see the grid - but cannot edit anything # non-members see the grid - but cannot edit anything
if not EventParticipation.isMember(request.user): if not EventParticipation.isMember( request.user ):
return events_grid(request) return events_grid(request)
# All events in the future sorted by date # All events in the future sorted by date
all_future_events = list(Event.objects.filter(date__gte=datetime.date.today()).order_by('date')) all_future_events = list ( Event.objects.filter( date__gte = datetime.date.today() ).order_by( 'date') )
for e in all_future_events: for e in all_future_events:
e.participation = EventParticipation.get_or_create(event=e, user=request.user) e.participation = EventParticipation.get_or_create( event = e, user = request.user )
context = {'events': all_future_events} context = { 'events' : all_future_events }
return render(request, 'eventplanner/eventplanning_view.html', context) return render ( request, 'eventplanner/eventplanning_view.html', context )
def events_grid(request):
usernames = [u.username for u in EventParticipation.members()]
all_future_events = list(Event.objects.filter(date__gte=datetime.date.today()).order_by('date')) def events_grid( request ):
usernames = [ u.username for u in EventParticipation.members() ]
all_future_events = list ( Event.objects.filter( date__gte = datetime.date.today() ).order_by( 'date') )
for e in all_future_events: for e in all_future_events:
e.participation = [EventParticipation.get_or_create(event=e, user=u) for u in EventParticipation.members()] e.participation = [ EventParticipation.get_or_create( event = e, user = u ) for u in EventParticipation.members() ]
context = {'events': all_future_events, context = { 'events': all_future_events,
'usernames': usernames} 'usernames' : usernames }
return render(request, 'eventplanner/events_grid.html', context) return render ( request, 'eventplanner/events_grid.html', context )
def deleteEvent(request, pk):
Event.objects.get(pk=pk).delete()
return redirect(events_grid)
def deleteEvent( request, pk ):
Event.objects.get( pk = pk ).delete()
return redirect( events_grid )
# ------------------------------------ Detail Views ---------------------------------------------------- # ------------------------------------ Detail Views ----------------------------------------------------
@ -97,27 +102,24 @@ from django.views.generic.edit import UpdateView, CreateView
from location_field.widgets import LocationWidget from location_field.widgets import LocationWidget
class EventForm( ModelForm ):
class EventForm(ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.helper = FormHelper() self.helper = FormHelper()
self.helper.form_class = 'form-horizontal' self.helper.form_class = 'form-horizontal'
self.helper.add_input(Submit('submit', 'Speichern')) self.helper.add_input(Submit('submit', 'Speichern'))
super(EventForm, self).__init__(*args, **kwargs) return super(EventForm, self).__init__(*args, **kwargs)
class Meta: class Meta:
model = Event model = Event
fields = ['type', 'short_desc', 'date', 'end_date', 'time', 'meeting_time', 'location', 'map_location', fields= [ 'type', 'short_desc', 'date', 'end_date', 'time', 'meeting_time', 'location', 'map_location', 'desc', ]
'desc', ]
widgets = { widgets = {
'time': TimeInput(format='%H:%M'), 'location' : TextInput(),
'location': TextInput(), 'map_location' : LocationWidget(),
'map_location': LocationWidget(),
} }
class EventUpdate(UpdateView): class EventUpdate( UpdateView ):
form_class = EventForm form_class = EventForm
model = Event model = Event
template_name_suffix = "_update_form" template_name_suffix = "_update_form"
@ -129,7 +131,7 @@ class EventUpdate(UpdateView):
return context return context
class EventCreate(CreateView): class EventCreate( CreateView ):
form_class = EventForm form_class = EventForm
model = Event model = Event
template_name_suffix = "_update_form" template_name_suffix = "_update_form"
@ -139,3 +141,8 @@ class EventCreate(CreateView):
context = super(CreateView, self).get_context_data(**kwargs) context = super(CreateView, self).get_context_data(**kwargs)
context['viewtype'] = "create" context['viewtype'] = "create"
return context return context

View File

@ -0,0 +1,2 @@
import signals

View File

@ -3,409 +3,373 @@ import httplib2
import datetime import datetime
import time import time
from eventplanner.models import Event, EventParticipation from eventplanner.models import Event, EventParticipation
from eventplanner_gcal.models import GCalMapping, GCalPushChannel, UserGCalCoupling from eventplanner_gcal.models import GCalMapping, GCalPushChannel,UserGCalCoupling
# noinspection PyUnresolvedReferences,PyUnresolvedReferences
from apiclient.http import BatchHttpRequest from apiclient.http import BatchHttpRequest
from builtins import str as text # python2 and python3
from django.contrib.auth.models import User
from django.conf import settings from django.conf import settings
from pprint import pprint
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# --------------------- Authentication using oauth2 --------------------------------------------
# ---------------------------------- Authentication using oauth2 ----------------------------------------------------- def createGCalServiceObject():
def create_gcal_service_object():
"""Creates a Google API service object. This object is required whenever a Google API call is made""" """Creates a Google API service object. This object is required whenever a Google API call is made"""
from oauth2client.file import Storage from oauth2client.file import Storage
# noinspection PyUnresolvedReferences
from apiclient.discovery import build from apiclient.discovery import build
gcal_settings = settings.GCAL_COUPLING gcal_settings = settings.GCAL_COUPLING
storage = Storage(gcal_settings['credentials_file']) storage = Storage( gcal_settings['credentials_file'] )
credentials = storage.get() credentials = storage.get()
logger.debug("Credentials", credentials) if credentials is None or credentials.invalid == True:
if credentials is None or credentials.invalid is True:
# flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
logger.error("Unable to initialize Google Calendar coupling. Check your settings!") logger.error("Unable to initialize Google Calendar coupling. Check your settings!")
return None return None
http = httplib2.Http() http = httplib2.Http()
http = credentials.authorize(http) http = credentials.authorize( http )
res = build(serviceName='calendar', version='v3', res = build( serviceName='calendar', version='v3',
http=http, developerKey=gcal_settings['developerKey']) http=http, developerKey=gcal_settings['developerKey'] )
if res is None: if res is None:
logger.error("Authentication at Google API failed. Check your settings!") logger.error( "Authentication at google API failed. Check your settings!" )
return res return res
def get_service_object(): def getServiceObject():
if get_service_object.__serviceObject is None: if getServiceObject.__serviceObject is None:
get_service_object.__serviceObject = create_gcal_service_object() getServiceObject.__serviceObject = createGCalServiceObject()
return get_service_object.__serviceObject return getServiceObject.__serviceObject
getServiceObject.__serviceObject = None
get_service_object.__serviceObject = None
# --------------------- Building GCal event representation ------------------------------------
# --------------------- Building GCal event representation ---------------------------------------------------------- def buildGCalAttendeesObj( event ):
"""Builds a attendees object that is inserted into the GCal event.
Attendees are all users that have a google mail address. """
def build_gcal_attendees_obj(event):
"""Builds an attendees object that is inserted into the GCal event.
Attendees are all users that have a google mail address."""
result = [] result = []
for userMapping in UserGCalCoupling.objects.all(): for userMapping in UserGCalCoupling.objects.all():
u = userMapping.user u = userMapping.user
participation = EventParticipation.get_or_create( u, event )
# No get or create here, since a create would trigger another synchronization
# participation = EventParticipation.get_or_create( u, event )
try:
participation = EventParticipation.objects.get(event=event, user=u)
local_status = participation.status
local_comment = participation.comment
except EventParticipation.DoesNotExist:
local_status = "-"
local_comment = ""
status = "needsAction" status = "needsAction"
if local_status == "?": if participation.status == "?" : status = "tentative"
status = "tentative" if participation.status == 'Yes': status = "accepted"
elif local_status == 'Yes': if participation.status == 'No' : status = "declined"
status = "accepted"
elif local_status == 'No':
status = "declined"
o = { o = {
'id': userMapping.email, 'id': userMapping.email,
'email': userMapping.email, 'email': userMapping.email,
'displayName': u.username, 'displayName': u.username,
'comment': local_comment, 'comment': participation.comment,
'responseStatus': status, 'responseStatus': status,
} }
result.append(o) result.append( o )
return result return result
def build_gcal_event(event, timezone="Europe/Berlin"):
def buildGCalEvent( event, timezone="Europe/Berlin" ):
""" Builds a GCal event using a local event. """ """ Builds a GCal event using a local event. """
def create_date_time_obj(date, time_obj): def createDateTimeObj( date, time ):
if time_obj is None: if time is None:
return {'date': text(date), 'timeZone': timezone} return { 'date': unicode(date), 'timeZone': timezone }
else: else:
return {'dateTime': text(date) + 'T' + text(time_obj), 'timeZone': timezone} return { 'dateTime': unicode(date) + 'T' + unicode(time) , 'timeZone': timezone }
start_date = event.date startDate = event.date
end_date = event.end_date endDate = event.end_date
if end_date is None: if endDate is None: endDate = startDate
end_date = start_date
start_time = event.meeting_time startTime = event.meeting_time
if start_time is None: if startTime is None: startTime = event.time
start_time = event.time
if start_time is None: if startTime is None:
end_time = None endTime = None
else: else:
end_time = datetime.time(22, 30) endTime = datetime.time( 22, 30 )
g_location = text(event.location)
if event.map_location:
# Map location has the following format: latitude,longitude,zoomlevel
# the first two are needed
s = event.map_location.split(",")
g_location = text("%s,%s" % (s[0], s[1]))
return { return {
'summary': text(settings.GCAL_COUPLING['eventPrefix'] + event.title), 'summary': unicode(settings.GCAL_COUPLING['eventPrefix'] + event.title),
'description': text(event.desc), 'description': unicode(event.desc),
'location': g_location, 'location': unicode(event.location),
'start': create_date_time_obj(start_date, start_time), 'start': createDateTimeObj( startDate, startTime ),
'end': create_date_time_obj(end_date, end_time), 'end' : createDateTimeObj( endDate, endTime ),
'extendedProperties': { 'extendedProperties': {
'private': { 'private': {
'blechreizEvent': 'true', 'blechreizEvent': 'true',
'blechreizID': event.id, 'blechreizID': event.id,
} }
}, },
'attendees': build_gcal_attendees_obj(event), 'attendees': buildGCalAttendeesObj( event ),
} }
# ------------------------------ Callback Functions -------------------------------------------------------------------
def on_gcal_event_created(_, response, exception=None): # ------------------------------ GCal Api Calls -------------------------------------------------
"""Callback function for created events to enter new gcal id in the mapping table"""
if exception is not None:
logger.error("on_gcal_event_created: Exception " + str(exception))
raise exception
google_id = response['id'] def getAllGCalEvents( service, fromNow=False ):
django_id = response['extendedProperties']['private']['blechreizID']
mapping = GCalMapping(gcal_id=google_id, event=Event.objects.get(pk=django_id))
mapping.save()
# ------------------------------ GCal Api Calls --------------------------------------------------------------------
def get_all_gcal_events(service, from_now=False):
"""Retrieves all gcal events with custom property blechreizEvent=True i.e. all """Retrieves all gcal events with custom property blechreizEvent=True i.e. all
events that have been created by this script.""" events that have been created by this script."""
if from_now: if fromNow:
now = datetime.datetime.now() now = datetime.datetime.now()
min_time = now.strftime("%Y-%m-%dT%H:%M:%S-00:00") minTime = now.strftime("%Y-%m-%dT%H:%M:%S-00:00")
else: else:
min_time = '2000-01-01T00:00:00-00:00' minTime = '2000-01-01T00:00:00-00:00'
events = service.events().list( events = service.events().list(
calendarId='primary', calendarId='primary',
singleEvents=True, singleEvents=True,
maxResults=1000, maxResults=1000,
orderBy='startTime', orderBy='startTime',
timeMin=min_time, timeMin=minTime,
timeMax='2100-01-01T00:00:00-00:00', timeMax='2100-01-01T00:00:00-00:00',
privateExtendedProperty='blechreizEvent=true', privateExtendedProperty='blechreizEvent=true',
).execute() ).execute()
return events['items'] return events['items']
def createGCalEvent( service, event, timezone="Europe/Berlin" ):
def create_gcal_event(service, event, timezone="Europe/Berlin"):
"""Creates a new gcal event using a local event""" """Creates a new gcal event using a local event"""
google_event = build_gcal_event(event, timezone) googleEvent = buildGCalEvent(event,timezone)
return service.events().insert(calendarId='primary', body=google_event) return service.events().insert(calendarId='primary', body=googleEvent)
def updateGCalEvent( service, event, timezone="Europe/Berlin"):
def update_gcal_event(service, event, timezone="Europe/Berlin"):
"""Updates an existing gcal event, using a local event""" """Updates an existing gcal event, using a local event"""
google_event = build_gcal_event(event, timezone) googleEvent = buildGCalEvent(event,timezone)
try: mapping = GCalMapping.objects.get( event=event )
mapping = GCalMapping.objects.get(event=event) gcalId = mapping.gcal_id
except GCalMapping.DoesNotExist: return service.events().patch(calendarId='primary', eventId= gcalId, body=googleEvent)
return create_gcal_event(service, event, timezone)
return service.events().patch(calendarId='primary', eventId=mapping.gcal_id, body=google_event) def deleteGCalEvent( service, event ):
def delete_gcal_event(service, event):
"""Deletes gcal that belongs to the given local event""" """Deletes gcal that belongs to the given local event"""
mapping = GCalMapping.objects.get(event=event) mapping = GCalMapping.objects.get( event=event )
gcal_id = mapping.gcal_id gcalId = mapping.gcal_id
mapping.delete() return service.events().delete(calendarId='primary', eventId=gcalId)
return service.events().delete(calendarId='primary', eventId=gcal_id)
# ------------------------------------- Synchronization -------------------------------------------------------------
def delete_all_gcal_events(service=None): # ------------------------------------- Synchronization ----------------------------------------------------
def deleteAllGCalEvents( service = getServiceObject() ):
"""Deletes all gcal events that have been created by this script""" """Deletes all gcal events that have been created by this script"""
if service is None: if service is None: service = getServiceObject()
service = get_service_object()
gcal_ids = [ev['id'] for ev in get_all_gcal_events(service)] gcalIds = [ ev['id'] for ev in getAllGCalEvents( service ) ]
num_ids = len(gcal_ids) l = len( gcalIds )
if num_ids == 0: if l == 0:
return num_ids return l
batch = BatchHttpRequest() batch = BatchHttpRequest()
for ev_id in gcal_ids: for id in gcalIds:
batch.add(service.events().delete(calendarId='primary', eventId=ev_id)) batch.add( service.events().delete(calendarId='primary', eventId=id) )
batch.execute() batch.execute()
GCalMapping.objects.all().delete() return l
return num_ids def syncFromLocalToGoogle( service = None ):
def sync_from_local_to_google(service=None):
""" Creates a google event for each local event (if it does not exist yet) and deletes all google events """ Creates a google event for each local event (if it does not exist yet) and deletes all google events
that are not found in local database. Updates participation info of gcal events using local data that are not found in local database. Updates participation info of gcal events using local data
""" """
if service is None: service = getServiceObject()
if service is None: allEvents = getAllGCalEvents( service )
service = get_service_object()
all_events = get_all_gcal_events(service) eventsAtGoogle_djangoID = set()
eventsAtGoogle_googleID = set()
for gcalEv in allEvents:
eventsAtGoogle_djangoID.add( int(gcalEv['extendedProperties']['private']['blechreizID'] ) )
eventsAtGoogle_googleID.add( gcalEv['id'] )
events_at_google_django_id = set() localEvents_djangoID = set( Event. objects.all().values_list('pk' , flat=True) )
events_at_google_google_id = set() localEvents_googleID = set( GCalMapping.objects.all().values_list('gcal_id', flat=True) )
for gcal_ev in all_events:
events_at_google_django_id.add(int(gcal_ev['extendedProperties']['private']['blechreizID'])) eventsToCreate_djangoID = localEvents_djangoID - eventsAtGoogle_djangoID
events_at_google_google_id.add(gcal_ev['id']) eventsToDelete_googleID = eventsAtGoogle_googleID - localEvents_googleID
def onGcalEventCreated( request_id, response, exception ):
"""Callback function for created events to enter new gcal id in the mapping table"""
if exception is not None:
print ( "response " + str( response ) )
raise exception
googleId = response['id']
djangoId = response['extendedProperties']['private']['blechreizID']
mapping = GCalMapping( gcal_id = googleId, event = Event.objects.get( pk=djangoId ) )
mapping.save()
local_events_django_id = set(Event.objects.all().values_list('pk', flat=True))
local_events_google_id = set(GCalMapping.objects.all().values_list('gcal_id', flat=True))
events_to_create_django_id = local_events_django_id - events_at_google_django_id
events_to_delete_google_id = events_at_google_google_id - local_events_google_id
batch = BatchHttpRequest() batch = BatchHttpRequest()
batch_is_empty = True batchIsEmpty = True
for event_django_id in events_to_create_django_id: for eventDjangoID in eventsToCreate_djangoID:
batch.add(create_gcal_event(service, Event.objects.get(pk=event_django_id)), callback=on_gcal_event_created) batch.add( createGCalEvent( service, Event.objects.get( pk=eventDjangoID ) ), callback=onGcalEventCreated )
batch_is_empty = False batchIsEmpty=False
for eventGoogleID in events_to_delete_google_id: for eventGoogleID in eventsToDelete_googleID:
batch.add(service.events().delete(calendarId='primary', eventId=eventGoogleID)) batch.add( service.events().delete(calendarId='primary', eventId=eventGoogleID) )
batch_is_empty = False batchIsEmpty=False
for gcal_ev in all_events: for gcalEv in allEvents:
event_django_id = int(gcal_ev['extendedProperties']['private']['blechreizID']) eventDjangoID = int( gcalEv['extendedProperties']['private']['blechreizID'] )
try: try:
django_ev = Event.objects.get(pk=event_django_id) djangoEv = Event.objects.get( pk=eventDjangoID )
if 'attendees' not in gcal_ev: if 'attendees' not in gcalEv:
gcal_ev['attendees'] = [] gcalEv['attendees'] = []
if gcal_ev['attendees'] != build_gcal_attendees_obj(django_ev): if gcalEv['attendees'] != buildGCalAttendeesObj( djangoEv ):
batch.add(update_gcal_event(service, django_ev)) batch.add( updateGCalEvent( service, djangoEv ) )
batch_is_empty = False batchIsEmpty = False
except Event.DoesNotExist: except Event.DoesNotExist:
pass pass
if not batch_is_empty: if not batchIsEmpty:
batch.execute() batch.execute()
return len(events_to_create_django_id), len(events_to_delete_google_id)
def sync_from_google_to_local(service=None): return len (eventsToCreate_djangoID), len(eventsToDelete_googleID)
def syncFromGoogleToLocal( service = None ):
"""Retrieves only participation infos for all events and updates local database if anything has changed. """ """Retrieves only participation infos for all events and updates local database if anything has changed. """
if service is None: if service is None: service = getServiceObject()
service = get_service_object()
new_status_received = False newStatusReceived = False
all_events = get_all_gcal_events(service, from_now=True) allEvents = getAllGCalEvents( service, fromNow=True)
for e in all_events: for e in allEvents:
local_id = e['extendedProperties']['private']['blechreizID'] localId = e['extendedProperties']['private']['blechreizID']
local_event = Event.objects.get(pk=local_id) localEvent = Event.objects.get( pk=localId )
for a in e['attendees']: for a in e['attendees']:
user = UserGCalCoupling.objects.get(email=a['email']).user user = UserGCalCoupling.objects.get( email = a['email'] ).user
part = EventParticipation.get_or_create(user, local_event) part = EventParticipation.get_or_create( user, localEvent )
if 'comment' in a: if 'comment' in a:
part.comment = a['comment'] part.comment = a['comment']
if a['responseStatus'] == 'needsAction': if a['responseStatus'] == 'needsAction' :
part.status = "-" part.status = "-"
elif a['responseStatus'] == 'tentative': elif a['responseStatus']=='tentative':
part.status = '?' part.status = '?'
elif a['responseStatus'] == 'accepted': elif a['responseStatus'] == 'accepted':
part.status = 'Yes' part.status = 'Yes'
elif a['responseStatus'] == 'declined': elif a['responseStatus'] == 'declined':
part.status = 'No' part.status = 'No'
else: else:
logger.error("Unknown response status when mapping gcal event: " + a['responseStatus']) logger.error("Unknown response status when mapping gcal event: " + a['responseStatus'] )
prev = EventParticipation.objects.get(event=part.event, user=part.user) prev = EventParticipation.objects.get( event = part.event, user = part.user )
# Important: Save only if the participation info has changed # Important: Save only if the participation info has changed
# otherwise everything is synced back to google via the post save signal # otherwise everything is synced back to google via the post save signal
# and an endless loop is entered # and an endless loop is entered
if prev.status != part.status or prev.comment != part.comment: if prev.status != part.status or prev.comment != part.comment:
part.save() part.save()
new_status_received = True newStatusReceived = True
return newStatusReceived
return new_status_received
# ------------------------------------- Synchronization ---------------------------------------------------- # ------------------------------------- Synchronization ----------------------------------------------------
def check_gcal_subscription(service=None, time_to_live=14 * 24 * 3600, renew_before_expiry=None): def checkGCalSubscription( service=None, timeToLive = 14*24*3600, renewBeforeExpiry = None ):
"""Google offers a push service if any event information has changed. This works using a so called """Google offers a push service if any event information has changed. This works using a so called
channel, which has a certain time to live. This method checks that a valid channel exists: channel, which has a certain time to live. This method checks that a valid channel exists:
- if none exists a new one is created - if none exists a new one is created
- if existing channel does expire soon, the channel is renewed - if existing channel does expire soon, the channel is renewed
- if channel has already expired a sync is triggered and a new channel is created - if channel has already expired a sync is triggered and a new channel is created
""" """
if service is None: if service is None: service = getServiceObject()
service = get_service_object()
if renew_before_expiry is None: if renewBeforeExpiry is None:
renew_before_expiry = 0.8 * time_to_live renewBeforeExpiry = 0.8 * timeToLive
callback_url = settings.GCAL_COUPLING['push_url'] callbackUrl = settings.GCAL_COUPLING['push_url']
# Test if a channel already exists for this callbackURL # Test if a channel already exists for this callbackURL
try: try:
db_channel = GCalPushChannel.objects.get(address=callback_url) dbChannel = GCalPushChannel.objects.get( address=callbackUrl )
g_channel = db_channel.to_google_channel() gChannel = dbChannel.toGChannel()
# if expiration time between 0 and two days: stop and create new channel # if expiration time between 0 and two days: stop and create new channel
cur_time = int(time.time() * 1000) curTime = int( time.time() * 1000)
if g_channel.expiration > cur_time: if gChannel.expiration > curTime:
# not yet expired # not yet expired
if cur_time + renew_before_expiry * 1000 > g_channel.expiration: if curTime + renewBeforeExpiry*1000 > gChannel.expiration:
# will expire in less than "renewBeforeExpiry" #will expire in less than "renewBeforeExpiry"
logger.info("Renewing Google Calendar Subscription: " + callback_url) print ( "Renewing Google Calendar Subscription: " + callbackUrl )
GCalPushChannel.stop(service, g_channel) GCalPushChannel.stop( service, gChannel )
GCalPushChannel.create_new(callback_url, service, time_to_live) GCalPushChannel.createNew( callbackUrl, service, timeToLive )
else: else:
logger.info("Channel active until %d " % (g_channel.expiration,)) print ("Channel active until %d " % ( gChannel.expiration, ) )
else: else:
logger.info("Google calendar subscription had expired - getting new subscription") logger.info( "Google calendar subscription had expired - getting new subscription" )
# to get back in sync again we have to decide which data to take # to get back in sync again we have to decide which data to take
# so we use the local data as reference # so we use the local data as reference
sync_from_local_to_google(service) syncFromLocalToGoogle( service )
GCalPushChannel.create_new(callback_url, service, time_to_live) GCalPushChannel.createNew( callbackUrl, service, timeToLive )
except GCalPushChannel.DoesNotExist: except GCalPushChannel.DoesNotExist:
# create new channel and save it in database # create new channel and save it in database
logger.info("No CGalCallback Channel exists yet for: " + callback_url) logger.info ( "No CGalCallback Channel exists yet for: " + callbackUrl )
# to get back in sync again we have to decide which data to take # to get back in sync again we have to decide which data to take
# so we use the local data as reference # so we use the local data as reference
sync_from_local_to_google(service) syncFromLocalToGoogle( service )
GCalPushChannel.create_new(callback_url, service, time_to_live) GCalPushChannel.createNew( callbackUrl, service, timeToLive )
def stop_all_gcal_subscriptions(service=None): def stopAllGCalSubscriptions( service=None ):
"""Stops the channel subscription """ """Stops the channel subscription """
if service is None: if service is None: service = getServiceObject()
service = get_service_object()
for dbChannel in GCalPushChannel.objects.all(): for dbChannel in GCalPushChannel.objects.all():
logger.info("Stopping %s expiry at %d " % (dbChannel.id, dbChannel.expiration)) print("Stopping %s expiry at %d " % ( dbChannel.id, dbChannel.expiration ) )
GCalPushChannel.stop(service, dbChannel.to_google_channel()) GCalPushChannel.stop( service, dbChannel.toGChannel() )
def check_if_google_callback_is_valid(token, channel_id, resource_id, service=None): def checkIfGoogleCallbackIsValid( token, channelID, resourceID, service=None ):
if service is None: if service is None: service = getServiceObject()
service = get_service_object()
all_channels = GCalPushChannel.objects.all() allChannels = GCalPushChannel.objects.all()
if len(all_channels) == 0: if len(allChannels) == 0:
return False # no known subscriptions -> callback has to be from an old channel return False # no known subscriptions -> callback has to be from an old channel
if len(all_channels) > 1: if len(allChannels) > 1:
logger.warning("Multiple GCal subscriptions! This is strange and probably an error. " logger.warning( "Multiple GCal subscriptions! This is strange and probably an error. "
"All channels are closed and one new is created. ") "All channels are closed and one new is created. ")
stop_all_gcal_subscriptions(service) stopAllGCalSubscriptions( service )
check_gcal_subscription() checkGCalSubscription()
all_channels = GCalPushChannel.objects.all() allChannels = GCalPushChannel.objects.all()
assert (len(all_channels) == 1) assert( len(allChannels) == 1 )
the_channel = all_channels[0] theChannel = allChannels[0]
if channel_id != the_channel.id or resource_id != the_channel.resource_id or token != the_channel.token: if channelID != theChannel.id or resourceID != theChannel.resource_id or token != theChannel.token:
logger.warning("Got GCal Response from an unexpected Channel" logger.warning( "Got GCal Response from an unexpected Channel"
"Got (%s,%s,%s) " "Got (%s,%s,%s) "
"expected (%s,%s,%s) " "expected (%s,%s,%s) "
"Old Channel is stopped." "Old Channel is stopped."
% (channel_id, resource_id, token, the_channel.id, the_channel.resource_id, the_channel.token)) % ( channelID, resourceID,token, theChannel.id, theChannel.resource_id, theChannel.token ))
channel_to_stop = GCalPushChannel(id=channel_id, resource_id=resource_id, token=token) channelToStop = GCalPushChannel( id = channelID, resource_id = resourceID, token = token )
GCalPushChannel.stop(service, channel_to_stop.to_google_channel()) GCalPushChannel.stop( service, channelToStop.toGChannel() )
return False return False

View File

@ -1 +1 @@
{"_module": "oauth2client.client", "token_expiry": "2017-10-24T07:29:15Z", "access_token": "ya29.GlvuBAjiaOmu9fZaR9RElCkEvkcJVv-lL-hsL8bGczd-Lvl-y_vYA-dHPmCurc111i7SwLCY2nWRrUcZneR3bwGQuOW8j6MbeYncJDRcpjqYJBGpJUxuTizafOOv", "token_uri": "https://accounts.google.com/o/oauth2/token", "invalid": false, "token_response": {"access_token": "ya29.GlvuBAjiaOmu9fZaR9RElCkEvkcJVv-lL-hsL8bGczd-Lvl-y_vYA-dHPmCurc111i7SwLCY2nWRrUcZneR3bwGQuOW8j6MbeYncJDRcpjqYJBGpJUxuTizafOOv", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "1/txixroRJyyVmuENPpaXyB_bGeXa1XV-pClAxqKHk_5-JW1qGFE0Gl-WlgCu1Eizq"}, "client_id": "34462582242-4kpdvvbi27ajt4u22uitqurpve9o8ipj.apps.googleusercontent.com", "id_token": null, "client_secret": "y4t9XBrJdCODPTO5UvtONWWn", "revoke_uri": "https://accounts.google.com/o/oauth2/revoke", "_class": "OAuth2Credentials", "refresh_token": "1/txixroRJyyVmuENPpaXyB_bGeXa1XV-pClAxqKHk_5-JW1qGFE0Gl-WlgCu1Eizq", "user_agent": null} {"_module": "oauth2client.client", "token_expiry": "2014-03-08T14:33:53Z", "access_token": "ya29.1.AADtN_UH8eRhIXsdwF4W1D5oC8xYlMhG-0qeT210pyb6pxk7LTLmd-EnUNVS2UjJZQ", "token_uri": "https://accounts.google.com/o/oauth2/token", "invalid": false, "token_response": {"access_token": "ya29.1.AADtN_UH8eRhIXsdwF4W1D5oC8xYlMhG-0qeT210pyb6pxk7LTLmd-EnUNVS2UjJZQ", "token_type": "Bearer", "expires_in": 3600}, "client_id": "34462582242-4kpdvvbi27ajt4u22uitqurpve9o8ipj.apps.googleusercontent.com", "id_token": null, "client_secret": "y4t9XBrJdCODPTO5UvtONWWn", "revoke_uri": "https://accounts.google.com/o/oauth2/revoke", "_class": "OAuth2Credentials", "refresh_token": "1/7-6-m_lLAKX8IeD7OuGtkcIiprty_nZUSxhMunSC5b0", "user_agent": null}

View File

@ -16,9 +16,7 @@ if createLink:
print "Visit this link - grab the key from the url and paste it into the else block" print "Visit this link - grab the key from the url and paste it into the else block"
exit(0) exit(0)
else: else:
#code = "4/Iais8aK8_KxbMQjq3Rtw3PFXu6Nr.8itpukY_6ZgZOl05ti8ZT3ax27a3hAI" code = "4/Iais8aK8_KxbMQjq3Rtw3PFXu6Nr.8itpukY_6ZgZOl05ti8ZT3ax27a3hAI"
#code = "4/YjdxGI8sIokRhYVE18ut9WMeYbmRLfazB-HOGCyqo4M#"
code = "4/3EhMJx4WlXrZhyEwGGiHG-rhJzZAPrALFEYJpfvp5J8#"
credentials = flow.step2_exchange( code ) credentials = flow.step2_exchange( code )
storage = Storage('calendarCredentials.dat') storage = Storage('calendarCredentials.dat')
storage.put( credentials ) storage.put( credentials )

View File

@ -1,11 +1,9 @@
from django.core.management.base import NoArgsCommand from django.core.management.base import NoArgsCommand
from eventplanner_gcal.google_sync import check_gcal_subscription from eventplanner_gcal.google_sync import checkGCalSubscription
class Command(NoArgsCommand): class Command(NoArgsCommand):
help = 'Checks if the GCal notification channel is still active' help = 'Checks if the GCal notification channel is still active'
def handle_noargs(self, **options): def handle_noargs(self, **options):
print("Checking Subscription") print ( "Checking Subscription")
check_gcal_subscription() checkGCalSubscription()

View File

@ -1,11 +1,9 @@
from django.core.management.base import NoArgsCommand from django.core.management.base import NoArgsCommand
from eventplanner_gcal.google_sync import delete_all_gcal_events from eventplanner_gcal.google_sync import deleteAllGCalEvents
class Command(NoArgsCommand): class Command(NoArgsCommand):
help = 'Delete all events in the google calendar created by this app' help = 'Delete all events in the google calendar created by this app'
def handle_noargs(self, **options): def handle_noargs(self, **options):
print("Deleting all GCal Events.") print ("Deleting all GCal Events.")
nr_of_deleted_events = delete_all_gcal_events() nrOfDeletedEvents = deleteAllGCalEvents()
print("Deleted %d events. To Restore them from local database run gcal_sync" % (nr_of_deleted_events,)) print ("Deleted %d events. To Restore them from local database run gcal_sync" % (nrOfDeletedEvents, ) )

View File

@ -1,10 +1,8 @@
from django.core.management.base import NoArgsCommand from django.core.management.base import NoArgsCommand
from eventplanner_gcal.google_sync import stop_all_gcal_subscriptions from eventplanner_gcal.google_sync import stopAllGCalSubscriptions
class Command(NoArgsCommand): class Command(NoArgsCommand):
help = 'Stops all GCal subscriptions' help = 'Stops all GCal subscriptions'
def handle_noargs(self, **options): def handle_noargs(self, **options):
stop_all_gcal_subscriptions() stopAllGCalSubscriptions()

View File

@ -1,11 +1,10 @@
from django.core.management.base import NoArgsCommand from django.core.management.base import NoArgsCommand
from eventplanner_gcal.google_sync import sync_from_local_to_google
from eventplanner_gcal.google_sync import syncFromLocalToGoogle
class Command(NoArgsCommand): class Command(NoArgsCommand):
help = 'Synchronize Google Calendar with locally stored Events' help = 'Synchronize Google Calendar with locally stored Events'
def handle_noargs(self, **options): def handle_noargs(self, **options):
print("Running Sync") print ( "Running Sync")
created, deleted = sync_from_local_to_google() created, deleted = syncFromLocalToGoogle()
print("Created %d and deleted %d events" % (created, deleted)) print ( "Created %d and deleted %d events" % (created,deleted) )

View File

@ -3,57 +3,59 @@ import uuid
from eventplanner.models import Event from eventplanner.models import Event
from django.contrib.auth.models import User from django.contrib.auth.models import User
from apiclient.channel import Channel from apiclient.channel import Channel
from django.db import models from django.db import models
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class UserGCalCoupling(models.Model): class UserGCalCoupling( models.Model ):
# For every user in this table the gcal coupling is activated # For every user in this table the gcal coupling is activated
user = models.OneToOneField(User, on_delete=models.CASCADE) user = models.OneToOneField( User )
email = models.CharField(max_length=1024) email = models.CharField( max_length=1024 )
class GCalMapping(models.Model): class GCalMapping( models.Model ):
"""Mapping between event id at google and local event id""" """Mapping between event id at google and local event id"""
gcal_id = models.CharField(max_length=64) gcal_id = models.CharField( max_length=64 )
event = models.OneToOneField(Event, primary_key=True, on_delete=models.CASCADE) event = models.OneToOneField( Event, primary_key=True )
class GCalPushChannel(models.Model): class GCalPushChannel( models.Model ):
"""This table has either zero or one entry. Required to store if a channel already exists, """This table has either zero or one entry. Required to store if a channel already exists,
when it expires and how to stop (renew) the channel when it expires and how to stop (renew) the channel
""" """
id = models.CharField(max_length=128, primary_key=True) id = models.CharField( max_length=128, primary_key=True )
address = models.CharField(max_length=256) address = models.CharField( max_length=256 )
token = models.CharField(max_length=128) token = models.CharField( max_length=128 )
resource_id = models.CharField(max_length=128) resource_id = models.CharField( max_length=128 )
expiration = models.IntegerField() expiration = models.IntegerField()
def to_google_channel(self): def toGChannel( self ):
return Channel('web_hook', self.id, self.token, self.address, self.expiration, resource_id=self.resource_id) return Channel( 'web_hook', self.id, self.token, self.address, self.expiration, resource_id = self.resource_id )
@staticmethod @staticmethod
def from_google_channel(google_channel): def fromGChannel( gChannel ):
return GCalPushChannel(id=google_channel.id, return GCalPushChannel( id = gChannel.id,
address=google_channel.address, address = gChannel.address,
token=google_channel.token, token = gChannel.token,
expiration=google_channel.expiration, expiration = gChannel.expiration,
resource_id=google_channel.resource_id) resource_id= gChannel.resource_id )
@staticmethod @staticmethod
def create_new(callback_url, service, ttl=None): def createNew( callbackUrl, service, ttl = None ):
gChannel = Channel('web_hook', str(uuid.uuid4()), 'blechreizGcal', callback_url, params={'ttl': int(ttl)}) gChannel = Channel('web_hook', str(uuid.uuid4()), 'blechreizGcal', callbackUrl, params= { 'ttl' : int(ttl) } )
response = service.events().watch(calendarId='primary', body=gChannel.body()).execute() response = service.events().watch( calendarId='primary', body= gChannel.body() ).execute()
gChannel.update(response) gChannel.update( response )
dbChannel = GCalPushChannel.from_google_channel(gChannel) dbChannel = GCalPushChannel.fromGChannel( gChannel )
dbChannel.save() dbChannel.save()
@staticmethod @staticmethod
def stop(service, google_channel): def stop( service, gChannel ):
channel_service = service.channels() channelService = service.channels()
channel_service.stop(body=google_channel.body()).execute() channelService.stop( body = gChannel.body() ).execute()
GCalPushChannel.from_google_channel(google_channel).delete() GCalPushChannel.fromGChannel( gChannel ).delete()

View File

@ -1,61 +1,42 @@
from django.db.models.signals import post_save, pre_delete from django.db.models.signals import post_save,pre_delete
from django.dispatch import receiver from django.dispatch import receiver
from eventplanner.models import Event, EventParticipation from eventplanner.models import Event, EventParticipation
from eventplanner_gcal.google_sync import get_service_object, \ from django.contrib.auth.models import User
create_gcal_event, delete_gcal_event, update_gcal_event, on_gcal_event_created from eventplanner_gcal.google_sync import getServiceObject, syncFromLocalToGoogle,\
createGCalEvent, deleteGCalEvent, updateGCalEvent
import logging import logging
from django.conf import settings logger = logging.getLogger( __name__ )
logger = logging.getLogger(__name__)
# @receiver( post_save, sender=User ) #@receiver( post_save, sender=User )
# def user_changed( **kwargs ): #def user_changed( **kwargs ):
# logger.info("Synchronizing with google - user information changed") # logger.info("Synchronizing with google - user information changed")
# syncFromLocalToGoogle( getServiceObject() ) # syncFromLocalToGoogle( getServiceObject() )
@receiver(post_save, sender=Event) @receiver( post_save,sender= Event)
def event_post_save_handler(**kwargs): def event_post_save_handler( **kwargs):
if not settings.GCAL_SYNC_ENABLED:
return
event = kwargs['instance'] event = kwargs['instance']
created = kwargs['created'] created = kwargs['created']
try: if created:
if created: logger.info("Creating Gcal event")
logger.info("Creating Gcal event") createGCalEvent( getServiceObject(), event ).execute()
response = create_gcal_event(get_service_object(), event).execute() else:
on_gcal_event_created(None, response, None) logger.info( "Updating Gcal event")
else: updateGCalEvent( getServiceObject(),event ).execute()
logger.info("Updating Gcal event")
update_gcal_event(get_service_object(), event).execute()
except Exception as e:
logger.error("Error updating Gcal event" + str(e))
@receiver(pre_delete, sender=Event)
def event_pre_delete_handler(**kwargs):
if not settings.GCAL_SYNC_ENABLED:
return
try: @receiver( pre_delete,sender= Event)
event = kwargs['instance'] def event_pre_delete_handler( **kwargs):
logger.info("Deleting Gcal event") event = kwargs['instance']
delete_gcal_event(get_service_object(), event).execute() logger.info ("Deleting GCAL event")
except Exception as e: deleteGCalEvent( getServiceObject(), event ).execute()
logger.error("Error deleting GCAL event" + str(e))
@receiver(post_save, sender=EventParticipation) @receiver( post_save, sender=EventParticipation )
def participation_post_save_handler(**kwargs): def participation_post_save_handler( **kwargs):
if not settings.GCAL_SYNC_ENABLED: participation = kwargs['instance']
return logger.info("Participation post save -> update gcal")
updateGCalEvent( getServiceObject(), participation.event ).execute()
try:
participation = kwargs['instance']
logger.info("Participation post save -> update gcal")
update_gcal_event(get_service_object(), participation.event).execute()
except Exception as e:
logger.error("Error deleting GCAL event" + str(e))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@ -4,7 +4,7 @@
{% block content %} {% block content %}
{% addtoblock "css" strip %} {% addtoblock "css" strip %}
<link rel="stylesheet" href="{{STATIC_URL}}css/bootstrap-switch.min.css" type="text/css" media="screen" /> <link rel="stylesheet" href="{{STATIC_URL}}/css/bootstrap-switch.min.css" type="text/css" media="screen" />
{% endaddtoblock %} {% endaddtoblock %}
{% addtoblock "css" %} {% addtoblock "css" %}
@ -25,7 +25,7 @@
{% endaddtoblock %} {% endaddtoblock %}
{% addtoblock "js" strip %} {% addtoblock "js" strip %}
<script src="{{STATIC_URL}}js/bootstrap-switch.min.js"></script> <script src="{{STATIC_URL}}/js/bootstrap-switch.min.js"></script>
{% endaddtoblock %} {% endaddtoblock %}
{% addtoblock "js" %} {% addtoblock "js" %}
@ -68,22 +68,11 @@
<h5>NEU</h5> <h5>NEU</h5>
Die Blechreiz Termine können jetzt automatisch in den eigenen Google Kalender übernommen werden. Die Blechreiz Termine können jetzt automatisch in den eigenen Google Kalender übernommen werden.
Auch vom Google Kalender aus kann man sich dann für Termine eintragen, direkt vom Handy oder Tablet aus. Auch vom Google Kalender aus kann man sich dann für Termine eintragen, direkt vom Handy oder Tablet aus.
Die Termine werden automatisch in den eigenen Kalender übernommen. Das Eintragen fällt leichter
weil man alle anderen eigenen Termine auch im Blick hat.
</p> </p>
<img src="{{STATIC_URL}}img/screenshot.png">
<p> <p>
<h5>SO GEHTS:</h5> <h5>SO GEHTS:</h5>
Einfach die eigene Google Mail Adresse angeben und die Kopplung aktivieren. Einfach die eigene Google Mail Adresse angeben und die Kopplung aktivieren.
<br>
Achtung: Beim Kalender wird zwischen der Endung <em>@googlemail.com</em> und der
Endung <em>@gmail.com</em> unterschieden ( bei Emails macht es keinen Unterschied, egal welche Endung,
alle kommen an). <br>
Um herauszufinden was die richtige Endung ist, meldet man sich
<a href="https://www.google.com/calendar/" target="_blank">hier</a> an und öffnet die Einstellungen des eigenen Kalenders
(in der Leiste links, unter "Meine Kalender" aufs Dreieck neben dem eigenen Kalender klicken).
</p> </p>
@ -110,15 +99,11 @@
{% endif %} {% endif %}
</form> </form>
</div> </div>
<div class="span3 offset1"> <div class="span3 offset1">
<img src="{{STATIC_URL}}img/google_cal.png"> <img src="{{STATIC_URL}}/img/google_cal.png">
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,9 +1,10 @@
from django.conf.urls import url from django.conf.urls import patterns, url
from .views import run_sync, gcal_api_callback, manage from views import runSync, gcalApiCallback, manage
urlpatterns = patterns('',
url(r'^runSync$', runSync ),
url(r'^gcalApiCallback$', gcalApiCallback ),
url(r'^manage$', manage ),
)
urlpatterns = [
url(r'^runSync$', run_sync),
url(r'^gcalApiCallback$', gcal_api_callback),
url(r'^manage$', manage),
]

View File

@ -1,63 +1,64 @@
from django.shortcuts import redirect from django.shortcuts import redirect
from eventplanner_gcal.google_sync import sync_from_google_to_local, sync_from_local_to_google from eventplanner_gcal.google_sync import syncFromGoogleToLocal, syncFromLocalToGoogle
from django.http import HttpResponse from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
from eventplanner_gcal.google_sync import check_if_google_callback_is_valid from pprint import pformat
from eventplanner_gcal.google_sync import checkIfGoogleCallbackIsValid
from eventplanner_gcal.models import UserGCalCoupling from eventplanner_gcal.models import UserGCalCoupling
from django.shortcuts import render from django.shortcuts import render
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger( __name__ )
def run_sync(request): def runSync( request ):
sync_from_local_to_google() syncFromLocalToGoogle()
return redirect("/") return redirect("/")
def manage(request): def manage( request ):
if request.method == 'POST': if request.method == 'POST':
if request.POST['activate'] == "1": if request.POST['activate'] == "1":
UserGCalCoupling.objects.filter(user=request.user).delete() UserGCalCoupling.objects.filter( user=request.user ).delete()
c = UserGCalCoupling(user=request.user, email=request.POST['email']) c = UserGCalCoupling( user=request.user, email = request.POST['email'] )
c.save() c.save()
sync_from_local_to_google() syncFromLocalToGoogle()
else: else:
UserGCalCoupling.objects.filter(user=request.user).delete() UserGCalCoupling.objects.filter( user=request.user ).delete()
sync_from_local_to_google() syncFromLocalToGoogle()
context = {} context = {}
user_coupling = UserGCalCoupling.objects.filter(user=request.user) userCoupling = UserGCalCoupling.objects.filter( user = request.user )
context['enabled'] = len(user_coupling) context['enabled'] = len(userCoupling)
assert (len(user_coupling) < 2) assert( len(userCoupling) < 2 )
if len(user_coupling) == 1: if len(userCoupling) == 1:
context['mail'] = user_coupling[0].email context['mail'] = userCoupling[0].email
return render(request, 'eventplanner_gcal/management.html', context) return render( request, 'eventplanner_gcal/management.html', context )
@csrf_exempt @csrf_exempt
def gcal_api_callback(request): def gcalApiCallback( request ):
# TODO check channel info here
token = "" token = ""
if 'HTTP_X_GOOG_CHANNEL_TOKEN' in request.META: if 'HTTP_X_GOOG_CHANNEL_TOKEN' in request.META: token = request.META['HTTP_X_GOOG_CHANNEL_TOKEN']
token = request.META['HTTP_X_GOOG_CHANNEL_TOKEN'] channelID = ""
if 'HTTP_X_GOOG_CHANNEL_ID' in request.META: channelID = request.META['HTTP_X_GOOG_CHANNEL_ID']
resourceID = ""
if 'HTTP_X_GOOG_RESOURCE_ID' in request.META: resourceID = request.META['HTTP_X_GOOG_RESOURCE_ID']
channel_id = "" valid = checkIfGoogleCallbackIsValid( token, channelID, resourceID)
if 'HTTP_X_GOOG_CHANNEL_ID' in request.META:
channel_id = request.META['HTTP_X_GOOG_CHANNEL_ID']
resource_id = ""
if 'HTTP_X_GOOG_RESOURCE_ID' in request.META:
resource_id = request.META['HTTP_X_GOOG_RESOURCE_ID']
valid = check_if_google_callback_is_valid(token, channel_id, resource_id)
if not valid: if not valid:
return HttpResponse('<h1>Old Channel - no update triggered</h1>') return HttpResponse('<h1>Old Channel - no update triggered</h1>')
logger.info("Received Google Callback with the following headers Token: "
"%s ID %s ResID %s " % (token, channel_id, resource_id)) logger.info( "Received Google Callback with the following headers Token: %s ID %s ResID %s " % ( token, channelID, resourceID ) )
result = sync_from_google_to_local() result = syncFromGoogleToLocal()
logger.info("Finished processing callback from GCal - New Information present: %d " % (result,)) logger.info("Finished processing callback from GCal - New Information present: %d " %(result, ) )
return HttpResponse('<h1>Callback successful</h1>') return HttpResponse('<h1>Callback successful</h1>')

0
imagestore/__init__.py Normal file
View File

36
imagestore/admin.py Normal file
View File

@ -0,0 +1,36 @@
from django.contrib import admin
from imagestore.models import Image, Album, AlbumUpload
from sorl.thumbnail.admin import AdminInlineImageMixin
from django.conf import settings
class InlineImageAdmin(AdminInlineImageMixin, admin.TabularInline):
model = Image
fieldsets = ((None, {'fields': ['image', 'user', 'title', 'order', 'tags', 'album']}),)
raw_id_fields = ('user', )
extra = 0
class AlbumAdmin(admin.ModelAdmin):
fieldsets = ((None, {'fields': ['name', 'user', 'is_public', 'order']}),)
list_display = ('name', 'admin_thumbnail', 'user', 'created', 'updated', 'is_public', 'order')
list_editable = ('order', )
inlines = [InlineImageAdmin]
admin.site.register(Album, AlbumAdmin)
class ImageAdmin(admin.ModelAdmin):
fieldsets = ((None, {'fields': ['user', 'title', 'image', 'description', 'order', 'tags', 'album']}),)
list_display = ('admin_thumbnail', 'user', 'order', 'album', 'title')
raw_id_fields = ('user', )
list_filter = ('album', )
class AlbumUploadAdmin(admin.ModelAdmin):
def has_change_permission(self, request, obj=None):
return False
IMAGE_MODEL = getattr(settings, 'IMAGESTORE_IMAGE_MODEL', None)
if not IMAGE_MODEL:
admin.site.register(Image, ImageAdmin)
ALBUM_MODEL = getattr(settings, 'IMAGESTORE_ALBUM_MODEL', None)
if not ALBUM_MODEL:
admin.site.register(AlbumUpload, AlbumUploadAdmin)

View File

@ -0,0 +1,9 @@
# coding=utf-8
from __future__ import unicode_literals
import autocomplete_light
from tagging.models import Tag
autocomplete_light.register(
Tag,
search_fields=['^name']
)

View File

@ -0,0 +1,29 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
from django.core.urlresolvers import reverse, NoReverseMatch
from django.conf import settings
from utils import get_model_string
from imagestore.models import image_applabel, image_classname
from imagestore.models import album_applabel, album_classname
def imagestore_processor(request):
template = getattr(settings, 'IMAGESTORE_TEMPLATE', False)
ret = {
'IMAGESTORE_SHOW_USER': getattr(settings, 'IMAGESTORE_SHOW_USER', True),
'IMAGESTORE_SHOW_TAGS': getattr(settings, 'IMAGESTORE_SHOW_TAGS', True),
'IMAGESTORE_MODEL_STRING': get_model_string('Image'),
'IMAGESTORE_LOAD_CSS': getattr(settings, 'IMAGESTORE_LOAD_CSS', True),
}
try:
ret['imagestore_index_url'] = reverse('imagestore:index')
except NoReverseMatch: #Bastard django-cms from hell!!!!111
pass
if template:
ret['IMAGESTORE_TEMPLATE'] = template
ret['imagestore_perms'] = {
'add_image': request.user.has_perm('%s.add_%s' % (image_applabel, image_classname)),
'add_album': request.user.has_perm('%s.add_%s' % (album_applabel, album_classname)),
}
return ret

42
imagestore/forms.py Normal file
View File

@ -0,0 +1,42 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
try:
import autocomplete_light
AUTOCOMPLETE_LIGHT_INSTALLED = True
except ImportError:
AUTOCOMPLETE_LIGHT_INSTALLED = False
__author__ = 'zeus'
from django import forms
from models import Image, Album
from django.utils.translation import ugettext_lazy as _
class ImageForm(forms.ModelForm):
class Meta(object):
model = Image
exclude = ('user', 'order')
description = forms.CharField(widget=forms.Textarea(attrs={'rows': 2, 'cols': 19}), required=False,
label=_('Description'))
def __init__(self, user, *args, **kwargs):
super(ImageForm, self).__init__(*args, **kwargs)
self.fields['album'].queryset = Album.objects.filter(user=user)
self.fields['album'].required = True
if AUTOCOMPLETE_LIGHT_INSTALLED:
self.fields['tags'].widget = autocomplete_light.TextWidget('TagAutocomplete')
class AlbumForm(forms.ModelForm):
class Meta(object):
model = Album
exclude = ('user', 'created', 'updated')
def __init__(self, *args, **kwargs):
super(AlbumForm, self).__init__(*args, **kwargs)
if 'instance' in kwargs and kwargs['instance']:
self.fields['head'].queryset = Image.objects.filter(album=kwargs['instance'])
else:
self.fields['head'].widget = forms.HiddenInput()

View File

@ -0,0 +1,5 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
__author__ = 'zeus'

View File

@ -0,0 +1,15 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
__author__ = 'zeus'
from cms.app_base import CMSApp
from cms.apphook_pool import apphook_pool
from django.utils.translation import ugettext_lazy as _
class ImagestoreApp(CMSApp):
name = _("Imagestore App") # give your app a name, this is required
urls = ["imagestore.imagestore_cms.urls"] # link your app to url configuration(s)
apphook_pool.register(ImagestoreApp) # register your app

View File

@ -0,0 +1,53 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
__author__ = 'zeus'
from cms.plugin_base import CMSPluginBase
from cms.plugin_pool import plugin_pool
from models import ImagestoreAlbumPtr, ImagestoreAlbumCarousel
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
class AlbumPlugin(CMSPluginBase):
model = ImagestoreAlbumPtr
name = _('Album')
render_template = "cms/plugins/imagestore_album.html"
text_enabled = True
def render(self, context, instance, placeholder):
context.update({'album': instance.album})
return context
class AlbumCarouselPlugin(CMSPluginBase):
model = ImagestoreAlbumCarousel
name = _('Album as carousel')
render_template = "cms/plugins/imagestore_album_carousel.html"
text_enabled = True
def render(self, context, instance, placeholder):
# default carousel template in the settings file
carousel_template = getattr(settings, 'IMAGESTORE_CAROUSEL_TEMPLATE', None)
if carousel_template:
self.render_template = carousel_template
if instance.template_file:
self.render_template = instance.template_file
else:
if carousel_template:
instance.template_file = carousel_template
else:
instance.template_file = self.render_template
instance.save()
images = instance.album.images.all()
if instance.limit:
images = images[:instance.limit]
context.update({'images': images, 'carousel': instance})
return context
plugin_pool.register_plugin(AlbumCarouselPlugin)
plugin_pool.register_plugin(AlbumPlugin)

View File

@ -0,0 +1,112 @@
# 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 'ImagestoreAlbumPtr'
db.create_table('cmsplugin_imagestorealbumptr', (
('cmsplugin_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['cms.CMSPlugin'], unique=True, primary_key=True)),
('album', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['imagestore.Album'])),
))
db.send_create_signal('imagestore_cms', ['ImagestoreAlbumPtr'])
def backwards(self, orm):
# Deleting model 'ImagestoreAlbumPtr'
db.delete_table('cmsplugin_imagestorealbumptr')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'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'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'imagestore.album': {
'Meta': {'ordering': "('created', 'name')", 'object_name': 'Album'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'head': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'head_of'", 'null': 'True', 'to': "orm['imagestore.Image']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'albums'", 'null': 'True', 'to': "orm['auth.User']"})
},
'imagestore.image': {
'Meta': {'ordering': "('order', 'id')", 'object_name': 'Image'},
'album': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['imagestore.Album']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'image': ('sorl.thumbnail.fields.ImageField', [], {'max_length': '100'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'tags': ('tagging.fields.TagField', [], {}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['auth.User']"})
},
'imagestore_cms.imagestorealbumptr': {
'Meta': {'object_name': 'ImagestoreAlbumPtr', 'db_table': "'cmsplugin_imagestorealbumptr'", '_ormbases': ['cms.CMSPlugin']},
'album': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['imagestore.Album']"}),
'cmsplugin_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['cms.CMSPlugin']", 'unique': 'True', 'primary_key': 'True'})
}
}
complete_apps = ['imagestore_cms']

View File

@ -0,0 +1,121 @@
# 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 'ImagestoreAlbumCarusel'
db.create_table('cmsplugin_imagestorealbumcarusel', (
('cmsplugin_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['cms.CMSPlugin'], unique=True, primary_key=True)),
('album', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['imagestore.Album'])),
('width', self.gf('django.db.models.fields.IntegerField')(default=200)),
('limit', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)),
))
db.send_create_signal('imagestore_cms', ['ImagestoreAlbumCarusel'])
def backwards(self, orm):
# Deleting model 'ImagestoreAlbumCarusel'
db.delete_table('cmsplugin_imagestorealbumcarusel')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'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'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'imagestore.album': {
'Meta': {'ordering': "('created', 'name')", 'object_name': 'Album'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'head': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'head_of'", 'null': 'True', 'to': "orm['imagestore.Image']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'albums'", 'null': 'True', 'to': "orm['auth.User']"})
},
'imagestore.image': {
'Meta': {'ordering': "('order', 'id')", 'object_name': 'Image'},
'album': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['imagestore.Album']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'image': ('sorl.thumbnail.fields.ImageField', [], {'max_length': '100'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'tags': ('tagging.fields.TagField', [], {}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['auth.User']"})
},
'imagestore_cms.imagestorealbumcarusel': {
'Meta': {'object_name': 'ImagestoreAlbumCarusel', 'db_table': "'cmsplugin_imagestorealbumcarusel'", '_ormbases': ['cms.CMSPlugin']},
'album': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['imagestore.Album']"}),
'cmsplugin_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['cms.CMSPlugin']", 'unique': 'True', 'primary_key': 'True'}),
'limit': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'width': ('django.db.models.fields.IntegerField', [], {'default': '200'})
},
'imagestore_cms.imagestorealbumptr': {
'Meta': {'object_name': 'ImagestoreAlbumPtr', 'db_table': "'cmsplugin_imagestorealbumptr'", '_ormbases': ['cms.CMSPlugin']},
'album': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['imagestore.Album']"}),
'cmsplugin_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['cms.CMSPlugin']", 'unique': 'True', 'primary_key': 'True'})
}
}
complete_apps = ['imagestore_cms']

View File

@ -0,0 +1,137 @@
# 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 'ImagestoreAlbumCarusel'
db.delete_table('cmsplugin_imagestorealbumcarusel')
# Adding model 'ImagestoreAlbumCarousel'
db.create_table('cmsplugin_imagestorealbumcarousel', (
('cmsplugin_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['cms.CMSPlugin'], unique=True, primary_key=True)),
('album', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['imagestore.Album'])),
('width', self.gf('django.db.models.fields.IntegerField')(default=200)),
('height', self.gf('django.db.models.fields.IntegerField')(default=200)),
('skin', self.gf('django.db.models.fields.CharField')(default='jcarousel-skin-tango', max_length=100)),
('limit', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)),
))
db.send_create_signal('imagestore_cms', ['ImagestoreAlbumCarousel'])
def backwards(self, orm):
# Adding model 'ImagestoreAlbumCarusel'
db.create_table('cmsplugin_imagestorealbumcarusel', (
('album', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['imagestore.Album'])),
('limit', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)),
('cmsplugin_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['cms.CMSPlugin'], unique=True, primary_key=True)),
('width', self.gf('django.db.models.fields.IntegerField')(default=200)),
))
db.send_create_signal('imagestore_cms', ['ImagestoreAlbumCarusel'])
# Deleting model 'ImagestoreAlbumCarousel'
db.delete_table('cmsplugin_imagestorealbumcarousel')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'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'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'imagestore.album': {
'Meta': {'ordering': "('created', 'name')", 'object_name': 'Album'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'head': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'head_of'", 'null': 'True', 'to': "orm['imagestore.Image']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'albums'", 'null': 'True', 'to': "orm['auth.User']"})
},
'imagestore.image': {
'Meta': {'ordering': "('order', 'id')", 'object_name': 'Image'},
'album': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['imagestore.Album']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'image': ('sorl.thumbnail.fields.ImageField', [], {'max_length': '100'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'tags': ('tagging.fields.TagField', [], {}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['auth.User']"})
},
'imagestore_cms.imagestorealbumcarousel': {
'Meta': {'object_name': 'ImagestoreAlbumCarousel', 'db_table': "'cmsplugin_imagestorealbumcarousel'", '_ormbases': ['cms.CMSPlugin']},
'album': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['imagestore.Album']"}),
'cmsplugin_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['cms.CMSPlugin']", 'unique': 'True', 'primary_key': 'True'}),
'height': ('django.db.models.fields.IntegerField', [], {'default': '200'}),
'limit': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'skin': ('django.db.models.fields.CharField', [], {'default': "'jcarousel-skin-tango'", 'max_length': '100'}),
'width': ('django.db.models.fields.IntegerField', [], {'default': '200'})
},
'imagestore_cms.imagestorealbumptr': {
'Meta': {'object_name': 'ImagestoreAlbumPtr', 'db_table': "'cmsplugin_imagestorealbumptr'", '_ormbases': ['cms.CMSPlugin']},
'album': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['imagestore.Album']"}),
'cmsplugin_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['cms.CMSPlugin']", 'unique': 'True', 'primary_key': 'True'})
}
}
complete_apps = ['imagestore_cms']

View File

@ -0,0 +1,135 @@
# 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 field 'ImagestoreAlbumCarousel.height'
db.delete_column('cmsplugin_imagestorealbumcarousel', 'height')
# Deleting field 'ImagestoreAlbumCarousel.width'
db.delete_column('cmsplugin_imagestorealbumcarousel', 'width')
# Adding field 'ImagestoreAlbumCarousel.size'
db.add_column('cmsplugin_imagestorealbumcarousel', 'size', self.gf('django.db.models.fields.CharField')(default='72x72', max_length=20), keep_default=False)
# Adding field 'ImagestoreAlbumCarousel.full_size'
db.add_column('cmsplugin_imagestorealbumcarousel', 'full_size', self.gf('django.db.models.fields.CharField')(default='600x600', max_length=20), keep_default=False)
def backwards(self, orm):
# Adding field 'ImagestoreAlbumCarousel.height'
db.add_column('cmsplugin_imagestorealbumcarousel', 'height', self.gf('django.db.models.fields.IntegerField')(default=200), keep_default=False)
# Adding field 'ImagestoreAlbumCarousel.width'
db.add_column('cmsplugin_imagestorealbumcarousel', 'width', self.gf('django.db.models.fields.IntegerField')(default=200), keep_default=False)
# Deleting field 'ImagestoreAlbumCarousel.size'
db.delete_column('cmsplugin_imagestorealbumcarousel', 'size')
# Deleting field 'ImagestoreAlbumCarousel.full_size'
db.delete_column('cmsplugin_imagestorealbumcarousel', 'full_size')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'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'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'imagestore.album': {
'Meta': {'ordering': "('created', 'name')", 'object_name': 'Album'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'head': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'head_of'", 'null': 'True', 'to': "orm['imagestore.Image']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'albums'", 'null': 'True', 'to': "orm['auth.User']"})
},
'imagestore.image': {
'Meta': {'ordering': "('order', 'id')", 'object_name': 'Image'},
'album': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['imagestore.Album']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'image': ('sorl.thumbnail.fields.ImageField', [], {'max_length': '100'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'tags': ('tagging.fields.TagField', [], {}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['auth.User']"})
},
'imagestore_cms.imagestorealbumcarousel': {
'Meta': {'object_name': 'ImagestoreAlbumCarousel', 'db_table': "'cmsplugin_imagestorealbumcarousel'", '_ormbases': ['cms.CMSPlugin']},
'album': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['imagestore.Album']"}),
'cmsplugin_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['cms.CMSPlugin']", 'unique': 'True', 'primary_key': 'True'}),
'full_size': ('django.db.models.fields.CharField', [], {'default': "'600x600'", 'max_length': '20'}),
'limit': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'size': ('django.db.models.fields.CharField', [], {'default': "'72x72'", 'max_length': '20'}),
'skin': ('django.db.models.fields.CharField', [], {'default': "'jcarousel-skin-tango'", 'max_length': '100'})
},
'imagestore_cms.imagestorealbumptr': {
'Meta': {'object_name': 'ImagestoreAlbumPtr', 'db_table': "'cmsplugin_imagestorealbumptr'", '_ormbases': ['cms.CMSPlugin']},
'album': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['imagestore.Album']"}),
'cmsplugin_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['cms.CMSPlugin']", 'unique': 'True', 'primary_key': 'True'})
}
}
complete_apps = ['imagestore_cms']

View File

@ -0,0 +1,210 @@
# 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 field 'ImagestoreAlbumCarousel.template_file'
db.add_column('cmsplugin_imagestorealbumcarousel', 'template_file', self.gf('django.db.models.fields.CharField')(default='cms/plugins/imagestore_album_carousel.html', max_length=100), keep_default=False)
def backwards(self, orm):
# Deleting field 'ImagestoreAlbumCarousel.template_file'
db.delete_column('cmsplugin_imagestorealbumcarousel', 'template_file')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'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'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'image.image': {
'Meta': {'ordering': "('order', 'id')", 'object_name': 'Image', 'db_table': "'imagestore_image'"},
'album': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['imagestore.Album']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'image': ('sorl.thumbnail.fields.ImageField', [], {'max_length': '100'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'place': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['places.GeoPlace']"}),
'tags': ('tagging.fields.TagField', [], {}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['auth.User']"})
},
'imagestore.album': {
'Meta': {'ordering': "('created', 'name')", 'object_name': 'Album'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'head': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'head_of'", 'null': 'True', 'to': "orm['image.Image']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'albums'", 'null': 'True', 'to': "orm['auth.User']"})
},
'imagestore_cms.imagestorealbumcarousel': {
'Meta': {'object_name': 'ImagestoreAlbumCarousel', 'db_table': "'cmsplugin_imagestorealbumcarousel'", '_ormbases': ['cms.CMSPlugin']},
'album': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['imagestore.Album']"}),
'cmsplugin_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['cms.CMSPlugin']", 'unique': 'True', 'primary_key': 'True'}),
'full_size': ('django.db.models.fields.CharField', [], {'default': "'600x600'", 'max_length': '20'}),
'limit': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'size': ('django.db.models.fields.CharField', [], {'default': "'72x72'", 'max_length': '20'}),
'skin': ('django.db.models.fields.CharField', [], {'default': "'jcarousel-skin-tango'", 'max_length': '100'}),
'template_file': ('django.db.models.fields.CharField', [], {'default': "'cms/plugins/imagestore_album_carousel.html'", 'max_length': '100'})
},
'imagestore_cms.imagestorealbumptr': {
'Meta': {'object_name': 'ImagestoreAlbumPtr', 'db_table': "'cmsplugin_imagestorealbumptr'", '_ormbases': ['cms.CMSPlugin']},
'album': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['imagestore.Album']"}),
'cmsplugin_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['cms.CMSPlugin']", 'unique': 'True', 'primary_key': 'True'})
},
'places.geoplace': {
'Meta': {'object_name': 'GeoPlace'},
'addional_info': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'address': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'imagestore_tag': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'latitude': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
'longtitude': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
'metro': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'minuses': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'near_objects': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'near_objects_rel_+'", 'null': 'True', 'to': "orm['places.GeoPlace']"}),
'near_text': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'path_to': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'phone': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'pluses': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'private': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'tags': ('tagging.fields.TagField', [], {}),
'topic': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['pybb.Topic']", 'null': 'True', 'blank': 'True'}),
'topic_on_demand': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['places.PlaceType']", 'null': 'None', 'blank': 'None'}),
'url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'work_time': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
},
'places.placetype': {
'Meta': {'object_name': 'PlaceType'},
'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['pybb.Forum']", 'null': 'True', 'blank': 'True'}),
'forum_user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'icon_style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'name_plural': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'path_to_image': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'private': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'})
},
'pybb.category': {
'Meta': {'ordering': "['position']", 'object_name': 'Category'},
'hidden': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
'position': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'})
},
'pybb.forum': {
'Meta': {'ordering': "['position']", 'object_name': 'Forum'},
'category': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'forums'", 'to': "orm['pybb.Category']"}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'headline': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'hidden': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'moderators': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
'position': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}),
'post_count': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}),
'readed_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'readed_forums'", 'symmetrical': 'False', 'through': "orm['pybb.ForumReadTracker']", 'to': "orm['auth.User']"}),
'topic_count': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
},
'pybb.forumreadtracker': {
'Meta': {'object_name': 'ForumReadTracker'},
'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['pybb.Forum']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'time_stamp': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
},
'pybb.topic': {
'Meta': {'ordering': "['-created']", 'object_name': 'Topic'},
'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
'forum': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'topics'", 'to': "orm['pybb.Forum']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'on_moderation': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'post_count': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}),
'readed_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'readed_topics'", 'symmetrical': 'False', 'through': "orm['pybb.TopicReadTracker']", 'to': "orm['auth.User']"}),
'sticky': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'subscriptions'", 'blank': 'True', 'to': "orm['auth.User']"}),
'updated': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
'views': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'})
},
'pybb.topicreadtracker': {
'Meta': {'object_name': 'TopicReadTracker'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'time_stamp': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'topic': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['pybb.Topic']", 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
}
}
complete_apps = ['imagestore_cms']

View File

@ -0,0 +1,21 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
__author__ = 'zeus'
from cms.models import CMSPlugin
from django.db import models
from imagestore.models import Album
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
class ImagestoreAlbumPtr(CMSPlugin):
album = models.ForeignKey(Album, verbose_name=_('Album'), blank=False, null=False)
class ImagestoreAlbumCarousel(CMSPlugin):
album = models.ForeignKey(Album, verbose_name=_('Album'), blank=False, null=False)
skin = models.CharField(max_length=100, verbose_name=_('Skin'), default='jcarousel-skin-tango')
limit = models.IntegerField(verbose_name=_('Image limit'), blank=True, null=True)
size = models.CharField(max_length=20, verbose_name=_('Thumbnail size'), default='72x72')
full_size = models.CharField(max_length=20, verbose_name=_('Full size view'), default='600x600')
template_file = models.CharField(max_length=100, verbose_name=_('Template file'), default=getattr(settings,'IMAGESTORE_CAROUSEL_TEMPLATE','cms/plugins/imagestore_album_carousel.html'), blank=True, null=True)

View File

@ -0,0 +1,11 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
__author__ = 'zeus'
from django.conf.urls.defaults import *
from imagestore.views import AlbumListView
urlpatterns = patterns('',
url(r'^', include('imagestore.urls', namespace='imagestore')),
)

Binary file not shown.

View File

@ -0,0 +1,276 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-09-29 16:54+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: forms.py:22 models/bases/image.py:44
msgid "Description"
msgstr "Beschreibung"
#: views.py:63
#, python-format
msgid "No Tag found matching \"%s\"."
msgstr "Kein Tag gefunden der auf \"%s\" passt."
#: imagestore_cms/cms_app.py:11
msgid "Imagestore App"
msgstr ""
#: imagestore_cms/cms_plugins.py:14 imagestore_cms/models.py:13
#: imagestore_cms/models.py:16 models/album.py:14 models/bases/image.py:51
#: templates/imagestore/image-scope.html:9 templates/imagestore/image.html:16
msgid "Album"
msgstr ""
#: imagestore_cms/cms_plugins.py:25
msgid "Album as carousel"
msgstr "Album als Karousel"
#: imagestore_cms/models.py:17
msgid "Skin"
msgstr "Skin"
#: imagestore_cms/models.py:18
msgid "Image limit"
msgstr "Bilder Limit"
#: imagestore_cms/models.py:19
msgid "Thumbnail size"
msgstr "Thumbnail Größe"
#: imagestore_cms/models.py:20
msgid "Full size view"
msgstr "Vollbild Ansicht"
#: imagestore_cms/models.py:21
msgid "Template file"
msgstr "Template File"
#: models/album.py:15
msgid "Albums"
msgstr "Alben"
#: models/image.py:13 templates/imagestore/image.html:8
msgid "Image"
msgstr "Bild"
#: models/image.py:14
msgid "Images"
msgstr "Bilder"
#: models/upload.py:84
msgid "images file (.zip)"
msgstr "Bild Datei (.zip)"
#: models/upload.py:85
msgid "Select a .zip file of images to upload into a new Gallery."
msgstr "Zip Datei mit Bilder auswählen um eine neue Gallerie zu erstellen."
#: models/upload.py:90
msgid ""
"Select an album to add these images to. leave this empty to create a new "
"album from the supplied title."
msgstr "Bitte Album für neue Bilder auswählen. Leer lassen um ein neues Album zu erstellen."
#: models/upload.py:95
msgid "New album name"
msgstr "Name für neues Album"
#: models/upload.py:96
msgid ""
"If not empty new album with this name will be created and images will be "
"upload to this album"
msgstr "Falls nicht leer wird ein Album mit diesem Namen erstellt, und hochgeladene Bilder werden in dieses Album hinzugefügt."
#: models/upload.py:98
msgid "tags"
msgstr "Tags"
#: models/upload.py:101
msgid "Album upload"
msgstr "Album upload"
#: models/upload.py:102
msgid "Album uploads"
msgstr "Album uploads"
#: models/bases/album.py:38 models/bases/image.py:48
#: templates/imagestore/image-scope.html:4 templates/imagestore/image.html:13
#: templates/imagestore/user_info.html:7
msgid "User"
msgstr "Benutzer"
#: models/bases/album.py:39
msgid "Name"
msgstr "Name"
#: models/bases/album.py:40 models/bases/image.py:49
msgid "Created"
msgstr "Erstellt"
#: models/bases/album.py:41 models/bases/image.py:50
msgid "Updated"
msgstr "Aktualisiert"
#: models/bases/album.py:42
msgid "Is public"
msgstr "Öffentlich"
#: models/bases/album.py:45 models/bases/image.py:46
msgid "Order"
msgstr "Reihenfolge"
#: models/bases/album.py:72 templates/imagestore/album_list.html:53
msgid "Empty album"
msgstr "Leeres Album"
#: models/bases/album.py:74
msgid "Head"
msgstr ""
#: models/bases/image.py:43
msgid "Title"
msgstr "Titel"
#: models/bases/image.py:45 templates/imagestore/image.html:77
#: templates/imagestore/tag-cloud.html:7
msgid "Tags"
msgstr ""
#: models/bases/image.py:47
msgid "File"
msgstr "Datei"
#: models/bases/image.py:68
msgid "Thumbnail"
msgstr "Vorschau"
#: templates/imagestore/album_delete.html:6
msgid "Are you sure that you would like to delete this album?"
msgstr "Dieses Album wirklich löschen?"
#: templates/imagestore/album_delete.html:10
#: templates/imagestore/image_confirm_delete.html:10
#: templates/imagestore/image_delete.html:10
msgid "No, take me back"
msgstr "Nein, zurück"
#: templates/imagestore/album_delete.html:11
#: templates/imagestore/image_confirm_delete.html:11
#: templates/imagestore/image_delete.html:11
msgid "Yes, I am sure"
msgstr "Ja"
#: templates/imagestore/album_list.html:7
#: templates/imagestore/album_list.html:16
#: templates/imagestore/album_list.html:37
msgid "Albums for user"
msgstr ""
#: templates/imagestore/album_list.html:9
#: templates/imagestore/album_list.html:18
#: templates/imagestore/album_list.html:39
msgid "All albums"
msgstr "Alle Alben"
#: templates/imagestore/album_list.html:60
msgid "user"
msgstr "Benutzer"
#: templates/imagestore/base.html:27
msgid "Home"
msgstr "Home"
#: templates/imagestore/base.html:30 templates/imagestore/tag.html:7
msgid "Gallery"
msgstr "Galerie"
#: templates/imagestore/base.html:46
#: templates/imagestore/forms/image_form.html:7
#: templates/imagestore/forms/image_form.html:11
#: templates/imagestore/forms/image_form.html:15
msgid "Upload image"
msgstr "Bild hochladen"
#: templates/imagestore/base.html:49
msgid "Create new album"
msgstr "Neues Album erstellen"
#: templates/imagestore/image-list.html:14
#: templates/imagestore/image_list.html:55
msgid "Info"
msgstr ""
#: templates/imagestore/image-scope.html:14 templates/imagestore/image.html:19
#: templates/imagestore/tag.html:7 templates/imagestore/tag.html.py:11
#: templates/imagestore/tag.html:15
msgid "Tag"
msgstr ""
#: templates/imagestore/image.html:56
msgid "previous image"
msgstr "Vorheriges Bild"
#: templates/imagestore/image.html:59
msgid "next image"
msgstr "Nächstes Bild"
#: templates/imagestore/image.html:69
msgid "Edit info"
msgstr "Info editieren"
#: templates/imagestore/image.html:70
msgid "Delete image"
msgstr "Bild löschen"
#: templates/imagestore/image.html:85
msgid "Place"
msgstr ""
#: templates/imagestore/image_confirm_delete.html:6
#: templates/imagestore/image_delete.html:6
msgid "Are you sure that you would like to delete this image?"
msgstr "Soll das Bild sicher gelöscht werden?"
#: templates/imagestore/image_list.html:34
#: templates/imagestore/forms/album_form.html:13
#: templates/imagestore/forms/album_form.html:23
msgid "Edit album"
msgstr "Album bearbeiten"
#: templates/imagestore/pagination.html:8
msgid "previous page"
msgstr "Vorherige Seite"
#: templates/imagestore/pagination.html:22
msgid "next page"
msgstr "Nächste Seite"
#: templates/imagestore/forms/album_form.html:7
#: templates/imagestore/forms/album_form.html:15
#: templates/imagestore/forms/album_form.html:25
msgid "Create album"
msgstr "Neues album"
#: templates/imagestore/forms/album_form.html:31
msgid "Save"
msgstr "Speichern"
#: templates/imagestore/forms/image_form.html:19
msgid "Upload"
msgstr "Hochladen"

View File

@ -0,0 +1,78 @@
# 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 'Category'
db.create_table('imagestore_category', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('parent', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='children', null=True, to=orm['imagestore.Category'])),
('slug', self.gf('django.db.models.fields.SlugField')(max_length=200, db_index=True)),
('title', self.gf('django.db.models.fields.CharField')(max_length=200)),
('order', self.gf('django.db.models.fields.IntegerField')()),
('is_public', self.gf('django.db.models.fields.BooleanField')(default=False)),
('lft', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('rght', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('tree_id', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('level', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
))
db.send_create_signal('imagestore', ['Category'])
# Adding model 'Image'
db.create_table('imagestore_image', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('slug', self.gf('django.db.models.fields.SlugField')(db_index=True, max_length=200, null=True, blank=True)),
('title', self.gf('django.db.models.fields.CharField')(max_length=200, null=True, blank=True)),
('description', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
('tags', self.gf('tagging.fields.TagField')()),
('category', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['imagestore.Category'])),
('order', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)),
('is_public', self.gf('django.db.models.fields.BooleanField')(default=True)),
('image', self.gf('sorl.thumbnail.fields.ImageField')(max_length=100)),
))
db.send_create_signal('imagestore', ['Image'])
def backwards(self, orm):
# Deleting model 'Category'
db.delete_table('imagestore_category')
# Deleting model 'Image'
db.delete_table('imagestore_image')
models = {
'imagestore.category': {
'Meta': {'object_name': 'Category'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['imagestore.Category']"}),
'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '200', 'db_index': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
},
'imagestore.image': {
'Meta': {'object_name': 'Image'},
'category': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['imagestore.Category']"}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'image': ('sorl.thumbnail.fields.ImageField', [], {'max_length': '100'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '200', 'null': 'True', 'blank': 'True'}),
'tags': ('tagging.fields.TagField', [], {}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'})
}
}
complete_apps = ['imagestore']

View File

@ -0,0 +1,48 @@
# 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 field 'Image.slug'
db.delete_column('imagestore_image', 'slug')
def backwards(self, orm):
# Adding field 'Image.slug'
db.add_column('imagestore_image', 'slug', self.gf('django.db.models.fields.SlugField')(blank=True, max_length=200, null=True, db_index=True), keep_default=False)
models = {
'imagestore.category': {
'Meta': {'ordering': "('order', 'title')", 'object_name': 'Category'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['imagestore.Category']"}),
'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '200', 'db_index': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
},
'imagestore.image': {
'Meta': {'object_name': 'Image'},
'category': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'images'", 'to': "orm['imagestore.Category']"}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'image': ('sorl.thumbnail.fields.ImageField', [], {'max_length': '100'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'tags': ('tagging.fields.TagField', [], {}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'})
}
}
complete_apps = ['imagestore']

View File

@ -0,0 +1,85 @@
# 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 field 'Image.user'
db.add_column('imagestore_image', 'user', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='images', null=True, to=orm['auth.User']), keep_default=False)
def backwards(self, orm):
# Deleting field 'Image.user'
db.delete_column('imagestore_image', 'user_id')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'imagestore.category': {
'Meta': {'ordering': "('order', 'title')", 'object_name': 'Category'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['imagestore.Category']"}),
'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '200', 'db_index': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
},
'imagestore.image': {
'Meta': {'object_name': 'Image'},
'category': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'images'", 'to': "orm['imagestore.Category']"}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'image': ('sorl.thumbnail.fields.ImageField', [], {'max_length': '100'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'tags': ('tagging.fields.TagField', [], {}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['auth.User']"})
}
}
complete_apps = ['imagestore']

View File

@ -0,0 +1,85 @@
# 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):
# Changing field 'Image.order'
db.alter_column('imagestore_image', 'order', self.gf('django.db.models.fields.IntegerField')())
def backwards(self, orm):
# Changing field 'Image.order'
db.alter_column('imagestore_image', 'order', self.gf('django.db.models.fields.IntegerField')(null=True))
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'imagestore.category': {
'Meta': {'ordering': "('order', 'title')", 'object_name': 'Category'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['imagestore.Category']"}),
'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '200', 'db_index': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
},
'imagestore.image': {
'Meta': {'ordering': "('order', 'id')", 'object_name': 'Image'},
'category': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'images'", 'to': "orm['imagestore.Category']"}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'image': ('sorl.thumbnail.fields.ImageField', [], {'max_length': '100'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'tags': ('tagging.fields.TagField', [], {}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['auth.User']"})
}
}
complete_apps = ['imagestore']

View File

@ -0,0 +1,98 @@
# 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 'Album'
db.create_table('imagestore_album', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('name', self.gf('django.db.models.fields.CharField')(max_length=200)),
('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
('updated', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),
))
db.send_create_signal('imagestore', ['Album'])
def backwards(self, orm):
# Deleting model 'Album'
db.delete_table('imagestore_album')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'imagestore.album': {
'Meta': {'ordering': "('created', 'name')", 'object_name': 'Album'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
'imagestore.category': {
'Meta': {'ordering': "('order', 'title')", 'object_name': 'Category'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['imagestore.Category']"}),
'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '200', 'db_index': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
},
'imagestore.image': {
'Meta': {'ordering': "('order', 'id')", 'object_name': 'Image'},
'category': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'images'", 'to': "orm['imagestore.Category']"}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'image': ('sorl.thumbnail.fields.ImageField', [], {'max_length': '100'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'tags': ('tagging.fields.TagField', [], {}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['auth.User']"})
}
}
complete_apps = ['imagestore']

View File

@ -0,0 +1,106 @@
# 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 field 'Image.created'
db.add_column('imagestore_image', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, null=True, blank=True), keep_default=False)
# Adding field 'Image.updated'
db.add_column('imagestore_image', 'updated', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, null=True, blank=True), keep_default=False)
# Changing field 'Image.category'
db.alter_column('imagestore_image', 'category_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['imagestore.Category']))
def backwards(self, orm):
# Deleting field 'Image.created'
db.delete_column('imagestore_image', 'created')
# Deleting field 'Image.updated'
db.delete_column('imagestore_image', 'updated')
# User chose to not deal with backwards NULL issues for 'Image.category'
raise RuntimeError("Cannot reverse this migration. 'Image.category' and its values cannot be restored.")
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'imagestore.album': {
'Meta': {'ordering': "('created', 'name')", 'object_name': 'Album'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
'imagestore.category': {
'Meta': {'ordering': "('order', 'title')", 'object_name': 'Category'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['imagestore.Category']"}),
'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '200', 'db_index': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
},
'imagestore.image': {
'Meta': {'ordering': "('order', 'id')", 'object_name': 'Image'},
'category': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['imagestore.Category']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'image': ('sorl.thumbnail.fields.ImageField', [], {'max_length': '100'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'tags': ('tagging.fields.TagField', [], {}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['auth.User']"})
}
}
complete_apps = ['imagestore']

View File

@ -0,0 +1,131 @@
# 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 'Category'
db.delete_table('imagestore_category')
# Adding field 'Album.user'
db.add_column('imagestore_album', 'user', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='albums', null=True, to=orm['auth.User']), keep_default=False)
# Adding field 'Album.is_public'
db.add_column('imagestore_album', 'is_public', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False)
# Adding field 'Album.head'
db.add_column('imagestore_album', 'head', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='head_of', null=True, to=orm['imagestore.Image']), keep_default=False)
# Deleting field 'Image.is_public'
db.delete_column('imagestore_image', 'is_public')
# Deleting field 'Image.category'
db.delete_column('imagestore_image', 'category_id')
# Adding field 'Image.album'
db.add_column('imagestore_image', 'album', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='images', null=True, to=orm['imagestore.Album']), keep_default=False)
def backwards(self, orm):
# Adding model 'Category'
db.create_table('imagestore_category', (
('rght', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('parent', self.gf('django.db.models.fields.related.ForeignKey')(related_name='children', null=True, to=orm['imagestore.Category'], blank=True)),
('lft', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('is_public', self.gf('django.db.models.fields.BooleanField')(default=False)),
('slug', self.gf('django.db.models.fields.SlugField')(max_length=200, db_index=True)),
('level', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('title', self.gf('django.db.models.fields.CharField')(max_length=200)),
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('tree_id', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('order', self.gf('django.db.models.fields.IntegerField')(default=0)),
))
db.send_create_signal('imagestore', ['Category'])
# Deleting field 'Album.user'
db.delete_column('imagestore_album', 'user_id')
# Deleting field 'Album.is_public'
db.delete_column('imagestore_album', 'is_public')
# Deleting field 'Album.head'
db.delete_column('imagestore_album', 'head_id')
# Adding field 'Image.is_public'
db.add_column('imagestore_image', 'is_public', self.gf('django.db.models.fields.BooleanField')(default=True), keep_default=False)
# Adding field 'Image.category'
db.add_column('imagestore_image', 'category', self.gf('django.db.models.fields.related.ForeignKey')(related_name='images', null=True, to=orm['imagestore.Category'], blank=True), keep_default=False)
# Deleting field 'Image.album'
db.delete_column('imagestore_image', 'album_id')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'imagestore.album': {
'Meta': {'ordering': "('created', 'name')", 'object_name': 'Album'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'head': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'head_of'", 'null': 'True', 'to': "orm['imagestore.Image']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'albums'", 'null': 'True', 'to': "orm['auth.User']"})
},
'imagestore.image': {
'Meta': {'ordering': "('order', 'id')", 'object_name': 'Image'},
'album': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['imagestore.Album']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'image': ('sorl.thumbnail.fields.ImageField', [], {'max_length': '100'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'tags': ('tagging.fields.TagField', [], {}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['auth.User']"})
}
}
complete_apps = ['imagestore']

View File

@ -0,0 +1,93 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
from django.contrib.auth.management import create_permissions
from django.contrib.auth.models import User, Permission
from django.db.models import get_app
class Migration(DataMigration):
def forwards(self, orm):
app = get_app('imagestore')
create_permissions(app, (), 2)
add_image_permission = Permission.objects.get_by_natural_key('add_image', 'imagestore', 'image')
add_album_permission = Permission.objects.get_by_natural_key('add_album', 'imagestore', 'album')
change_image_permission = Permission.objects.get_by_natural_key('change_image', 'imagestore', 'image')
change_album_permission = Permission.objects.get_by_natural_key('change_album', 'imagestore', 'album')
delete_image_permission = Permission.objects.get_by_natural_key('delete_image', 'imagestore','image')
delete_album_permission = Permission.objects.get_by_natural_key('delete_album', 'imagestore', 'album')
for user in User.objects.all():
user.user_permissions.add(add_image_permission, add_album_permission,)
user.user_permissions.add(change_image_permission, change_album_permission,)
user.user_permissions.add(delete_image_permission, delete_album_permission,)
user.save()
def backwards(self, orm):
"Write your backwards methods here."
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'imagestore.album': {
'Meta': {'ordering': "('created', 'name')", 'object_name': 'Album'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'head': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'head_of'", 'null': 'True', 'to': "orm['imagestore.Image']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'albums'", 'null': 'True', 'to': "orm['auth.User']"})
},
'imagestore.image': {
'Meta': {'ordering': "('order', 'id')", 'object_name': 'Image'},
'album': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['imagestore.Album']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'image': ('sorl.thumbnail.fields.ImageField', [], {'max_length': '100'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'tags': ('tagging.fields.TagField', [], {}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['auth.User']"})
}
}
complete_apps = ['imagestore']

View File

@ -0,0 +1,89 @@
# 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):
# Changing field 'Album.name'
db.alter_column('imagestore_album', 'name', self.gf('django.db.models.fields.CharField')(max_length=20))
# Changing field 'Image.title'
db.alter_column('imagestore_image', 'title', self.gf('django.db.models.fields.CharField')(max_length=20, null=True))
def backwards(self, orm):
# Changing field 'Album.name'
db.alter_column('imagestore_album', 'name', self.gf('django.db.models.fields.CharField')(max_length=200))
# Changing field 'Image.title'
db.alter_column('imagestore_image', 'title', self.gf('django.db.models.fields.CharField')(max_length=200, null=True))
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'imagestore.album': {
'Meta': {'ordering': "('created', 'name')", 'object_name': 'Album'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'head': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'head_of'", 'null': 'True', 'to': "orm['imagestore.Image']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'albums'", 'null': 'True', 'to': "orm['auth.User']"})
},
'imagestore.image': {
'Meta': {'ordering': "('order', 'id')", 'object_name': 'Image'},
'album': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['imagestore.Album']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'image': ('sorl.thumbnail.fields.ImageField', [], {'max_length': '100'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'tags': ('tagging.fields.TagField', [], {}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['auth.User']"})
}
}
complete_apps = ['imagestore']

View File

@ -0,0 +1,172 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
try:
from places.models import GeoPlace
except:
GeoPlace = None
class Migration(SchemaMigration):
def forwards(self, orm):
if GeoPlace:
# Adding field 'Image.place'
db.add_column('imagestore_image', 'place', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='images', null=True, to=orm['places.GeoPlace']), keep_default=False)
def backwards(self, orm):
# Deleting field 'Image.place'
db.delete_column('imagestore_image', 'place_id')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'imagestore.album': {
'Meta': {'ordering': "('created', 'name')", 'object_name': 'Album'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'head': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'head_of'", 'null': 'True', 'to': "orm['imagestore.Image']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'albums'", 'null': 'True', 'to': "orm['auth.User']"})
},
'imagestore.image': {
'Meta': {'ordering': "('order', 'id')", 'object_name': 'Image'},
'album': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['imagestore.Album']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'image': ('sorl.thumbnail.fields.ImageField', [], {'max_length': '100'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'place': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['places.GeoPlace']"}),
'tags': ('tagging.fields.TagField', [], {}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['auth.User']"})
},
'places.geoplace': {
'Meta': {'object_name': 'GeoPlace'},
'addional_info': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'address': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'imagestore_tag': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'latitude': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
'longtitude': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
'metro': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'minuses': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'near_objects': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'near_objects_rel_+'", 'null': 'True', 'to': "orm['places.GeoPlace']"}),
'near_text': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'path_to': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'phone': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'pluses': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'tags': ('tagging.fields.TagField', [], {}),
'topic': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['pybb.Topic']", 'null': 'True', 'blank': 'True'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['places.PlaceType']", 'null': 'None', 'blank': 'None'}),
'work_time': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
},
'places.placetype': {
'Meta': {'object_name': 'PlaceType'},
'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['pybb.Forum']", 'null': 'True', 'blank': 'True'}),
'forum_user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'icon_style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'name_plural': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'path_to_image': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'})
},
'pybb.category': {
'Meta': {'ordering': "['position']", 'object_name': 'Category'},
'hidden': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
'position': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'})
},
'pybb.forum': {
'Meta': {'ordering': "['position']", 'object_name': 'Forum'},
'category': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'forums'", 'to': "orm['pybb.Category']"}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'headline': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'hidden': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'moderators': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
'position': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}),
'post_count': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}),
'readed_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'readed_forums'", 'symmetrical': 'False', 'through': "orm['pybb.ForumReadTracker']", 'to': "orm['auth.User']"}),
'topic_count': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
},
'pybb.forumreadtracker': {
'Meta': {'object_name': 'ForumReadTracker'},
'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['pybb.Forum']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'time_stamp': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
},
'pybb.topic': {
'Meta': {'ordering': "['-created']", 'object_name': 'Topic'},
'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
'forum': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'topics'", 'to': "orm['pybb.Forum']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'post_count': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}),
'readed_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'readed_topics'", 'symmetrical': 'False', 'through': "orm['pybb.TopicReadTracker']", 'to': "orm['auth.User']"}),
'sticky': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'subscriptions'", 'blank': 'True', 'to': "orm['auth.User']"}),
'updated': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
'views': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'})
},
'pybb.topicreadtracker': {
'Meta': {'object_name': 'TopicReadTracker'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'time_stamp': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'topic': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['pybb.Topic']", 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
}
}
complete_apps = ['imagestore']

View File

@ -0,0 +1,98 @@
# 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 'AlbumUpload'
db.create_table('imagestore_albumupload', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('zip_file', self.gf('django.db.models.fields.files.FileField')(max_length=100)),
('album', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['imagestore.Album'], null=True, blank=True)),
('new_album_name', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True)),
('tags', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True)),
))
db.send_create_signal('imagestore', ['AlbumUpload'])
def backwards(self, orm):
# Deleting model 'AlbumUpload'
db.delete_table('imagestore_albumupload')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'imagestore.album': {
'Meta': {'ordering': "('created', 'name')", 'object_name': 'Album'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'head': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'head_of'", 'null': 'True', 'to': "orm['imagestore.Image']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'albums'", 'null': 'True', 'to': "orm['auth.User']"})
},
'imagestore.albumupload': {
'Meta': {'object_name': 'AlbumUpload'},
'album': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['imagestore.Album']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'new_album_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'tags': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'zip_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'})
},
'imagestore.image': {
'Meta': {'ordering': "('order', 'id')", 'object_name': 'Image'},
'album': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['imagestore.Album']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'image': ('sorl.thumbnail.fields.ImageField', [], {'max_length': '100'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'tags': ('tagging.fields.TagField', [], {}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['auth.User']"})
}
}
complete_apps = ['imagestore']

View File

@ -0,0 +1,92 @@
# 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 field 'Album.order'
db.add_column('imagestore_album', 'order', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
def backwards(self, orm):
# Deleting field 'Album.order'
db.delete_column('imagestore_album', 'order')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'imagestore.album': {
'Meta': {'ordering': "('created', 'name')", 'object_name': 'Album'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'head': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'head_of'", 'null': 'True', 'to': "orm['imagestore.Image']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'albums'", 'null': 'True', 'to': "orm['auth.User']"})
},
'imagestore.albumupload': {
'Meta': {'object_name': 'AlbumUpload'},
'album': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['imagestore.Album']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'new_album_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'tags': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'zip_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'})
},
'imagestore.image': {
'Meta': {'ordering': "('order', 'id')", 'object_name': 'Image'},
'album': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['imagestore.Album']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'image': ('sorl.thumbnail.fields.ImageField', [], {'max_length': '100'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'tags': ('tagging.fields.TagField', [], {}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['auth.User']"})
}
}
complete_apps = ['imagestore']

View File

@ -0,0 +1,92 @@
# 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):
# Changing field 'Image.title'
db.alter_column('imagestore_image', 'title', self.gf('django.db.models.fields.CharField')(max_length=100, null=True))
def backwards(self, orm):
# Changing field 'Image.title'
db.alter_column('imagestore_image', 'title', self.gf('django.db.models.fields.CharField')(max_length=20, null=True))
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'imagestore.album': {
'Meta': {'ordering': "('created', 'name')", 'object_name': 'Album'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'head': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'head_of'", 'null': 'True', 'to': "orm['imagestore.Image']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'albums'", 'null': 'True', 'to': "orm['auth.User']"})
},
'imagestore.albumupload': {
'Meta': {'object_name': 'AlbumUpload'},
'album': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['imagestore.Album']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'new_album_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'tags': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'zip_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'})
},
'imagestore.image': {
'Meta': {'ordering': "('order', 'id')", 'object_name': 'Image'},
'album': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['imagestore.Album']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'image': ('sorl.thumbnail.fields.ImageField', [], {'max_length': '100'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'tags': ('tagging.fields.TagField', [], {}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['auth.User']"})
}
}
complete_apps = ['imagestore']

View File

@ -0,0 +1,92 @@
# 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):
# Changing field 'Album.name'
db.alter_column('imagestore_album', 'name', self.gf('django.db.models.fields.CharField')(max_length=100))
def backwards(self, orm):
# Changing field 'Album.name'
db.alter_column('imagestore_album', 'name', self.gf('django.db.models.fields.CharField')(max_length=20))
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'imagestore.album': {
'Meta': {'ordering': "('created', 'name')", 'object_name': 'Album'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'head': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'head_of'", 'null': 'True', 'to': "orm['imagestore.Image']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'albums'", 'null': 'True', 'to': "orm['auth.User']"})
},
'imagestore.albumupload': {
'Meta': {'object_name': 'AlbumUpload'},
'album': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['imagestore.Album']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'new_album_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'tags': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'zip_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'})
},
'imagestore.image': {
'Meta': {'ordering': "('order', 'id')", 'object_name': 'Image'},
'album': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['imagestore.Album']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'image': ('sorl.thumbnail.fields.ImageField', [], {'max_length': '100'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'tags': ('tagging.fields.TagField', [], {}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'images'", 'null': 'True', 'to': "orm['auth.User']"})
}
}
complete_apps = ['imagestore']

View File

@ -0,0 +1,5 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
__author__ = 'zeus'

View File

@ -0,0 +1,19 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
__author__ = 'zeus'
from imagestore.utils import load_class, get_model_string
from django.conf import settings
Album = load_class(getattr(settings, 'IMAGESTORE_ALBUM_MODEL', 'imagestore.models.album.Album'))
Image = load_class(getattr(settings, 'IMAGESTORE_IMAGE_MODEL', 'imagestore.models.image.Image'))
# This labels and classnames used to generate permissons labels
image_applabel = Image._meta.app_label
image_classname = Image.__name__.lower()
album_applabel = Album._meta.app_label
album_classname = Album.__name__.lower()
from upload import AlbumUpload

View File

@ -0,0 +1,16 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
__author__ = 'zeus'
from bases.album import BaseAlbum
from django.utils.translation import ugettext_lazy as _
from imagestore.utils import load_class, get_model_string
class Album(BaseAlbum):
class Meta(BaseAlbum.Meta):
abstract = False
verbose_name = _('Album')
verbose_name_plural = _('Albums')
app_label = 'imagestore'

View File

@ -0,0 +1,5 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
__author__ = 'zeus'

View File

@ -0,0 +1,75 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
__author__ = 'zeus'
from django.db import models
from django.db.models import permalink
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from sorl.thumbnail import get_thumbnail
try:
from django.contrib.auth import get_user_model
User = get_user_model()
except ImportError:
from django.contrib.auth.models import User
try:
import Image as PILImage
except ImportError:
from PIL import Image as PILImage
from imagestore.utils import get_model_string
SELF_MANAGE = getattr(settings, 'IMAGESTORE_SELF_MANAGE', True)
class BaseAlbum(models.Model):
class Meta(object):
abstract = True
ordering = ('order', 'created', 'name')
permissions = (
('moderate_albums', 'View, update and delete any album'),
)
user = models.ForeignKey(User, verbose_name=_('User'), null=True, blank=True, related_name='albums')
name = models.CharField(_('Name'), max_length=100, blank=False, null=False)
created = models.DateTimeField(_('Created'), auto_now_add=True)
updated = models.DateTimeField(_('Updated'), auto_now=True)
is_public = models.BooleanField(_('Is public'), default=True)
head = models.ForeignKey(get_model_string('Image'), related_name='head_of', null=True, blank=True, on_delete=models.SET_NULL)
order = models.IntegerField(_('Order'), default=0)
def get_head(self):
if self.head:
return self.head
else:
if self.images.all().count()>0:
self.head = self.images.all()[0]
self.save()
return self.head
else:
return None
@permalink
def get_absolute_url(self):
return 'imagestore:album', (), {'album_id': self.id}
def __unicode__(self):
return self.name
def admin_thumbnail(self):
img = self.get_head()
if img:
try:
return '<img src="%s">' % get_thumbnail(img.image, '100x100', crop='center').url
except IOError:
return 'IOError'
return _('Empty album')
admin_thumbnail.short_description = _('Head')
admin_thumbnail.allow_tags = True

View File

@ -0,0 +1,104 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
__author__ = 'zeus'
from django.db import models
from django.db.models import permalink
from sorl.thumbnail.helpers import ThumbnailError
from tagging.fields import TagField
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from sorl.thumbnail import ImageField, get_thumbnail
from django.contrib.auth.models import Permission
from django.db.models.signals import post_save
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist
try:
from django.contrib.auth import get_user_model
User = get_user_model()
except ImportError:
from django.contrib.auth.models import User
try:
import Image as PILImage
except ImportError:
from PIL import Image as PILImage
from imagestore.utils import get_file_path, get_model_string
SELF_MANAGE = getattr(settings, 'IMAGESTORE_SELF_MANAGE', True)
class BaseImage(models.Model):
class Meta(object):
abstract = True
ordering = ('order', 'id')
permissions = (
('moderate_images', 'View, update and delete any image'),
)
title = models.CharField(_('Title'), max_length=100, blank=True, null=True)
description = models.TextField(_('Description'), blank=True, null=True)
tags = TagField(_('Tags'), blank=True)
order = models.IntegerField(_('Order'), default=0)
image = ImageField(verbose_name = _('File'), upload_to=get_file_path)
user = models.ForeignKey(User, verbose_name=_('User'), null=True, blank=True, related_name='images')
created = models.DateTimeField(_('Created'), auto_now_add=True, null=True)
updated = models.DateTimeField(_('Updated'), auto_now=True, null=True)
album = models.ForeignKey(get_model_string('Album'), verbose_name=_('Album'), null=True, blank=True, related_name='images')
@permalink
def get_absolute_url(self):
return 'imagestore:image', (), {'pk': self.id}
def __unicode__(self):
return '%s'% self.id
def admin_thumbnail(self):
try:
return '<img src="%s">' % get_thumbnail(self.image, '100x100', crop='center').url
except IOError:
return 'IOError'
except ThumbnailError, ex:
return 'ThumbnailError, %s' % ex.message
admin_thumbnail.short_description = _('Thumbnail')
admin_thumbnail.allow_tags = True
#noinspection PyUnusedLocal
def setup_imagestore_permissions(instance, created, **kwargs):
if not created:
return
try:
from imagestore.models import Album, Image
album_type = ContentType.objects.get(
#app_label=load_class('imagestore.models.Album')._meta.app_label,
app_label = Album._meta.app_label,
name='Album'
)
image_type = ContentType.objects.get(
#app_label=load_class('imagestore.models.Image')._meta.app_label,
app_label = Image._meta.app_label,
name='Image'
)
add_image_permission = Permission.objects.get(codename='add_image', content_type=image_type)
add_album_permission = Permission.objects.get(codename='add_album', content_type=album_type)
change_image_permission = Permission.objects.get(codename='change_image', content_type=image_type)
change_album_permission = Permission.objects.get(codename='change_album', content_type=album_type)
delete_image_permission = Permission.objects.get(codename='delete_image', content_type=image_type)
delete_album_permission = Permission.objects.get(codename='delete_album', content_type=album_type)
instance.user_permissions.add(add_image_permission, add_album_permission,)
instance.user_permissions.add(change_image_permission, change_album_permission,)
instance.user_permissions.add(delete_image_permission, delete_album_permission,)
except ObjectDoesNotExist:
# Permissions are not yet installed or conten does not created yet
# probaly this is first
pass
if SELF_MANAGE:
post_save.connect(setup_imagestore_permissions, User)

View File

@ -0,0 +1,15 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
__author__ = 'zeus'
from bases.image import BaseImage
from django.utils.translation import ugettext_lazy as _
from imagestore.utils import load_class, get_model_string
class Image(BaseImage):
class Meta(BaseImage.Meta):
abstract = False
verbose_name = _('Image')
verbose_name_plural = _('Images')
app_label = 'imagestore'

112
imagestore/models/upload.py Normal file
View File

@ -0,0 +1,112 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
from django.core.exceptions import ImproperlyConfigured
from django.utils.importlib import import_module
__author__ = 'zeus'
import os
import zipfile
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from django.core.files.base import ContentFile
try:
import Image as PILImage
except ImportError:
from PIL import Image as PILImage
from imagestore.models import Album, Image
TEMP_DIR = getattr(settings, 'TEMP_DIR', 'temp/')
def process_zipfile(uploaded_album):
if os.path.isfile(uploaded_album.zip_file.path):
# TODO: implement try-except here
zip = zipfile.ZipFile(uploaded_album.zip_file.path)
bad_file = zip.testzip()
if bad_file:
raise Exception('"%s" in the .zip archive is corrupt.' % bad_file)
if not uploaded_album.album:
uploaded_album.album = Album.objects.create(name=uploaded_album.new_album_name)
from cStringIO import StringIO
for filename in sorted(zip.namelist()):
if filename.startswith('__'): # do not process meta files
continue
print filename
data = zip.read(filename)
if len(data):
try:
# the following is taken from django.forms.fields.ImageField:
# load() could spot a truncated JPEG, but it loads the entire
# image in memory, which is a DoS vector. See #3848 and #18520.
# verify() must be called immediately after the constructor.
PILImage.open(StringIO(data)).verify()
except Exception, ex:
# if a "bad" file is found we just skip it.
print('Error verify image: %s' % ex.message)
continue
if hasattr(data, 'seek') and callable(data.seek):
print 'seeked'
data.seek(0)
try:
img = Image(album=uploaded_album.album)
img.image.save(filename, ContentFile(data))
img.save()
except Exception, ex:
print('error create Image: %s' % ex.message)
zip.close()
uploaded_album.delete()
upload_processor_function = getattr(settings, 'IMAGESTORE_UPLOAD_ALBUM_PROCESSOR', None)
upload_processor = process_zipfile
if upload_processor_function:
i = upload_processor_function.rfind('.')
module, attr = upload_processor_function[:i], upload_processor_function[i+1:]
try:
mod = import_module(module)
except ImportError as e:
raise ImproperlyConfigured('Error importing request processor module %s: "%s"' % (module, e))
try:
upload_processor = getattr(mod, attr)
except AttributeError:
raise ImproperlyConfigured('Module "%s" does not define a "%s" callable request processor' % (module, attr))
class AlbumUpload(models.Model):
"""
Just re-written django-photologue GalleryUpload method
"""
zip_file = models.FileField(_('images file (.zip)'), upload_to=TEMP_DIR,
help_text=_('Select a .zip file of images to upload into a new Gallery.'))
album = models.ForeignKey(
Album,
null=True,
blank=True,
help_text=_('Select an album to add these images to. leave this empty to create a new album from the supplied title.')
)
new_album_name = models.CharField(
max_length=255,
blank=True,
verbose_name=_('New album name'),
help_text=_('If not empty new album with this name will be created and images will be upload to this album')
)
tags = models.CharField(max_length=255, blank=True, verbose_name=_('tags'))
class Meta(object):
verbose_name = _('Album upload')
verbose_name_plural = _('Album uploads')
app_label = 'imagestore'
def save(self, *args, **kwargs):
super(AlbumUpload, self).save(*args, **kwargs)
upload_processor(self)
def delete(self, *args, **kwargs):
storage, path = self.zip_file.storage, self.zip_file.path
super(AlbumUpload, self).delete(*args, **kwargs)
storage.delete(path)

Some files were not shown because too many files have changed in this diff Show More