Skip to content

Commit

Permalink
cleanup / refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
Maximillian Dornseif committed Dec 10, 2014
1 parent 5f05577 commit fbff6f1
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 77 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
GAE_VERSION=1.8.6
GAE_VERSION=1.9.15

LINT_LINE_LENGTH= 110
LINT_FLAKE8_ARGS= --max-complexity=27 --builtins=_ --max-line-length=$(LINT_LINE_LENGTH) --exclude=mywebapp2.py,gaesessions.py,gaetk/__init__.py
Expand Down Expand Up @@ -77,7 +77,7 @@ check: google_appengine pythonenv
dependencies: pythonenv google_appengine

google_appengine:
curl -s -O http://googleappengine.googlecode.com/files/google_appengine_$(GAE_VERSION).zip
curl -s -O https://storage.googleapis.com/appengine-sdks/featured/google_appengine_$(GAE_VERSION).zip
#/google/__init__.py:
unzip -q google_appengine_$(GAE_VERSION).zip
rm -Rf google_appengine_$(GAE_VERSION).zip
Expand Down
74 changes: 16 additions & 58 deletions gaetk/admin/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

import cgi
import logging
from urllib import unquote

import gaetk.handler
import wtforms
Expand All @@ -24,6 +23,7 @@
from gaetk.admin import util
from gaetk.admin.sites import site
from gaetk.admin.models import DeletedObject
from gaetk import compat


class ModelAdmin(object):
Expand Down Expand Up @@ -81,48 +81,13 @@ def get_ordering(self, request):
direction = request.get('ot', 'asc')
return order_field, '-' if direction == 'desc' else '+'

def _get_queryset_db(self, ordering=None):
"""Queryset für Subklasse von db.Model"""
query = self.model.all()
if ordering:
attr, direction = ordering
if attr in self.model.properties():
if direction == '-':
attr = '-' + attr
query.order(attr)
return query

def _get_queryset_ndb(self, ordering):
"""Queryset für Subklasse von ndb.Model"""
query = self.model.query()
if ordering:
attr, direction = ordering
prop = self.model._properties.get(attr)
if prop:
if direction == '-':
return query.order(-prop)
else:
return query.order(prop)
return query

def get_kind(self):
kind = getattr(self.model, '_get_kind', None)
if not kind:
kind = getattr(self.model, 'kind')
return kind()

def get_queryset(self, request):
"""Gib das QuerySet für die Admin-Seite zurück
Es wird die gewünschte Sortierung durchgeführt.
"""
# TODO: Tupel: (attr, direction)
ordering = self.get_ordering(request)
if issubclass(self.model, ndb.Model):
query = self._get_queryset_ndb(ordering)
elif issubclass(self.model, db.Model):
query = self._get_queryset_db(ordering)
return query
return compat.xdb_queryset(self.model, ordering)

def get_form(self, **kwargs):
"""Erzeuge Formularklasse für das Model"""
Expand Down Expand Up @@ -155,12 +120,7 @@ def get_form(self, **kwargs):

def get_object(self, encoded_key):
"""Ermittle die Instanz über den gegeben ID"""
if issubclass(self.model, ndb.Model):
key = ndb.Key(urlsafe=encoded_key)
instance = key.get()
elif issubclass(self.model, db.Model):
instance = self.model.get(unquote(encoded_key))
return instance
return compat.xdb_get(self.model, encoded_key)

def handle_blobstore_fields(self, handler, obj):
"""Upload für Blobs"""
Expand All @@ -183,32 +143,29 @@ def change_view(self, handler, object_id, extra_context=None):

if handler.request.get('delete') == 'yesiwant':
# Der User hat gebeten, dieses Objekt zu löschen.
if hasattr(obj, 'model') and issubclass(obj.model, db.Model):
data = db.model_to_protobuf(obj).Encode()
dblayer = 'db'
key = obj.key()
else:
# assume ndb
data = ndb.ModelAdapter().entity_to_pb(obj).Encode()
key = compat.xdb_key(obj)
data = compat.xdb_to_protobuf(obj)
dblayer = 'db'
if compat.xdb_is_ndb(obj):
dblayer = 'ndb'
key = obj.key
archived = DeletedObject(key_name=str(key), model_class=model_class.__name__,
old_key=str(key), dblayer=dblayer, data=data)
archived.put()
# Indexierung für Admin-Volltextsuche
from gaetk.admin.search import remove_from_index
if dblayer == 'ndb':
if compat.xdb_is_ndb(obj):
obj.key.delete()
deferred.defer(remove_from_index, obj.key)
else:
obj.delete()
deferred.defer(remove_from_index, obj.key())

