def get_model_class(self, application, model): """Klasse zu 'model' zurückgeben.""" for model_class in self._registry: if model == xdb_kind( model_class) and application == util.get_app_name( model_class): return model_class
def get(self): """Zeige Template mit allen registrierten Models an""" apps = {} for model_class in site.registry.keys(): application = get_app_name(model_class) apps.setdefault(application, []).append(xdb_kind(model_class)) self.render({'apps': apps}, 'admin/index.html')
def export_view_xls(self, handler, extra_context=None): # pylint: disable=W0613 """Request zum Exportieren von allen Objekten behandeln. `extra_context` ist für die Signatur erforderlich, wird aber nicht genutzt. """ exporter = modelexporter.ModelExporter(self.model) filename = '%s-%s.xls' % (compat.xdb_kind(self.model), datetime.datetime.now()) handler.response.headers['Content-Type'] = 'application/msexcel' handler.response.headers['content-disposition'] = \ 'attachment; filename=%s' % filename exporter.to_xls(handler.response)
def export_view_xls(self, handler, extra_context=None): # pylint: disable=W0613 """Request zum Exportieren von allen Objekten behandeln. `extra_context` ist für die Signatur erforderlich, wird aber nicht genutzt. """ exporter = modelexporter.ModelExporter(self.model) filename = '%s-%s.xls' % (compat.xdb_kind( self.model), datetime.datetime.now()) handler.response.headers['Content-Type'] = 'application/msexcel' handler.response.headers['content-disposition'] = \ 'attachment; filename=%s' % filename exporter.to_xls(handler.response)
def export_view_csv(self, handler, extra_context=None): # pylint: disable=W0613 """Request zum Exportieren von allen Objekten behandeln. `extra_context` ist für die Signatur erforderlich, wird aber nicht genutzt. """ # irgendwann werden wir hier einen longtask nutzen muessen exporter = modelexporter.ModelExporter(self.model) 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 exporter.to_csv(handler.response)
def export_view_csv(self, handler, extra_context=None): # pylint: disable=W0613 """Request zum Exportieren von allen Objekten behandeln. `extra_context` ist für die Signatur erforderlich, wird aber nicht genutzt. """ # irgendwann werden wir hier einen longtask nutzen muessen exporter = modelexporter.ModelExporter(self.model) 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 exporter.to_csv(handler.response)
def upload_to_blobstore(obj, key_name, blob): """ Lade ein Datei-ähnliches Objekt in den Blobstore Der Rückgabewert ist der Blob-Key des neuen Objekts. """ mime_type, _ = mimetypes.guess_type(blob.filename) bucket = getattr(config, 'GCS_BUCKET_NAME', app_identity.get_default_gcs_bucket_name()) file_name = '/%s/admin/%s/%s/%s' % (bucket, xdb_kind(obj), key_name, blob.filename) with cloudstorage.open(file_name, 'w', content_type=mime_type) as fileobj: while blob.file: data = blob.file.read(8192) if not data: break fileobj.write(data) return blobstore.BlobKey(blobstore.create_gs_key('/gs' + file_name))
def get_impl(self, typ, additional_context=None): query = self.prepare_query() model_class = compat.xdb_kind_from_query(query) kind = compat.xdb_kind(model_class) if not self.filename: self.filename = u'%s-%s-%s' % (kind, datetime.datetime.now(), self.credential.uid) exporter = modelexporter.ModelExporter(model_class, query=query, uid=self.credential.uid, **self.exporter_config) typ = typ.strip('/') if typ in {'xls', 'csv'}: self.check_download_permission() self.handle_download(typ, kind, exporter) else: loginfo = gaetk_ExportLog.query( gaetk_ExportLog.tablename == kind).order( -gaetk_ExportLog.created_at).fetch_async(10) rowtemplate, headtemplate = self.get_rowtemplate(exporter) myvalues = self.default_template_vars({}) values = dict( title=myvalues.get('title', self.title), widetable=self.widetable, filename=self.filename, downloadlog=loginfo.get_result(), header=self.header, rowtemplate=rowtemplate, headtemplate=headtemplate, ) values.update(self.get_pagination(query)) if additional_context: values.update(additional_context) if self.request.path.endswith('.html'): parsed_url = urlparse.urlparse(self.request.path) values[ 'listviewer_urlbase'] = '://' + parsed_url.netloc + parsed_url.path self.render(values, self.template)
def register(self, model_class, admin_class=None): """Registers the given model with the given admin class.""" # We have some very nasty problems with cyclic imports # site registry depends on options and options depends # on a lot of stuff which depends on the site registry # if we would be able to break the dependency between the registry # AdminSite and ModelAdmin things would be much easier. if admin_class is None: admin_class = ModelAdmin # # Don't import the humongous validation code unless required # if admin_class and settings.DEBUG: # from django.contrib.admin.validation import validate # else: # validate = lambda model, adminclass: None if model_class in self._registry: 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)
def register(self, model_class, admin_class=None): """Registers the given model with the given admin class.""" # We have some very nasty problems with cyclic imports # site registry depends on options and options depends # on a lot of stuff which depends on the site registry # if we would be able to break the dependency between the registry # AdminSite and ModelAdmin things would be much easier. if admin_class is None: admin_class = ModelAdmin # # Don't import the humongous validation code unless required # if admin_class and settings.DEBUG: # from django.contrib.admin.validation import validate # else: # validate = lambda model, adminclass: None if model_class in self._registry: logger.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)
def add_view(self, handler, extra_context=None): """View zum Hinzufügen eines neuen Objekts""" form_class = self.get_form() # Standardmaessig lassen wir die App Engine fuer das Model automatisch einen # Key generieren. Es besteht jedoch in der Admin-Klasse die Moeglichkeit, via # 'db_key_field=[propertyname]' ein Feld festzulegen, dessen Inhalt im Formular # als Key beim Erzeugen der Instanz genutzt wird. admin_class = site.get_admin_class(self.model) key_field = None if admin_class and hasattr(admin_class, 'db_key_field'): key_field = admin_class.db_key_field # Wenn das Formular abgeschickt wurde und gültig ist, # speichere das veränderte Objekt und leite auf die Übersichtsseite um. if handler.request.method == 'POST': form = form_class(handler.request.POST) if form.validate(): form_data = self._convert_property_data(form.data) key_name = form_data.get(key_field) if key_field else None # TODO: util.create_instance nutzen oder entfernen if hasattr(self.model, 'create'): factory = self.model.create else: factory = self.model if issubclass(self.model, ndb.Model): obj = factory(id=key_name, **form_data) else: obj = factory(key_name=key_name, **form_data) # Beim Anlegen muss dann halt einmal gespeichert werden, # ansonsten ist der ID unbekannt. if self.blob_upload_fields and key_name is None: key_name = compat.xdb_id_or_name(obj.put()) self.handle_blobstore_fields(handler, obj, key_name) key = obj.put() handler.add_message( 'success', u'<strong><a href="/admin/{}/{}/{}/">{} {}</a></strong> wurde angelegt.' .format(util.get_app_name(self.model), compat.xdb_kind(self.model), compat.xdb_str_key(key), compat.xdb_kind(self.model), compat.xdb_id_or_name(key))) # Indexierung für Admin-Volltextsuche from gaetk.admin.search import add_to_index deferred.defer(add_to_index, key) # Call post-create-hooks if isinstance(self.post_create_hooks, collections.Iterable): for hook in self.post_create_hooks: deferred.defer(util.call_hook, hook, compat.xdb_str_key(key)) raise gaetk.handler.HTTP302_Found(location='..') else: form = form_class() template_values = { 'form': form, 'field_args': self.field_args, 'admin_class': self } if extra_context is not None: template_values.update(extra_context) handler.render(template_values, self.get_template('add'))
def change_view(self, handler, object_id, extra_context=None): """View zum Bearbeiten eines vorhandenen Objekts""" obj = self.get_object(object_id) if obj is None: raise gaetk.handler.HTTP404_NotFound model_class = type(obj) form_class = self.get_form() if handler.request.get('delete') == 'yesiwant': # Der User hat gebeten, dieses Objekt zu löschen. key = compat.xdb_key(obj) data = compat.xdb_to_protobuf(obj) dblayer = 'ndb' if compat.xdb_is_ndb(obj) else 'db' 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 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>{} {}</strong> wurde gelöscht. <a href="{}">Objekt wiederherstellen!</a>' .format(compat.xdb_kind(self.model), compat.xdb_id_or_name(key), archived.undelete_url())) raise gaetk.handler.HTTP302_Found( location='/admin/%s/%s/' % (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. if handler.request.method == 'POST': form = form_class(handler.request.POST) if form.validate(): key_name = compat.xdb_id_or_name(compat.xdb_key(obj)) self.handle_blobstore_fields(handler, obj, key_name) if hasattr(obj, 'update'): obj.update(form.data) else: form.populate_obj(obj) key = obj.put() handler.add_message( 'success', u'<strong><a href="/admin/{}/{}/{}/">{} {}</a></strong> wurde gespeichert.' .format(util.get_app_name(self.model), compat.xdb_kind(self.model), compat.xdb_str_key(key), compat.xdb_kind(self.model), compat.xdb_id_or_name(key))) # Indexierung für Admin-Volltextsuche 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), compat.xdb_kind(model_class))) else: form = form_class(obj=obj) template_values = { 'object': obj, 'form': form, 'field_args': self.field_args, 'admin_class': self } if extra_context is not None: template_values.update(extra_context) handler.render(template_values, self.get_template('change'))
def get_model_class(self, application, model): """Klasse zu 'model' zurückgeben.""" for model_class in self._registry: if model == xdb_kind(model_class) and application == util.get_app_name(model_class): return model_class
def add_view(self, handler, extra_context=None): """View zum Hinzufügen eines neuen Objekts""" form_class = self.get_form() # Standardmaessig lassen wir die App Engine fuer das Model automatisch einen # Key generieren. Es besteht jedoch in der Admin-Klasse die Moeglichkeit, via # 'db_key_field=[propertyname]' ein Feld festzulegen, dessen Inhalt im Formular # als Key beim Erzeugen der Instanz genutzt wird. admin_class = site.get_admin_class(self.model) key_field = None if admin_class and hasattr(admin_class, 'db_key_field'): key_field = admin_class.db_key_field # Wenn das Formular abgeschickt wurde und gültig ist, # speichere das veränderte Objekt und leite auf die Übersichtsseite um. if handler.request.method == 'POST': form = form_class(handler.request.POST) if form.validate(): form_data = self._convert_property_data(form.data) key_name = form_data.get(key_field) if key_field else None # TODO: util.create_instance nutzen oder entfernen if hasattr(self.model, 'create'): factory = self.model.create else: factory = self.model if issubclass(self.model, ndb.Model): obj = factory(id=key_name, **form_data) else: obj = factory(key_name=key_name, **form_data) # Beim Anlegen muss dann halt einmal gespeichert werden, # ansonsten ist der ID unbekannt. if self.blob_upload_fields and key_name is None: key_name = compat.xdb_id_or_name(obj.put()) self.handle_blobstore_fields(handler, obj, key_name) key = obj.put() handler.add_message( 'success', u'<strong><a href="/admin/{}/{}/{}/">{} {}</a></strong> wurde angelegt.'.format( util.get_app_name(self.model), compat.xdb_kind(self.model), compat.xdb_str_key(key), compat.xdb_kind(self.model), compat.xdb_id_or_name(key))) # Indexierung für Admin-Volltextsuche from gaetk.admin.search import add_to_index deferred.defer(add_to_index, key) # Call post-create-hooks if isinstance(self.post_create_hooks, collections.Iterable): for hook in self.post_create_hooks: deferred.defer(util.call_hook, hook, compat.xdb_str_key(key)) raise gaetk.handler.HTTP302_Found(location='..') else: form = form_class() template_values = {'form': form, 'field_args': self.field_args, 'admin_class': self} if extra_context is not None: template_values.update(extra_context) handler.render(template_values, self.get_template('add'))
def change_view(self, handler, object_id, extra_context=None): """View zum Bearbeiten eines vorhandenen Objekts""" obj = self.get_object(object_id) if obj is None: raise gaetk.handler.HTTP404_NotFound model_class = type(obj) form_class = self.get_form() if handler.request.get('delete') == 'yesiwant': # Der User hat gebeten, dieses Objekt zu löschen. key = compat.xdb_key(obj) data = compat.xdb_to_protobuf(obj) dblayer = 'ndb' if compat.xdb_is_ndb(obj) else 'db' 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 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>{} {}</strong> wurde gelöscht. <a href="{}">Objekt wiederherstellen!</a>'.format( compat.xdb_kind(self.model), compat.xdb_id_or_name(key), archived.undelete_url())) raise gaetk.handler.HTTP302_Found(location='/admin/%s/%s/' % ( 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. if handler.request.method == 'POST': form = form_class(handler.request.POST) if form.validate(): key_name = compat.xdb_id_or_name(compat.xdb_key(obj)) self.handle_blobstore_fields(handler, obj, key_name) if hasattr(obj, 'update'): obj.update(form.data) else: form.populate_obj(obj) key = obj.put() handler.add_message( 'success', u'<strong><a href="/admin/{}/{}/{}/">{} {}</a></strong> wurde gespeichert.'.format( util.get_app_name(self.model), compat.xdb_kind(self.model), compat.xdb_str_key(key), compat.xdb_kind(self.model), compat.xdb_id_or_name(key))) # Indexierung für Admin-Volltextsuche 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), compat.xdb_kind(model_class))) else: form = form_class(obj=obj) template_values = {'object': obj, 'form': form, 'field_args': self.field_args, 'admin_class': self} if extra_context is not None: template_values.update(extra_context) handler.render(template_values, self.get_template('change'))