Skip to content
Browse files

Code cleanups

  • Loading branch information...
1 parent 2afa39e commit 38a305e0a42a1b0ee4b31fe08053bc28aa8d057e @rosarior committed Feb 10, 2013
View
1 apps/common/__init__.py
@@ -15,4 +15,3 @@
# You should have received a copy of the GNU General Public License
# along with descartes-bi. If not, see <http://www.gnu.org/licenses/>.
#
-
View
144 apps/common/dumpscript.py
@@ -32,7 +32,7 @@
Generates a Python script that will repopulate the database using objects.
The advantage of this approach is that it is easy to understand, and more
flexible than directly populating the database, or using XML.
-
+
* It also allows for new defaults to take effect and only transfers what is
needed.
* If a new database schema has a NEW ATTRIBUTE, it is simply not
@@ -43,19 +43,23 @@
* Problems may only occur if there is a new model and is now a required
ForeignKey for an existing model. But this is easy to fix by editing the
populate script :)
-
+
Improvements:
See TODOs and FIXMEs scattered throughout :-)
-
+
"""
import sys
+
from django.db import models
+from django.db.models import get_app, get_apps, get_model
+from django.db.models import get_models as get_all_models
+from django.db.models.query import CollectedObjects
+from django.contrib.contenttypes.models import ContentType
+from django.contrib.contenttypes.generic import GenericRelation
from django.core.exceptions import ObjectDoesNotExist
from django.core.management.base import BaseCommand
from django.utils.encoding import smart_unicode, force_unicode
-from django.contrib.contenttypes.models import ContentType
-from django.contrib.contenttypes.generic import GenericRelation
class Command(BaseCommand):
@@ -80,21 +84,16 @@ def get_models(app_labels):
TODO: If a required model is referenced, it should also be included.
Or at least discovered with a get_or_create() call.
"""
-
- from django.db.models import get_app, get_apps, get_model
- from django.db.models import get_models as get_all_models
-
# These models are not to be output, e.g. because they can be generated automatically
# TODO: This should be "appname.modelname" string
- from django.contrib.contenttypes.models import ContentType
- EXCLUDED_MODELS = (ContentType, )
+ EXCLUDED_MODELS = (ContentType,)
models = []
# If no app labels are given, return all
if not app_labels:
for app in get_apps():
- models += [ m for m in get_all_models(app) if m not in EXCLUDED_MODELS ]
+ models += [m for m in get_all_models(app) if m not in EXCLUDED_MODELS]
# Get all relevant apps
for app_label in app_labels:
@@ -104,7 +103,7 @@ def get_models(app_labels):
models.append(get_model(app_label, model_name))
# Get all models for a given app
else:
- models += [ m for m in get_all_models(get_app(app_label)) if m not in EXCLUDED_MODELS ]
+ models += [m for m in get_all_models(get_app(app_label)) if m not in EXCLUDED_MODELS]
return models
@@ -119,7 +118,7 @@ class Code(object):
def __init__(self):
self.imports = {}
self.indent = -1
-
+
def __str__(self):
""" Returns a string representation of this script.
"""
@@ -133,15 +132,15 @@ def get_import_lines(self):
""" Takes the stored imports and converts them to lines
"""
if self.imports:
- return [ "from %s import %s" % (value, key) for key, value in self.imports.items() ]
+ return ["from %s import %s" % (value, key) for key, value in self.imports.items()]
else:
return []
import_lines = property(get_import_lines)
-
+
class ModelCode(Code):
" Produces a python script that can recreate data for a given model class. "
-
+
def __init__(self, model, context={}):
self.model = model
self.context = context
@@ -152,7 +151,7 @@ def get_imports(self):
""" Returns a dictionary of import statements, with the variable being
defined as the key.
"""
- return { self.model.__name__: smart_unicode(self.model.__module__) }
+ return {self.model.__name__: smart_unicode(self.model.__module__)}
imports = property(get_imports)
def get_lines(self):
@@ -162,7 +161,7 @@ def get_lines(self):
code = []
for counter, item in enumerate(self.model.objects.all()):
- instance = InstanceCode(instance=item, id=counter+1, context=self.context)
+ instance = InstanceCode(instance=item, id=counter + 1, context=self.context)
self.instances.append(instance)
if instance.waiting_list:
code += instance.lines
@@ -203,7 +202,7 @@ def __init__(self, instance, id, context={}):
# a foreign key instead. The logic is, if the field creates a table, then it needs
# to be treated separately. Unfortunately, the GenericRelation field sets the
# create_table attribute to False.
- if not hasattr(field,'creates_table') or field.creates_table or isinstance(field, GenericRelation):
+ if not hasattr(field, 'creates_table') or field.creates_table or isinstance(field, GenericRelation):
self.many_to_many_waiting_list[field] = list(getattr(self.instance, field.name).all())
def get_lines(self, force=False):
@@ -214,86 +213,84 @@ def get_lines(self, force=False):
will be no waiting: a get_or_create() call is written instead.
"""
#HACK but works :)
- force=True
+ force = True
code_lines = []
-
+
# Don't return anything if this is an instance that should be skipped
if self.skip():
return []
-
+
# Initialise our new object
# e.g. model_name_35 = Model()
code_lines += self.instantiate()
-
+
# Add each field
# e.g. model_name_35.field_one = 1034.91
# model_name_35.field_two = "text"
code_lines += self.get_waiting_list()
-
+
if force:
# TODO: Check that M2M are not affected
code_lines += self.get_waiting_list(force=force)
-
+
# Print the save command for our new object
# e.g. model_name_35.save()
if code_lines:
code_lines.append("%s.save()\n" % (self.variable_name))
-
+
code_lines += self.get_many_to_many_lines(force=force)
-
+
return code_lines
lines = property(get_lines)
-
+
def skip(self):
""" Determine whether or not this object should be skipped.
If this model is a parent of a single subclassed instance, skip it.
The subclassed instance will create this parent instance for us.
TODO: Allow the user to force its creation?
"""
-
+
if self.skip_me is not None:
return self.skip_me
-
+
try:
# Django trunk since r7722 uses CollectedObjects instead of dict
- from django.db.models.query import CollectedObjects
sub_objects = CollectedObjects()
except ImportError:
# previous versions don't have CollectedObjects
sub_objects = {}
self.instance._collect_sub_objects(sub_objects)
- if reduce(lambda x, y: x+y, [self.model in so._meta.parents for so in sub_objects.keys()]) == 1:
+ if reduce(lambda x, y: x + y, [self.model in so._meta.parents for so in sub_objects.keys()]) == 1:
pk_name = self.instance._meta.pk.name
key = '%s_%s' % (self.model.__name__, getattr(self.instance, pk_name))
self.context[key] = None
self.skip_me = True
else:
self.skip_me = False
-
+
return self.skip_me
-
+
def instantiate(self):
" Write lines for instantiation "
# e.g. model_name_35 = Model()
code_lines = []
-
+
if not self.instantiated:
code_lines.append("%s = %s()" % (self.variable_name, self.model.__name__))
self.instantiated = True
-
+
# Store our variable name for future foreign key references
pk_name = self.instance._meta.pk.name
key = '%s_%s' % (self.model.__name__, getattr(self.instance, pk_name))
self.context[key] = self.variable_name
-
+
return code_lines
-
-
+
def get_waiting_list(self, force=False):
" Add lines for any waiting fields that can be completed now. "
-
+
code_lines = []
-
+
# Process normal fields
for field in list(self.waiting_list):
try:
@@ -308,16 +305,14 @@ def get_waiting_list(self, force=False):
except DoLater, e:
# Move on, maybe next time
continue
-
-
+
return code_lines
-
-
+
def get_many_to_many_lines(self, force=False):
""" Generates lines that define many to many relations for this instance. """
-
+
lines = []
-
+
for field, rel_items in self.many_to_many_waiting_list.items():
for rel_item in list(rel_items):
try:
@@ -331,36 +326,36 @@ def get_many_to_many_lines(self, force=False):
value = "%s.objects.get(%s=%s)" % (rel_item._meta.object_name, pk_name, getattr(rel_item, pk_name))
lines.append('%s.%s.add(%s)' % (self.variable_name, field.name, value))
self.many_to_many_waiting_list[field].remove(rel_item)
-
+
if lines:
lines.append("")
-
+
return lines
-
-
+
+
class Script(Code):
" Produces a complete python script that can recreate data for the given apps. "
-
+
def __init__(self, models, context={}):
self.models = models
self.context = context
-
+
self.indent = -1
self.imports = {}
-
+
def get_lines(self):
""" Returns a list of lists or strings, representing the code body.
Each list is a block, each string is a statement.
"""
- code = [ self.FILE_HEADER.strip() ]
-
+ code = [self.FILE_HEADER.strip()]
+
# Queue and process the required models
for model_class in queue_models(self.models, context=self.context):
sys.stderr.write('Processing model: %s\n' % model_class.model.__name__)
code.append(model_class.import_lines)
code.append("")
code.append(model_class.lines)
-
+
# Process left over foreign keys from cyclic models
for model in self.models:
sys.stderr.write('Re-processing model: %s\n' % model.model.__name__)
@@ -374,44 +369,42 @@ def get_lines(self):
# A user-friendly file header
FILE_HEADER = """
-
+
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-
+
# This file has been automatically generated, changes may be lost if you
# go and generate it again. It was generated with the following command:
# %s
-
+
import datetime
from decimal import Decimal
from django.contrib.contenttypes.models import ContentType
-
+
def run():
""" % " ".join(sys.argv)
-
# HELPER FUNCTIONS
-#-------------------------------------------------------------------------------
-
+#-------------------------------------------------------------------------------
def flatten_blocks(lines, num_indents=-1):
""" Takes a list (block) or string (statement) and flattens it into a string
with indentation.
"""
-
+
# The standard indent is four spaces
INDENTATION = " " * 4
-
+
if not lines:
return ""
-
+
# If this is a string, add the indentation and finish here
if isinstance(lines, basestring):
return INDENTATION * num_indents + lines
-
+
# If this is not a string, join the lines and recurse
- return "\n".join([ flatten_blocks(line, num_indents+1) for line in lines ])
+ return "\n".join([flatten_blocks(line, num_indents + 1) for line in lines])
def get_attribute_value(item, field, context, force=False):
@@ -462,11 +455,11 @@ def get_attribute_value(item, field, context, force=False):
else:
raise DoLater('(FK) %s.%s\n' % (item.__class__.__name__, field.name))
-
# A normal field (e.g. a python built-in)
else:
return repr(value)
+
def queue_models(models, context):
""" Works an an appropriate ordering for the models.
This isn't essential, but makes the script look nicer because
@@ -502,7 +495,7 @@ def queue_models(models, context):
allowed_cycles -= 1
if allowed_cycles <= 0:
# Add the remaining models, but do not remove them from the model list
- missing_models = [ ModelCode(model=m, context=context) for m in models ]
+ missing_models = [ModelCode(model=m, context=context) for m in models]
model_queue += missing_models
# Replace the models with the model class objects
# (sure, this is a little bit of hackery)
@@ -518,7 +511,7 @@ def check_dependencies(model, model_queue):
" Check that all the depenedencies for this model are already in the queue. "
# A list of allowed links: existing fields, itself and the special case ContentType
- allowed_links = [ m.model.__name__ for m in model_queue ] + [model.__name__, 'ContentType']
+ allowed_links = [m.model.__name__ for m in model_queue] + [model.__name__, 'ContentType']
# For each ForeignKey or ManyToMany field, check that a link is possible
for field in model._meta.fields + model._meta.many_to_many:
@@ -528,12 +521,11 @@ def check_dependencies(model, model_queue):
return True
-
# EXCEPTIONS
#-------------------------------------------------------------------------------
-
class SkipValue(Exception):
""" Value could not be parsed or should simply be skipped. """
-
+
+
class DoLater(Exception):
""" Value could not be parsed or should simply be skipped. """
View
3 apps/common/forms.py
@@ -18,5 +18,6 @@
from django import forms
+
class UploadFileForm(forms.Form):
- file = forms.FileField()
+ file = forms.FileField()
View
37 apps/common/runscript.py
@@ -21,29 +21,25 @@
"""
from django.core.management.base import BaseCommand
-from django.core.management.color import no_style
from optparse import make_option
-import sys
-import os
-
-try:
- set
-except NameError:
- from sets import Set as set # Python 2.3 fallback
+
def ERROR(string):
- raise Exception, string
+ raise Exception(string)
+
def ERROR2(string):
- raise Exception, string
+ raise Exception(string)
+
def NOTICE(string):
- raise Exception, string
+ raise Exception(string)
+
def NOTICE2(string):
- raise Exception, string
-
-
+ raise Exception(string)
+
+
class Command(BaseCommand):
option_list = BaseCommand.option_list + (
make_option('--fixtures', action='store_true', dest='infixtures',
@@ -61,16 +57,13 @@ class Command(BaseCommand):
args = "script [script ...]"
def handle(self, *scripts, **options):
- from django.db.models import get_pps
-
#NOTICE = self.style.SQL_TABLE
#NOTICE2 = self.style.SQL_FIELD
#ERROR = self.style.ERROR_OUTPUT
#ERROR2 = self.style.NOTICE
subdirs = []
-
if not options.get('noscripts'):
subdirs.append('scripts')
if options.get('infixtures'):
@@ -99,7 +92,7 @@ def run_script(mod):
# TODO: add arguments to run
try:
mod.run()
- except Exception, e:
+ except Exception as e:
if silent:
return
if verbosity > 0:
@@ -131,7 +124,7 @@ def find_modules_for_script(script):
modules = []
# first look in apps
for app in get_apps():
- app_name = app.__name__.split(".")[:-1] # + ['fixtures']
+ app_name = app.__name__.split(".")[:-1] # + ['fixtures']
for subdir in subdirs:
mod = my_import(".".join(app_name + [subdir, script]))
if mod:
@@ -156,15 +149,15 @@ def find_modules_for_script(script):
for script in scripts:
modules = find_modules_for_script(script)
if not modules:
- if verbosity>0 and not silent:
+ if verbosity > 0 and not silent:
print ERROR("No module for script '%s' found" % script)
for mod in modules:
- if verbosity>1:
+ if verbosity > 1:
print NOTICE2("Running script '%s' ..." % mod.__name__)
run_script(mod)
# Backwards compatibility for Django r9110
-if not [opt for opt in Command.option_list if opt.dest=='verbosity']:
+if not [opt for opt in Command.option_list if opt.dest == 'verbosity']:
Command.option_list += (
make_option('--verbosity', '-v', action="store", dest="verbosity",
default='1', type='choice', choices=['0', '1', '2'],
View
1 apps/common/templatetags/__init__.py
@@ -15,4 +15,3 @@
# You should have received a copy of the GNU General Public License
# along with descartes-bi. If not, see <http://www.gnu.org/licenses/>.
#
-
View
2 apps/common/templatetags/project_tags.py
@@ -20,9 +20,9 @@
register = Library()
+
@register.simple_tag
def project_name():
"""Tag to return the current project's title"""
from django.conf import settings
return settings.PROJECT_TITLE
-
View
60 apps/common/views.py
@@ -15,28 +15,34 @@
# You should have received a copy of the GNU General Public License
# along with descartes-bi. If not, see <http://www.gnu.org/licenses/>.
#
+import datetime
+import os
+import re
-from django.http import HttpResponse, HttpResponseRedirect
-from django.shortcuts import render_to_response, get_object_or_404
-from django.utils.translation import ugettext as _
-from django.contrib.auth.decorators import login_required
-from django.http import HttpResponseRedirect
-from django.template import Context
+from django import http
from django.conf import settings
+from django.contrib.auth.decorators import login_required
+from django.core.files import File
+from django.core.management.commands import reset
+from django.core.servers.basehttp import FileWrapper
+from django.http import HttpResponse, HttpResponseRedirect
+from django.shortcuts import render_to_response
from django.template import loader, RequestContext
-from django import http
+
+from forms import UploadFileForm
+import runscript
+import dumpscript
-def error500(request, template_name = '500.html'):
+def error500(request, template_name='500.html'):
#TODO: if user is admin include debug info
t = loader.get_template(template_name)
return http.HttpResponseServerError(t.render(RequestContext(request, {
- 'project_name' : settings.PROJECT_TITLE })))
+ 'project_name': settings.PROJECT_TITLE})))
def get_svn_revision(path=None):
- import os, re
rev = None
entries_path = '%s/.svn/entries' % path
@@ -59,12 +65,12 @@ def get_svn_revision(path=None):
return u'svn-r%s' % rev
return u'svn-unknown'
-
+
def set_language(request):
if request.method == "GET":
request.session['django_language'] = request.GET.get('language', 'en')
- return HttpResponseRedirect(request.META.get('HTTP_REFERER','/'))
+ return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
def home(request):
@@ -73,15 +79,11 @@ def home(request):
def about(request):
- import settings
-
- return render_to_response('about.html', { 'revision' : get_svn_revision(settings.PROJECT_ROOT ) },
+ return render_to_response('about.html', {'revision': get_svn_revision(settings.PROJECT_ROOT)},
context_instance=RequestContext(request))
def get_project_root():
- from django.conf import settings
- import os
""" get the project root directory """
settings_mod = __import__(settings.SETTINGS_MODULE, {}, {}, [''])
return os.path.dirname(os.path.abspath(settings_mod.__file__))
@@ -90,22 +92,12 @@ def get_project_root():
@login_required
def dbbackup(request):
# from django_extensions.management.commands import dumpscript
- import os
- import datetime
-
- from django.core.servers.basehttp import FileWrapper
- from django.conf import settings
- from django.core.files import File
-
- import tempfile
- import dumpscript
-
ct = datetime.datetime.now()
if not (request.user.is_authenticated() and request.user.is_staff):
raise http.Http404
- models = dumpscript.get_models(['reports','replicate','auth'])
+ models = dumpscript.get_models(['reports', 'replicate', 'auth'])
context = {}
@@ -124,7 +116,6 @@ def dbbackup(request):
@login_required
def dbrestore(request):
- from forms import UploadFileForm
error_message = ''
error_title = ''
if request.method == 'POST':
@@ -143,17 +134,12 @@ def dbrestore(request):
form = UploadFileForm()
return render_to_response('dbrestore.html', {
'form': form,
- 'error_title' : error_title,
- 'error_message' : error_message
- }, context_instance=RequestContext(request))
+ 'error_title': error_title,
+ 'error_message': error_message
+ }, context_instance=RequestContext(request))
def _handle_restore_file(uploaded_file):
- import sys
- import os.path
- from django.core.management.commands import reset
- import runscript
-
#Turn into a real file
dest_path = "%s/scripts/%s" % (get_project_root(), uploaded_file)
destination = open(dest_path, 'wb+')
View
1 apps/reports/__init__.py
@@ -15,4 +15,3 @@
# You should have received a copy of the GNU General Public License
# along with descartes-bi. If not, see <http://www.gnu.org/licenses/>.
#
-
View
52 apps/reports/admin.py
@@ -20,30 +20,30 @@
GroupPermissionFilterValues, UserPermissionFilterValues, \
UserPermission, GroupPermission, Report, Serie, Filterset, Filter, \
Menuitem, SeriesStatistic, ReportStatistic
-
+
from django.contrib import admin
from django import forms
from django.utils.translation import ugettext_lazy as _
from django.db.models.fields import CharField
+
#clone_objects Copyright (C) 2009 Rune Bromer
#http://www.bromer.eu/2009/05/23/a-generic-copyclone-action-for-django-11/
def clone_objects(objects, title_fieldnames):
def clone(from_object, title_fieldnames):
args = dict([(fld.name, getattr(from_object, fld.name))
- for fld in from_object._meta.fields
- if fld is not from_object._meta.pk])
+ for fld in from_object._meta.fields
+ if fld is not from_object._meta.pk])
for field in from_object._meta.fields:
if field.name in title_fieldnames:
if isinstance(field, CharField):
- args[field.name] = getattr(from_object, field.name) + \
- (" (%s) " % unicode(_(u'copy')))
+ args[field.name] = getattr(from_object, field.name) + (" (%s) " % unicode(_(u'copy')))
return from_object.__class__.objects.create(**args)
- if not hasattr(objects,'__iter__'):
- objects = [ objects ]
+ if not hasattr(objects, '__iter__'):
+ objects = [objects]
# We always have the objects in a list now
objs = []
@@ -95,11 +95,11 @@ class UserPermissionFilterValuesInline(admin.StackedInline):
model = UserPermissionFilterValues
extra = 1
classes = ('collapse-open',)
- allow_add = True
+ allow_add = True
class UserPermissionAdmin(admin.ModelAdmin):
- radio_fields = {'union':admin.HORIZONTAL}
+ radio_fields = {'union': admin.HORIZONTAL}
list_display = ('user', 'get_reports')
filter_horizontal = ('reports',)
inlines = [
@@ -112,7 +112,7 @@ class GroupPermissionFilterValuesInline(admin.StackedInline):
model = GroupPermissionFilterValues
extra = 1
classes = ('collapse-open',)
- allow_add = True
+ allow_add = True
class GroupPermissionAdmin(admin.ModelAdmin):
@@ -156,16 +156,16 @@ class SerieAdmin(admin.ModelAdmin):
order = 2
fieldsets = (
- (None, {
- 'fields': ('name', 'label', 'tick_format', 'query',
- 'description')
- }),
- (_(u'Validation'), {
- 'classes': ('collapse-open',),
- 'fields': ('validated', 'validated_date', 'validated_person',
- 'validation_description')
- }),
- )
+ (None, {
+ 'fields': ('name', 'label', 'tick_format', 'query',
+ 'description')
+ }),
+ (_(u'Validation'), {
+ 'classes': ('collapse-open',),
+ 'fields': ('validated', 'validated_date', 'validated_person',
+ 'validation_description')
+ }),
+ )
actions = ['clone']
@@ -178,7 +178,7 @@ def clone(self, request, queryset):
message_bit = _(u"%s series were") % queryset.count()
self.message_user(request, _(u"%s copied.") % message_bit)
- clone.short_description = _(u"Copy the selected object")
+ clone.short_description = _(u"Copy the selected object")
class SerieInline(admin.StackedInline):
@@ -189,17 +189,17 @@ class SerieInline(admin.StackedInline):
class ReportAdmin(admin.ModelAdmin):
- radio_fields = {'type':admin.VERTICAL, 'orientation':admin.HORIZONTAL}
+ radio_fields = {'type': admin.VERTICAL, 'orientation': admin.HORIZONTAL}
list_display = ('title', 'description', 'type', 'get_series',
'get_parents')
filter_horizontal = ('filtersets',)
search_fields = ['title', 'description']
search_fields_verbose = ['Title', 'Description']
exclude = ('series',)
inlines = [
- SerieInline,
+ SerieInline,
]
- order = 3
+ order = 3
actions = ['clone']
@@ -212,12 +212,12 @@ def clone(self, request, queryset):
message_bit = _(u"%s reports were") % queryset.count()
self.message_user(request, _(u"%s copied.") % message_bit)
- clone.short_description = _(u"Copy the selected object")
+ clone.short_description = _(u"Copy the selected object")
class MenuitemAdmin(admin.ModelAdmin):
list_display = ('title', 'order', 'get_reports')
- list_editable = ('order',)
+ list_editable = ('order',)
filter_horizontal = ('reports',)
order = 4
View
42 apps/reports/forms.py
@@ -18,8 +18,10 @@
from django import forms
from django.utils.translation import ugettext_lazy as _
+
from models import FILTER_TYPE_DATE, FILTER_TYPE_COMBO, FILTER_TYPE_MONTH
+
class FilterForm(forms.Form):
def __init__(self, filtersets, user, *args, **kwargs):
#cannot move this from here until leading _ is removed
@@ -30,10 +32,10 @@ def __init__(self, filtersets, user, *args, **kwargs):
if f.filter.type == FILTER_TYPE_DATE:
f.filter.execute_function()
self.fields[f.filter.name] = forms.DateField(('%m/%d/%Y',),
- initial=f.filter.default, required=False,
- label=f.filter.label,
- widget=forms.DateInput(format='%m/%d/%Y',
- attrs={'size':'10'}))
+ initial=f.filter.default, required=False,
+ label=f.filter.label,
+ widget=forms.DateInput(format='%m/%d/%Y',
+ attrs={'size': '10'}))
elif f.filter.type == FILTER_TYPE_COMBO:
results = _get_user_filters_limits(user)
#TODO: try this later on
@@ -52,25 +54,23 @@ def __init__(self, filtersets, user, *args, **kwargs):
if f.filter in results:
if 'default' in results[f.filter]:
f.filter.default = results[f.filter]['default']
-
- self.fields[f.filter.name] = \
- forms.ChoiceField(initial=f.filter.default, required=False,
- label=f.filter.label, choices = choices)
+
+ self.fields[f.filter.name] = forms.ChoiceField(initial=f.filter.default, required=False,
+ label=f.filter.label, choices=choices)
elif f.filter.type == FILTER_TYPE_MONTH:
- self.fields[f.filter.name] = \
- forms.ChoiceField(initial=f.filter.default, required=False,
- label=f.filter.label,
- choices = (('1',_(u'January')),('2', _(u'February')),
- ('3', _(u'March')),('4', _(u'April')),
- ('5', _(u'May')),('6', _(u'June')),
- ('7', _(u'July')),('8', _(u'August')),
- ('9', _(u'September')),('10', _(u'October')),
- ('11', _(u'November')),('12', _(u'December'))))
+ self.fields[f.filter.name] = forms.ChoiceField(initial=f.filter.default, required=False,
+ label=f.filter.label,
+ choices=(('1', _(u'January')), ('2', _(u'February')),
+ ('3', _(u'March')), ('4', _(u'April')),
+ ('5', _(u'May')), ('6', _(u'June')),
+ ('7', _(u'July')), ('8', _(u'August')),
+ ('9', _(u'September')), ('10', _(u'October')),
+ ('11', _(u'November')), ('12', _(u'December'))))
self.fields['output_type'] = forms.ChoiceField(initial='chart',
- required=False, label=_(u'Format'),
- choices = (('chart', _(u'Chart')),
- ('grid', _(u'Table'))))
+ required=False, label=_(u'Format'),
+ choices=(('chart', _(u'Chart')),
+ ('grid', _(u'Table'))))
+
class Media:
js = ('js/filterform.js',)
-
View
299 apps/reports/models.py
@@ -21,121 +21,120 @@
from django.contrib.auth.models import User
from django.contrib.auth.models import Group
-
from django.utils.translation import ugettext_lazy as _
-
-FILTER_TYPE_DATE = u'DA'
+
+FILTER_TYPE_DATE = u'DA'
FILTER_TYPE_COMBO = u'DR'
FILTER_TYPE_MONTH = u'MO'
-
-
+
+
class Filter(models.Model):
FILTER_FIELD_CHOICES = (
(FILTER_TYPE_DATE, _(u'Date field')),
(FILTER_TYPE_COMBO, _(u'Simple drop down')),
-# (u'SE', _(u'Separator *N/A*')),
-# (u'DQ', _(u'Simple drop down from query *N/A*')),
-# (u'SI', _(u'Drop down with hidden index *N/A*')),
-# (u'SI', _(u'Drop down with hidden index from query *N/A*')),
-# (u'TX', _(u'Text field *N/A*')),
-# (u'NU', _(u'Number field *N/A*')),
-# (u'MO', _(u'Month name drop down *N/A*')),
+# (u'SE', _(u'Separator *N/A*')),
+# (u'DQ', _(u'Simple drop down from query *N/A*')),
+# (u'SI', _(u'Drop down with hidden index *N/A*')),
+# (u'SI', _(u'Drop down with hidden index from query *N/A*')),
+# (u'TX', _(u'Text field *N/A*')),
+# (u'NU', _(u'Number field *N/A*')),
+# (u'MO', _(u'Month name drop down *N/A*')),
)
- name = models.CharField(max_length = 48, help_text = _(u"Name of the parameter to be used in the queries. Do not use spaces or special symbols."), verbose_name = _(u"name"))
- description = models.CharField(max_length = 32, blank = True, null = True, verbose_name = _(u"description"))
- type = models.CharField(max_length = 2, choices = FILTER_FIELD_CHOICES, verbose_name = _(u"type"))
- label = models.CharField(max_length = 32, help_text = "Text label that will be presented to the user.", verbose_name = _(u"label"))
- default = models.CharField(max_length = 32, blank = True, null = True, help_text = "Defautl value or one the special functions [this_day, this_month, this_year].", verbose_name = _(u"default"))
- options = models.TextField(blank = True, null = True, verbose_name = _(u"options"))
-
+ name = models.CharField(max_length=48, help_text=_(u"Name of the parameter to be used in the queries. Do not use spaces or special symbols."), verbose_name=_(u"name"))
+ description = models.CharField(max_length=32, blank=True, null=True, verbose_name=_(u"description"))
+ type = models.CharField(max_length=2, choices=FILTER_FIELD_CHOICES, verbose_name=_(u"type"))
+ label = models.CharField(max_length=32, help_text="Text label that will be presented to the user.", verbose_name=_(u"label"))
+ default = models.CharField(max_length=32, blank=True, null=True, help_text="Defautl value or one the special functions [this_day, this_month, this_year].", verbose_name=_(u"default"))
+ options = models.TextField(blank=True, null=True, verbose_name=_(u"options"))
+
def __unicode__(self):
if self.description:
return '%s "%s"' % (self.name, self.description)
else:
return self.name
-
+
def get_parents(self):
return ', '.join(['"%s"' % p.name for p in self.filterset_set.all()])
get_parents.short_description = _(u'used by filter sets')
-
+
def execute_function(self):
today = datetime.date.today()
if self.default == 'function:this_day':
self.default = today
-
+
if self.default == 'function:this_month':
self.default = datetime.date(today.year, today.month, 1)
-
+
if self.default == 'function:this_year':
self.default = datetime.date(today.year, 1, 1)
class Meta:
ordering = ['name']
verbose_name = _(u"filter")
- verbose_name_plural = _(u"filters")
-
-
+ verbose_name_plural = _(u"filters")
+
+
class Filterset(models.Model):
- name = models.CharField(max_length = 64, verbose_name = _(u"name"), help_text = _(u'A simple name for your convenience.'))
- filters = models.ManyToManyField(Filter, through='FilterExtra', verbose_name = _(u"filters"))
-
+ name = models.CharField(max_length=64, verbose_name=_(u"name"), help_text=_(u'A simple name for your convenience.'))
+ filters = models.ManyToManyField(Filter, through='FilterExtra', verbose_name=_(u"filters"))
+
def __unicode__(self):
return self.name
def get_parents(self):
- return ', '.join(['"%s"' % r.title for r in self.report_set.all()])
+ return ', '.join(['"%s"' % r.title for r in self.report_set.all()])
get_parents.short_description = _(u'used by reports')
-
+
class Meta:
ordering = ['name']
verbose_name = _(u"filters set")
- verbose_name_plural = _(u"filters sets")
+ verbose_name_plural = _(u"filters sets")
class FilterExtra(models.Model):
filterset = models.ForeignKey(Filterset)
- filter = models.ForeignKey(Filter, verbose_name = _(u"filter"))
- order = models.IntegerField(default = 0, verbose_name = _(u"order"))
+ filter = models.ForeignKey(Filter, verbose_name=_(u"filter"))
+ order = models.IntegerField(default=0, verbose_name=_(u"order"))
def __unicode__(self):
return unicode(self.filter)
-
+
class Meta:
verbose_name = _(u"filter")
- verbose_name_plural = _(u"filters")
-
-
+ verbose_name_plural = _(u"filters")
+
+
class Serie(models.Model):
- name = models.CharField(max_length = 64, help_text = "Internal name. Do not use spaces or special symbols.", verbose_name = _(u"name"))
- label = models.CharField(max_length = 24, null = True, blank = True, help_text = "Label to be shown to the user and to be used for the legend.", verbose_name = _(u"label"))
- tick_format = models.CharField(blank = True, null = True, max_length = 16, help_text = "Example: Currency - '$%d.00'", verbose_name = _(u"tick format"))
- query = models.TextField(verbose_name = _(u"query"), help_text = _(u"SQL query, that returns only 2 fields and may of may be a parameter query. Include parameters in the format: <field> LIKE %(parameter)s. Also the SQL wildcard character % must be escaped as %%."))
- description = models.TextField(null = True, blank = True, help_text = "Description of the query, notes and observations.", verbose_name = _(u"description"))
-
- validated = models.BooleanField(default = False, verbose_name = _(u"validated?"))
- validated_date = models.DateField(blank = True, null = True, verbose_name = _(u"validation date"))
- validated_person = models.CharField(max_length = 32, blank = True, null = True, verbose_name = _(u"validated by"))
- validation_description = models.TextField(blank = True, null = True, verbose_name = _(u"validation description"), help_text = _(u"An explanation or description about how this series was validated."))
-
- last_execution_time = models.PositiveIntegerField(blank = True, null = True)
- avg_execution_time = models.PositiveIntegerField(blank = True, null = True)
-
+ name = models.CharField(max_length=64, help_text="Internal name. Do not use spaces or special symbols.", verbose_name=_(u"name"))
+ label = models.CharField(max_length=24, null=True, blank=True, help_text="Label to be shown to the user and to be used for the legend.", verbose_name=_(u"label"))
+ tick_format = models.CharField(blank=True, null=True, max_length=16, help_text="Example: Currency - '$%d.00'", verbose_name=_(u"tick format"))
+ query = models.TextField(verbose_name=_(u"query"), help_text=_(u"SQL query, that returns only 2 fields and may of may be a parameter query. Include parameters in the format: <field> LIKE %(parameter)s. Also the SQL wildcard character % must be escaped as %%."))
+ description = models.TextField(null=True, blank=True, help_text="Description of the query, notes and observations.", verbose_name=_(u"description"))
+
+ validated = models.BooleanField(default=False, verbose_name=_(u"validated?"))
+ validated_date = models.DateField(blank=True, null=True, verbose_name=_(u"validation date"))
+ validated_person = models.CharField(max_length=32, blank=True, null=True, verbose_name=_(u"validated by"))
+ validation_description = models.TextField(blank=True, null=True, verbose_name=_(u"validation description"), help_text=_(u"An explanation or description about how this series was validated."))
+
+ last_execution_time = models.PositiveIntegerField(blank=True, null=True)
+ avg_execution_time = models.PositiveIntegerField(blank=True, null=True)
+
def __unicode__(self):
return self.name
-
+
def get_parents(self):
- return ', '.join(['"%s"' % r.title for r in self.report_set.all()])
+ return ', '.join(['"%s"' % r.title for r in self.report_set.all()])
get_parents.short_description = _(u'used by reports')
-
+
def get_params(self):
import re
return "(%s)" % ', '.join([p for p in re.compile('%\((.*?)\)').findall(self.query)])
get_params.short_description = _(u'parameters')
-
+
def get_filters(self):
#TODO: optmize
#return [fs for fs in [r.filtersets.all()] for r in self.report_set.all()]
- #return ', '.join(['"%s"' % f.title for f in self.report_set.all()])
+ #return ', '.join(['"%s"' % f.title for f in self.report_set.all()])
filters = []
for report in self.report_set.all():
@@ -145,34 +144,34 @@ def get_filters(self):
filters.append(filter)
return ' ,'.join(['%s' % f for f in filters])
get_filters.short_description = _(u'filters')
-
+
class Meta:
ordering = ['name']
verbose_name = _(u"serie")
- verbose_name_plural = _(u"series")
+ verbose_name_plural = _(u"series")
class SeriesStatistic(models.Model):
- timestamp = models.DateTimeField(auto_now_add=True, verbose_name = _(u"timestamp"))
- serie = models.ForeignKey(Serie, verbose_name = _(u"serie"))
- user = models.ForeignKey(User, verbose_name = _(u"user"))
- execution_time = models.PositiveIntegerField(verbose_name = _(u"execution time"))
- params = models.CharField(max_length = 128, blank = True, null = True, verbose_name = _(u"parameters"))
+ timestamp = models.DateTimeField(auto_now_add=True, verbose_name=_(u"timestamp"))
+ serie = models.ForeignKey(Serie, verbose_name=_(u"serie"))
+ user = models.ForeignKey(User, verbose_name=_(u"user"))
+ execution_time = models.PositiveIntegerField(verbose_name=_(u"execution time"))
+ params = models.CharField(max_length=128, blank=True, null=True, verbose_name=_(u"parameters"))
def __unicode__(self):
- return unicode(self.id)#"%s | %s | %s" % (self.timestamp, self.serie, self.user)
+ return unicode(self.id) # "%s | %s | %s" % (self.timestamp, self.serie, self.user)
class Meta:
ordering = ('-id',)
verbose_name = _(u"series statistic")
- verbose_name_plural = _(u"series statistics")
-
-
+ verbose_name_plural = _(u"series statistics")
+
+
class Report(models.Model):
CHART_TYPE_CHOICES = (
(u'SI', _(u'Standard X,Y')),
(u'PI', _(u'Pie chart')),
- )
+ )
LEGEND_LOCATION_CHOICES = (
(u'nw', _(u'North-West')),
(u'n', _(u'North')),
@@ -188,159 +187,157 @@ class Report(models.Model):
(u'v', _(u'Vertical')),
)
- title = models.CharField(max_length = 128, help_text = _(u"Chart title."), verbose_name = _(u"title"))
- description = models.TextField(null = True, blank = True, help_text = _(u"A description of the report. This description will also be presented to the user."), verbose_name = _(u"description"))
- type = models.CharField(max_length = 2, choices = CHART_TYPE_CHOICES, default = "SI", help_text = _(u"Chart type."), verbose_name = _(u"type"))
- zoom = models.BooleanField(default = False, verbose_name = _(u"zoom"), help_text = _(u"Allow the user to zoom in on the chart."))
- pointlabels = models.BooleanField(default = False, verbose_name = _(u"point labels"), help_text = _(u"Enable point labels displaying the values."))
- pointlabels_location = models.CharField(max_length = 2, default = 'n', choices = LEGEND_LOCATION_CHOICES, verbose_name = _(u"point label location"), help_text = _(u"The point label position respetive to the series."))
- trendline = models.BooleanField(default = False, help_text = _(u"Show a trendline?"), verbose_name = _(u"trendline"))
- highlighter = models.BooleanField(default = False, verbose_name = _(u"highlighter"))
- use_one_scale = models.BooleanField(default = False, help_text = _(u"This options forces all series in chart to use the same scale."), verbose_name = _(u"use one scale"))
- scale_label_override = models.CharField(max_length = 32, null = True, blank = True,help_text = _(u"The scale label to be used when using a single scale per report."), verbose_name = _(u"scale label override"))
- tracking = models.BooleanField(default = False, help_text = _(u"Draw horizontal and/or vertical tracking lines across the plot to the cursor location."), verbose_name = _(u"data tracking"))
- legend = models.BooleanField(default = False, help_text = _(u"Show legend?"), verbose_name = _(u"legend"))
- legend_location = models.CharField(max_length = 2, default = 'ne', choices = LEGEND_LOCATION_CHOICES, verbose_name = _(u"legend location"), help_text = _(u"Select the legend position respetive to the chart."))
- orientation = models.CharField(max_length = 1, default = 'v', choices = ORIENTATION_CHOICES, verbose_name = _(u"report orientation"), help_text = _(u"Direction the report's series will be drawn."))
- filtersets = models.ManyToManyField(Filterset, null = True, blank = True, verbose_name = _(u"filter sets"))
- series = models.ManyToManyField(Serie, through='SerieType', verbose_name = _(u"series"))
+ title = models.CharField(max_length=128, help_text=_(u"Chart title."), verbose_name=_(u"title"))
+ description = models.TextField(null=True, blank=True, help_text=_(u"A description of the report. This description will also be presented to the user."), verbose_name=_(u"description"))
+ type = models.CharField(max_length=2, choices=CHART_TYPE_CHOICES, default="SI", help_text=_(u"Chart type."), verbose_name=_(u"type"))
+ zoom = models.BooleanField(default=False, verbose_name=_(u"zoom"), help_text=_(u"Allow the user to zoom in on the chart."))
+ pointlabels = models.BooleanField(default=False, verbose_name=_(u"point labels"), help_text=_(u"Enable point labels displaying the values."))
+ pointlabels_location = models.CharField(max_length=2, default='n', choices=LEGEND_LOCATION_CHOICES, verbose_name=_(u"point label location"), help_text=_(u"The point label position respetive to the series."))
+ trendline = models.BooleanField(default=False, help_text=_(u"Show a trendline?"), verbose_name=_(u"trendline"))
+ highlighter = models.BooleanField(default=False, verbose_name=_(u"highlighter"))
+ use_one_scale = models.BooleanField(default=False, help_text=_(u"This options forces all series in chart to use the same scale."), verbose_name=_(u"use one scale"))
+ scale_label_override = models.CharField(max_length=32, null=True, blank=True, help_text=_(u"The scale label to be used when using a single scale per report."), verbose_name=_(u"scale label override"))
+ tracking = models.BooleanField(default=False, help_text=_(u"Draw horizontal and/or vertical tracking lines across the plot to the cursor location."), verbose_name=_(u"data tracking"))
+ legend = models.BooleanField(default=False, help_text=_(u"Show legend?"), verbose_name=_(u"legend"))
+ legend_location = models.CharField(max_length=2, default='ne', choices=LEGEND_LOCATION_CHOICES, verbose_name=_(u"legend location"), help_text=_(u"Select the legend position respetive to the chart."))
+ orientation = models.CharField(max_length=1, default='v', choices=ORIENTATION_CHOICES, verbose_name=_(u"report orientation"), help_text=_(u"Direction the report's series will be drawn."))
+ filtersets = models.ManyToManyField(Filterset, null=True, blank=True, verbose_name=_(u"filter sets"))
+ series = models.ManyToManyField(Serie, through='SerieType', verbose_name=_(u"series"))
#tracking_axis = X,Y, both
#publish = models.BooleanField(default = False)
-# validated = models.BooleanField(default = False, verbose_name = _(u"validated?"))
-# validated_date = models.DateField(blank = True, null = True, verbose_name = _(u"validation date"))
-# validated_person = models.CharField(max_length = 32, blank = True, null = True, verbose_name = _(u"validated by"))
-
-# series_label = models.CharField(max_length = 32, null = True, blank = True)
-# scale_label = models.CharField(max_length = 32, null = True, blank = True)
-# series_label_rotation = models.IntegerField(default = 0)
-# scale_label_rotation = models.IntegerField(default = 90)
-# use_series_label = models.BooleanField(default = True)
+# validated = models.BooleanField(default = False, verbose_name = _(u"validated?"))
+# validated_date = models.DateField(blank = True, null = True, verbose_name = _(u"validation date"))
+# validated_person = models.CharField(max_length = 32, blank = True, null = True, verbose_name = _(u"validated by"))
+# series_label = models.CharField(max_length = 32, null = True, blank = True)
+# scale_label = models.CharField(max_length = 32, null = True, blank = True)
+# series_label_rotation = models.IntegerField(default = 0)
+# scale_label_rotation = models.IntegerField(default = 90)
+# use_series_label = models.BooleanField(default = True)
def __unicode__(self):
return self.title
-
+
def get_absolute_url(self):
return ('ajax_report_view', [str(self.id)])
get_absolute_url = models.permalink(get_absolute_url)
-
def get_parents(self):
return ', '.join([mi.title for mi in self.menuitem_set.all()])
get_parents.short_description = _(u"used by menus")
-
+
def get_series(self):
return ', '.join(['"%s (%s)"' % (serie.serie.name, serie.get_type_display()) for serie in self.serietype_set.all()])
get_series.short_description = _(u"series")
-
+
class Meta:
ordering = ['title']
verbose_name = _(u"report")
- verbose_name_plural = _(u"reports")
-
-
+ verbose_name_plural = _(u"reports")
+
+
class ReportStatistic(models.Model):
- timestamp = models.DateTimeField(auto_now_add=True, verbose_name = _(u"timestamp"))
- report = models.ForeignKey(Report, verbose_name = _(u"report"))
- user = models.ForeignKey(User, verbose_name = _(u"user"))
- execution_time = models.PositiveIntegerField(verbose_name = _(u"execution time"))
- params = models.CharField(max_length = 128, blank = True, null = True, verbose_name = _(u"parameters"))
+ timestamp = models.DateTimeField(auto_now_add=True, verbose_name=_(u"timestamp"))
+ report = models.ForeignKey(Report, verbose_name=_(u"report"))
+ user = models.ForeignKey(User, verbose_name=_(u"user"))
+ execution_time = models.PositiveIntegerField(verbose_name=_(u"execution time"))
+ params = models.CharField(max_length=128, blank=True, null=True, verbose_name=_(u"parameters"))
def __unicode__(self):
- return unicode(self.id)#"%s | %s | %s" % (self.timestamp, self.serie, self.user)
+ return unicode(self.id) # "%s | %s | %s" % (self.timestamp, self.serie, self.user)
class Meta:
ordering = ('-id',)
verbose_name = _(u"report statistic")
- verbose_name_plural = _(u"report statistics")
-
-
+ verbose_name_plural = _(u"report statistics")
+
+
class SerieType(models.Model):
SERIES_TYPE_CHOICES = (
(u'BA', _(u'Bars')),
(u'LI', _(u'Lines')),
)
- serie = models.ForeignKey(Serie, verbose_name = _(u"serie"))
- report = models.ForeignKey(Report, verbose_name = _(u"chart"))
- type = models.CharField(max_length = 2, choices = SERIES_TYPE_CHOICES, default = "BA", verbose_name = _(u"type"))
- zerobase = models.BooleanField(default = True, verbose_name = _(u"zerobase"), help_text = _(u"Force this serie's scale to start at integer number 0."))
-
+ serie = models.ForeignKey(Serie, verbose_name=_(u"serie"))
+ report = models.ForeignKey(Report, verbose_name=_(u"chart"))
+ type = models.CharField(max_length=2, choices=SERIES_TYPE_CHOICES, default="BA", verbose_name=_(u"type"))
+ zerobase = models.BooleanField(default=True, verbose_name=_(u"zerobase"), help_text=_(u"Force this serie's scale to start at integer number 0."))
+
def __unicode__(self):
- return unicode(self.serie)
+ return unicode(self.serie)
class Meta:
#ordering = ['title']
verbose_name = _(u"serie")
- verbose_name_plural = _(u"series")
-
-
+ verbose_name_plural = _(u"series")
+
+
class Menuitem(models.Model):
#TODO: reports display order
- title = models.CharField(max_length = 64, verbose_name = _(u"title"))
- reports = models.ManyToManyField(Report, verbose_name = _(u"chart"))
- order = models.IntegerField(default = 0, verbose_name = _(u"order"))
+ title = models.CharField(max_length=64, verbose_name=_(u"title"))
+ reports = models.ManyToManyField(Report, verbose_name=_(u"chart"))
+ order = models.IntegerField(default=0, verbose_name=_(u"order"))
def __unicode__(self):
return self.title
class Meta:
- ordering = ['order', 'title']
+ ordering = ['order', 'title']
verbose_name = _(u"menu item")
verbose_name_plural = _(u"menu items")
-
+
def get_reports(self):
return ', '.join(['"%s"' % r.title for r in self.reports.all()])
get_reports.short_description = _(u"charts")
class UserPermission(models.Model):
UNION_CHOICES = (
- ( 'E', _(u'Exclusive')),
- ( 'I', _(u'Inclusive')),
- ( 'O', _(u'Override')),
+ ('E', _(u'Exclusive')),
+ ('I', _(u'Inclusive')),
+ ('O', _(u'Override')),
)
- user = models.ForeignKey(User, unique = True)
+ user = models.ForeignKey(User, unique=True)
#access_unpublished_reports = models.BooleanField(default = False)
- union = models.CharField(max_length = 1, choices = UNION_CHOICES, default = 'I', verbose_name = _(u"Group/user permissions union type"), help_text = _(u"Determines how the user permissions interact with the group permissions of this user."))
- reports = models.ManyToManyField(Report, blank = True, null = True, verbose_name = _(u"charts"))
- filters = models.ManyToManyField(Filter, through = 'UserPermissionFilterValues', verbose_name = _(u"filters"))
+ union = models.CharField(max_length=1, choices=UNION_CHOICES, default='I', verbose_name=_(u"Group/user permissions union type"), help_text=_(u"Determines how the user permissions interact with the group permissions of this user."))
+ reports = models.ManyToManyField(Report, blank=True, null=True, verbose_name=_(u"charts"))
+ filters = models.ManyToManyField(Filter, through='UserPermissionFilterValues', verbose_name=_(u"filters"))
def get_reports(self):
return ', '.join(['"%s"' % r.title for r in self.reports.all()])
get_reports.short_description = _(u"charts")
-
+
def __unicode__(self):
return unicode(self.user)
-
+
class Meta:
verbose_name = _(u"user permission")
verbose_name_plural = _(u"user permissions")
class UserPermissionFilterValues(models.Model):
- userpermission = models.ForeignKey(UserPermission, verbose_name = _(u"user permissions"))
- filter = models.ForeignKey(Filter, verbose_name = _(u"filter"))
- options = models.TextField(blank = True, null = True, verbose_name = _(u"options"))
- default = models.CharField(max_length = 32, blank = True, null = True, help_text = "Defautl value or one the special functions [this_day, this_month, this_year].", verbose_name = _(u"default"))
-
+ userpermission = models.ForeignKey(UserPermission, verbose_name=_(u"user permissions"))
+ filter = models.ForeignKey(Filter, verbose_name=_(u"filter"))
+ options = models.TextField(blank=True, null=True, verbose_name=_(u"options"))
+ default = models.CharField(max_length=32, blank=True, null=True, help_text="Defautl value or one the special functions [this_day, this_month, this_year].", verbose_name=_(u"default"))
+
def __unicode__(self):
return "%s = %s" % (self.filter, self.options)
-
+
class Meta:
verbose_name = _(u"user filter values limit")
verbose_name_plural = _(u"user filter values limits")
-
-
+
+
class GroupPermission(models.Model):
- group = models.ForeignKey(Group, unique=True, verbose_name = _(u"group"))
+ group = models.ForeignKey(Group, unique=True, verbose_name=_(u"group"))
#access_unpublished_reports = models.BooleanField(default = False)
- reports = models.ManyToManyField(Report, blank = True, null = True, verbose_name = _(u"reports"))
- filters = models.ManyToManyField(Filter, through = 'GroupPermissionFilterValues', verbose_name = _(u"filters"))
+ reports = models.ManyToManyField(Report, blank=True, null=True, verbose_name=_(u"reports"))
+ filters = models.ManyToManyField(Filter, through='GroupPermissionFilterValues', verbose_name=_(u"filters"))
def __unicode__(self):
return unicode(self.group)
-
+
class Meta:
verbose_name = _(u"group permissions")
verbose_name_plural = _(u"groups permissions")
@@ -351,14 +348,14 @@ def get_reports(self):
class GroupPermissionFilterValues(models.Model):
- grouppermission = models.ForeignKey(GroupPermission, verbose_name = _(u"group permissions"))
- filter = models.ForeignKey(Filter, verbose_name = _(u"filter"))
- options = models.TextField(blank = True, null = True, verbose_name = _(u"options"))
- default = models.CharField(max_length = 32, blank = True, null = True, help_text = "Defautl value or one the special functions [this_day, this_month, this_year].", verbose_name = _(u"default"))
+ grouppermission = models.ForeignKey(GroupPermission, verbose_name=_(u"group permissions"))
+ filter = models.ForeignKey(Filter, verbose_name=_(u"filter"))
+ options = models.TextField(blank=True, null=True, verbose_name=_(u"options"))
+ default = models.CharField(max_length=32, blank=True, null=True, help_text="Defautl value or one the special functions [this_day, this_month, this_year].", verbose_name=_(u"default"))
def __unicode__(self):
return "%s = %s" % (self.filter, self.options)
-
+
class Meta:
verbose_name = _(u"group filter values limit")
- verbose_name_plural = _(u"group filter values limits")
+ verbose_name_plural = _(u"group filter values limits")
View
1 apps/reports/templatetags/__init__.py
@@ -15,4 +15,3 @@
# You should have received a copy of the GNU General Public License
# along with descartes-bi. If not, see <http://www.gnu.org/licenses/>.
#
-
View
19 apps/reports/templatetags/menubuilder.py
@@ -25,6 +25,7 @@
register = template.Library()
+
def build_menu(parser, token):
"""
{% menu menu_name %}
@@ -52,7 +53,7 @@ class get_menu_node(template.Node):
def render(self, context):
from reports.views import _get_allowed_object_for_user
user = template.resolve_variable('request.user', context)
-
+
results = _get_allowed_object_for_user(user)
mi_order = [mi.order for mi in results['menuitems']]
mi_order.sort()
@@ -66,33 +67,35 @@ def render(self, context):
def get_menu(parser, token):
return get_menu_node()
+
@register.filter
def in_list(value, arg):
return value in arg
-
+
class GetCustomAppsNode(template.Node):
def render(self, context):
custom_apps = getattr(settings, 'CUSTOMIZATION_APPS', [])
context['custom_apps'] = custom_apps
-
+
custom_apps_data = {}
for app in custom_apps:
exec "import %s" % app
try:
custom_apps_data[app] = eval("%s.APP_DATA" % app)
-
+
if 'template_name' in custom_apps_data[app]:
custom_template = get_template(
custom_apps_data[app]['template_name'])
custom_apps_data[app]['template_data'] = custom_template.render(Context(context))
except:
pass
-
- context['custom_apps_data'] = custom_apps_data
-
+
+ context['custom_apps_data'] = custom_apps_data
+
return ''
-
+
+
@register.tag(name='get_custom_apps')
def get_custom_apps(parser, token):
return GetCustomAppsNode()
View
8 apps/reports/urls.py
@@ -16,15 +16,15 @@
# along with descartes-bi. If not, see <http://www.gnu.org/licenses/>.
#
-from django.conf.urls.defaults import *
+from django.conf.urls.defaults import patterns, url
urlpatterns = patterns('reports.views',
url(r'^ajax/report/(?P<report_id>\d+)/$', 'ajax_report', (), 'ajax_report_view'),
url(r'^ajax/filter_form/(?P<report_id>\d+)/$', 'ajax_filter_form', (), 'ajax_filter_form_view'),
- url(r'^ajax/report_description/(?P<report_id>\d+)/$','ajax_report_description', (), 'ajax_report_description_view'),
- url(r'^ajax/report_validation/(?P<report_id>\d+)/$','ajax_report_validation', (), 'ajax_report_validation_view'),
+ url(r'^ajax/report_description/(?P<report_id>\d+)/$', 'ajax_report_description', (), 'ajax_report_description_view'),
+ url(r'^ajax/report_validation/(?P<report_id>\d+)/$', 'ajax_report_validation', (), 'ajax_report_validation_view'),
url(r'^ajax/report/(?P<report_id>\d+)/benchmarks/$', 'ajax_report_benchmarks', (), 'ajax_report_benchmarks_view'),
- #url(r'^dashboard/$', 'django.views.generic.simple.direct_to_template', { 'template' : 'dashboard.html'}, 'dashboard'),
+ #url(r'^dashboard/$', 'django.views.generic.simple.direct_to_template', { 'template' : 'dashboard.html'}, 'dashboard'),
)
View
116 apps/reports/views.py
@@ -15,20 +15,18 @@
# You should have received a copy of the GNU General Public License
# along with descartes-bi. If not, see <http://www.gnu.org/licenses/>.
#
+import datetime
+import re
+
from django.db import connections
-from django.http import HttpResponse, HttpResponseRedirect
+from django.http import HttpResponse
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django.utils.translation import ugettext as _
-from django.conf import settings
-from django.utils.importlib import import_module
+from forms import FilterForm
from models import Report, Menuitem, GroupPermission, UserPermission, User, SeriesStatistic, ReportStatistic
from models import FILTER_TYPE_DATE, FILTER_TYPE_COMBO
-from forms import FilterForm
-
-import datetime
-import re
def ajax_report_benchmarks(request, report_id):
@@ -38,12 +36,13 @@ def ajax_report_benchmarks(request, report_id):
if request.user.is_staff:
result = '<ul>'
for s in report.series.all():
- result += "<li>%s</li><br />" % _('"%(serie)s" = Lastest run: %(last)ss; Average: %(avg)ss') % {'serie':s.label or unicode(s), 'last':s.last_execution_time or '0', 'avg':s.avg_execution_time or '0'}
+ result += "<li>%s</li><br />" % _('"%(serie)s" = Lastest run: %(last)ss; Average: %(avg)ss') % {'serie': s.label or unicode(s), 'last': s.last_execution_time or '0', 'avg': s.avg_execution_time or '0'}
result += '</ul>'
return HttpResponse(result)
+
def ajax_filter_form(request, report_id):
#TODO: access control
if request.method == 'GET':
@@ -53,24 +52,25 @@ def ajax_filter_form(request, report_id):
if report not in _get_allowed_object_for_user(request.user)['reports']:
return render_to_response('messagebox-error.html',
- {'title':_(u'Permission error'),
- 'message':_(u"Insufficient permissions to access this area.")})
+ {'title': _(u'Permission error'),
+ 'message': _(u"Insufficient permissions to access this area.")})
if query:
filter_form = FilterForm(report.filtersets.all(), request.user, query)
else:
filter_form = FilterForm(report.filtersets.all(), request.user)
-
- return render_to_response('filter_form_subtemplate.html', {'filter_form':filter_form},
+ return render_to_response('filter_form_subtemplate.html', {'filter_form': filter_form},
context_instance=RequestContext(request))
+
def ajax_report_description(request, report_id):
report = get_object_or_404(Report, pk=report_id)
result = "<strong>%s</strong><br />%s" % (report.title, report.description or '')
return HttpResponse(result)
+
def ajax_report_validation(request, report_id):
report = get_object_or_404(Report, pk=report_id)
@@ -90,15 +90,16 @@ def ajax_report_validation(request, report_id):
else:
return HttpResponse(_(u'No element of this report has been validates.'))
+
def ajax_report(request, report_id):
start_time = datetime.datetime.now()
report = get_object_or_404(Report, pk=report_id)
if report not in _get_allowed_object_for_user(request.user)['reports']:
return render_to_response('messagebox-error.html',
- {'title':_(u'Permission error'),
- 'message':_(u"Insufficient permissions to access this area.")})
+ {'title': _(u'Permission error'),
+ 'message': _(u"Insufficient permissions to access this area.")})
output_type = request.GET.get('output_type', 'chart')
params = {}
@@ -111,8 +112,6 @@ def ajax_report(request, report_id):
else:
filter_form = FilterForm(filtersets, request.user)
- valid_form = filter_form.is_valid()
-
for set in filtersets.all():
for filter in set.filters.all():
@@ -138,20 +137,20 @@ def ajax_report(request, report_id):
for s in report.serietype_set.all():
query = s.serie.query
if re.compile("[^%]%[^%(]").search(query):
- return render_to_response('messagebox-error.html', {'title':_(u'Query error'), 'message':_(u"Single '%' found, replace with double '%%' to properly escape the SQL wildcard caracter '%'.")})
+ return render_to_response('messagebox-error.html', {'title': _(u'Query error'), 'message': _(u"Single '%' found, replace with double '%%' to properly escape the SQL wildcard caracter '%'.")})
cursor = connections['data_source'].cursor()
if special_params:
for sp in special_params.keys():
- query = re.compile('%\(' + sp +'\)s').sub(special_params[sp], query)
+ query = re.compile('%\(' + sp + '\)s').sub(special_params[sp], query)
try:
serie_start_time = datetime.datetime.now()
cursor.execute(query, params)
except:
import sys
(exc_type, exc_info, tb) = sys.exc_info()
- return render_to_response('messagebox-error.html', {'title':exc_type, 'message':exc_info})
+ return render_to_response('messagebox-error.html', {'title': exc_type, 'message': exc_info})
else:
cursor.execute(query, params)
@@ -198,15 +197,15 @@ def ajax_report(request, report_id):
data = {
'chart_data': ','.join(series_results),
'series_results': series_results,
- 'chart_series' : report.serietype_set.all(),
- 'chart' : report,
- 'h_axis' : h_axis,
- 'v_axis' : v_axis,
- 'ajax' : True,
- 'query' : query,
- 'params' : params,
+ 'chart_series': report.serietype_set.all(),
+ 'chart': report,
+ 'h_axis': h_axis,
+ 'v_axis': v_axis,
+ 'ajax': True,
+ 'query': query,
+ 'params': params,
'series_labels': labels,
- 'time_delta' : datetime.datetime.now() - start_time,
+ 'time_delta': datetime.datetime.now() - start_time,
}
if output_type == 'chart':
@@ -216,10 +215,11 @@ def ajax_report(request, report_id):
return render_to_response('single_grid.html', data,
context_instance=RequestContext(request))
else:
- return render_to_response('messagebox-error.html', {'title':_(u'Error'), 'message':_(u"Unknown output type (chart, table, etc).")})
+ return render_to_response('messagebox-error.html', {'title': _(u'Error'), 'message': _(u"Unknown output type (chart, table, etc).")})
+
#TODO: Improve this further
-def data_to_js_chart(data, label_format = None, orientation = 'v'):
+def data_to_js_chart(data, label_format=None, orientation='v'):
if not data:
return ''
@@ -248,7 +248,8 @@ def data_to_js_chart(data, label_format = None, orientation = 'v'):
return result
-def data_to_js_grid(data, label_format = None):
+
+def data_to_js_grid(data, label_format=None):
if not data:
return ''
@@ -257,19 +258,20 @@ def data_to_js_grid(data, label_format = None):
result = '['
for key, value in data:
- result += '{key:"%s", value:"%s"},' % (key or '?', label_format % value)
+ result += '{key:"%s", value:"%s"},' % (key or '?', label_format % value)
result = result[:-1]
result += ']'
return result
+
def acl(request):
aclform = ACLForm()
return render_to_response('acl.html', {
- 'aclform' : aclform,
- },
- context_instance=RequestContext(request))
+ 'aclform': aclform,
+ }, context_instance=RequestContext(request))
+
def _get_allowed_object_for_user(user):
reports_allowed = []
@@ -281,8 +283,8 @@ def _get_allowed_object_for_user(user):
#staff gets all reports & menuitems
if user.is_staff:
return {
- 'reports':Report.objects.all(),
- 'menuitems':Menuitem.objects.all()
+ 'reports': Report.objects.all(),
+ 'menuitems': Menuitem.objects.all()
}
for group in user.groups.all():
@@ -297,14 +299,14 @@ def _get_allowed_object_for_user(user):
pass
try:
up = UserPermission.objects.get(user=user)
- if up.union == 'O': #Overwrite
+ if up.union == 'O': # Overwrite
reports_allowed = []
- if up.union == 'I' or up.union == 'O': #Inclusive
+ if up.union == 'I' or up.union == 'O': # Inclusive
for report in up.reports.all():
if report not in reports_allowed:
reports_allowed.append(report)
- elif up.union == 'E': #Exclusive
+ elif up.union == 'E': # Exclusive
for report in up.reports.all():
if report in reports_allowed:
reports_allowed.remove(report)
@@ -323,9 +325,10 @@ def _get_allowed_object_for_user(user):
menuitems_allowed.append(menuitem)
return {
- 'reports':reports_allowed,
- 'menuitems':menuitems_allowed
- }
+ 'reports': reports_allowed,
+ 'menuitems': menuitems_allowed
+ }
+
#TODO: Define filter default value when user is doing an exclusive union
def _get_user_filters_limits(user):
@@ -342,17 +345,17 @@ def _get_user_filters_limits(user):
try:
gp = GroupPermission.objects.get(group=group)
for filter in gp.filters.all():
- if filter not in filter_limits:#.keys():
+ if filter not in filter_limits: # .keys():
filter_limits[filter] = {}
- if gp.grouppermissionfiltervalues_set.get(filter = filter).default:
- filter_limits[filter]['default'] = gp.grouppermissionfiltervalues_set.get(filter = filter).default
+ if gp.grouppermissionfiltervalues_set.get(filter=filter).default:
+ filter_limits[filter]['default'] = gp.grouppermissionfiltervalues_set.get(filter=filter).default
if filter.type == FILTER_TYPE_COMBO:
if 'mask' not in filter_limits[filter]:
- filter_limits[filter]['mask'] = list(eval(gp.grouppermissionfiltervalues_set.get(filter = filter).options, {}))
+ filter_limits[filter]['mask'] = list(eval(gp.grouppermissionfiltervalues_set.get(filter=filter).options, {}))
else:
- for n in eval(gp.grouppermissionfiltervalues_set.get(filter = filter).options, {}):
+ for n in eval(gp.grouppermissionfiltervalues_set.get(filter=filter).options, {}):
if n not in filter_limits[filter]['mask']:
filter_limits[filter]['mask'].append(n)
except:
@@ -361,31 +364,31 @@ def _get_user_filters_limits(user):
try:
up = UserPermission.objects.get(user=user)
- if up.union == 'O': #Overwrite
+ if up.union == 'O': # Overwrite
filter_limits = {}
- if up.union == 'I' or up.union == 'O': #Inclusive
+ if up.union == 'I' or up.union == 'O': # Inclusive
for filter in up.filters.all():
- if filter not in filter_limits:#.keys():
+ if filter not in filter_limits: # .keys():
filter_limits[filter] = {}
- if up.userpermissionfiltervalues_set.get(filter = filter).default:
- filter_limits[filter]['default'] = up.userpermissionfiltervalues_set.get(filter = filter).default
+ if up.userpermissionfiltervalues_set.get(filter=filter).default:
+ filter_limits[filter]['default'] = up.userpermissionfiltervalues_set.get(filter=filter).default
if filter.type == FILTER_TYPE_COMBO:
if 'mask' not in filter_limits[filter]:
- filter_limits[filter]['mask'] = list(eval(up.userpermissionfiltervalues_set.get(filter = filter).options, {}))
+ filter_limits[filter]['mask'] = list(eval(up.userpermissionfiltervalues_set.get(filter=filter).options, {}))
else:
#if filter.type == 'DR':
- for n in eval(up.userpermissionfiltervalues_set.get(filter = filter).options, {}):
+ for n in eval(up.userpermissionfiltervalues_set.get(filter=filter).options, {}):
if n not in filter_limits[filter]['mask']:
filter_limits[filter]['mask'].append(n)
- elif up.union == 'E': #Exclusive
+ elif up.union == 'E': # Exclusive
for filter in up.filters.all():
if filter in filter_limits.keys():
if filter.type == FILTER_TYPE_COMBO:
- for n in eval(up.userpermissionfiltervalues_set.get(filter = filter).options, {}):
+ for n in eval(up.userpermissionfiltervalues_set.get(filter=filter).options, {}):
if n in filter_limits[filter]['mask']:
filter_limits[filter]['mask'].remove(n)
@@ -396,6 +399,5 @@ def _get_user_filters_limits(user):
#unkown user or anonymous
pass
-
#print "FILTER LIMITS: %s" % filter_limits
return filter_limits

0 comments on commit 38a305e

Please sign in to comment.
Something went wrong with that request. Please try again.