handler.add_message(
'warning',
u'<strong>%s</strong> wurde gelöscht. <a href="%s">Objekt wiederherstellen!</a>' % (
obj, archived.undelete_url()))
raise gaetk.handler.HTTP302_Found(location='/admin/%s/%s/' % (
util.get_app_name(model_class), util.get_kind(model_class)))
util.get_app_name(model_class), compat.xdb_kind(model_class)))

# Wenn das Formular abgeschickt wurde und gültig ist,
# speichere das veränderte Objekt und leite auf die Übersichtsseite um.
Expand All @@ -226,7 +183,7 @@ def change_view(self, handler, object_id, extra_context=None):
from gaetk.admin.search import add_to_index
deferred.defer(add_to_index, key)
raise gaetk.handler.HTTP302_Found(location='/admin/%s/%s/' % (
util.get_app_name(model_class), util.get_kind(model_class)))
util.get_app_name(model_class), compat.xdb_kind(model_class)))
else:
form = form_class(obj=obj)

Expand Down Expand Up @@ -332,8 +289,9 @@ def export_view_csv(self, handler, extra_context=None): # pylint: disable=W0613
`extra_context` ist für die Signatur erforderlich, wird aber nicht genutzt.
"""
# irgendwann werden wir hier einen longtask nutzen muessen
exporter = ModelExporter(self.model)
filename = '%s-%s.csv' % (self.get_kind(), datetime.datetime.now())
filename = '%s-%s.csv' % (compat.xdb_kind(self.model), datetime.datetime.now())
handler.response.headers['Content-Type'] = 'text/csv; charset=utf-8'
handler.response.headers['content-disposition'] = \
'attachment; filename=%s' % filename
Expand All @@ -345,7 +303,7 @@ def export_view_xls(self, handler, extra_context=None): # pylint: disable=W0613
`extra_context` ist für die Signatur erforderlich, wird aber nicht genutzt.
"""
exporter = ModelExporter(self.model)
filename = '%s-%s.xls' % (self.get_kind(), datetime.datetime.now())
filename = '%s-%s.cls' % (compat.xdb_kind(self.model), datetime.datetime.now())
handler.response.headers['Content-Type'] = 'application/msexcel'
handler.response.headers['content-disposition'] = \
'attachment; filename=%s' % filename
Expand Down Expand Up @@ -378,12 +336,12 @@ def fields(self):
"""Liste der zu exportierenden Felder"""
if not hasattr(self, '_fields'):
fields = []
# ndb & db compatibility
# ndb & db compatatibility
props = getattr(self.model, '_properties', None)
if not props:
props = self.model.properties()
for prop in props.values():
# ndb & db compatibility
# ndb & db compatatibility
fields.append(getattr(prop, '_name', getattr(prop, 'name', '?')))
if hasattr(self, 'additional_fields'):
fields.extend(self.additional_fields)
Expand Down
5 changes: 3 additions & 2 deletions gaetk/admin/sites.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import logging

from gaetk.admin import util
from gaetk.compat import xdb_kind


class AdminSite(object):
Expand All @@ -35,7 +36,7 @@ def register(self, model_class, admin_class=None):
# validate = lambda model, adminclass: None

if model_class in self._registry:
logging.warn(u'The model %s is already registered', util.get_kind(model_class))
logging.warn(u'The model %s is already registered', xdb_kind(model_class))

# Instantiate the admin class to save in the registry
self._registry[model_class] = admin_class(model_class, self)
Expand All @@ -49,7 +50,7 @@ def get_model_class(self, application, model):
"""Klasse zu 'model' zurückgeben."""

for model_class in self._registry:
if model == util.get_kind(model_class) and application == util.get_app_name(model_class):
if model == xdb_kind(model_class) and application == util.get_app_name(model_class):
return model_class


Expand Down
12 changes: 1 addition & 11 deletions gaetk/admin/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def get_app_name(model):
>>> get_app_name('frontend.news.models.NewsItem')
'news'
>>> get_app_name('common.models.Sparepart')
'Sparepart'
"""
if not hasattr(model, '__module__'):
return u''
Expand All @@ -33,17 +34,6 @@ def get_app_name(model):
return components[-2]


def get_kind(model_class):
"""Get kind from db or ndb model class"""
if hasattr(model_class, '_get_kind'):
kind = model_class._get_kind()
elif hasattr(model_class, '_get_kind'):
kind = model_class.kind()
else:
kind = model_class.__name__
return kind


def create_instance(klass, data):
"""Erzeuge eine Instanz eines Models aus den übergebenen Daten"""

Expand Down
5 changes: 3 additions & 2 deletions gaetk/admin/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
from gaetk.admin import search
from gaetk.admin.models import DeletedObject
from gaetk.admin.sites import site
from gaetk.admin.util import get_app_name, get_kind
from gaetk.admin.util import get_app_name
from gaetk.compat import xdb_kind


def make_app(url_mapping):
Expand Down Expand Up @@ -68,7 +69,7 @@ def get(self):
apps = {}
for model_class in site.registry.keys():
application = get_app_name(model_class)
apps.setdefault(application, []).append(get_kind(model_class))
apps.setdefault(application, []).append(xdb_kind(model_class))
self.render({'apps': apps}, 'admin/index.html')


Expand Down
86 changes: 86 additions & 0 deletions gaetk/compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#!/usr/bin/env python
# encoding: utf-8
"""
gaetk/comp.py compability layer for App Engine
Created by Dr. Maximillian Dornseif on 2014-12-10.
Copyright (c) 2014 HUDORA GmbH. All rights reserved.
"""

from urllib import unquote

from google.appengine.ext import db
from google.appengine.ext import ndb

def xdb_kind(model_class):
"""Get kind from db or ndb model class"""
kind = getattr(model_class, '_get_kind', None)
if not kind:
kind = getattr(model_class, 'kind', None)
if not kind:
return model_class.__name__
return kind()

def xdb_get(model_class, encoded_key):
"""Ermittle die Instanz über den gegeben ID"""
if issubclass(model_class, ndb.Model):
key = ndb.Key(urlsafe=encoded_key)
instance = key.get()
elif issubclass(model_class, db.Model):
instance = model_class.get(unquote(encoded_key))
return instance

def xdb_is_ndb(model_class):
if hasattr(model_class, 'all'):
return False
else:
return True

def xdb_key(instance):
if xdb_is_ndb(instance):
return instance.key
else:
return instance.key()

def xdb_to_protobuf(instance):
if xdb_is_ndb(instance):
return ndb.ModelAdapter().entity_to_pb(instance).Encode()
else:
db.model_to_protobuf(instance).Encode()

def _get_queryset_db(model_class, ordering=None):
"""Queryset für Subklasse von db.Model"""
query = model_class.all()
if ordering:
attr, direction = ordering
if attr in model_class.properties():
if direction == '-':
attr = '-' + attr
query.order(attr)
return query

def _get_queryset_ndb(model_class, ordering):
"""Queryset für Subklasse von ndb.Model"""
query = model_class.query()
if ordering:
attr, direction = ordering
prop = model_class._properties.get(attr)
if prop:
if direction == '-':
return query.order(-prop)
else:
return query.order(prop)
return query

def xdb_queryset(model_class, ordering=None):
"""Gib das QuerySet für die Admin-Seite zurück
Es wird die gewünschte Sortierung durchgeführt.
"""
# TODO: Tupel: (attr, direction)
if xdb_is_ndb(model_class):
query = _get_queryset_ndb(model_class, ordering)
else:
query = _get_queryset_db(model_class, ordering)
return query

6 changes: 4 additions & 2 deletions templates/base_admin.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@
}
</style>
{% endblock gaetkstyle %}
<!-- is_admin = "{{ is_admin }}" -->
<!-- profiler_request_id = "{{ profiler_request_id }}" -->
{% if is_admin and profiler_request_id -%}<link rel="stylesheet" type="text/css" href="/gae_mini_profiler/static/css/profiler.css" />{%- endif %}
{% block stylesheets -%}{%- endblock %}
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" type="text/javascript"></script>
Expand Down Expand Up @@ -83,6 +81,10 @@
<h1>{% block firstheading %}{% if title is defined %}{{ title|e }}{% endif %}{% endblock %}
{# <small>Supporting text or tagline</small> #}</h1>
</div>

{% block breadcrumbs %}
{% endblock breadcrumbs %}

<div class="row">
{% block mainrow -%}
<div class="span9" id="maincontent">
Expand Down

0 comments on commit fbff6f1

Please sign in to comment.