how to make a custom filter in flask admin - flask-admin

What am I doing wrong in this?? I am getting an exception thrown.
Exception: Invalid field : does not contains any columns.
I actually want to filter results from three different columns containing the cost of rooms.If any room satisfies a certain condition from the three rooms then it should appear on the list. That's why I want to make a custom filter.
Please help me. Thanks in advance.
from flask.ext.admin.babel import lazy_gettext
from flask.ext.admin.model import filters
class MyBaseFilter(filters.BaseFilter):
"""
Base SQLAlchemy filter.
"""
def __init__(self, column, name, options=None, data_type=None):
"""
Constructor.
:param column:
Model field
:param name:
Display name
:param options:
Fixed set of options
:param data_type:
Client data type
"""
super(MyBaseFilter, self).__init__(name, options, data_type)
self.column = column
class Views():
class HotelAdmin(ModelView):
class FilterCost(MyBaseFilter):
def apply(self, query, value):
return query.filter(self.column > value)
def operation(self):
return lazy_gettext('Cost')
column_labels = {'hotel_name':'Hotel Details'}
column_list = ('hotel_name','website')
column_searchable_list = ('city',)
column_filters = (FilterCost(Table.Hotel.deluxe_room,'Cost'),'state')

I did the following and it worked:
added:
from flask.ext.admin.contrib.sqla import filters
removed:
from flask.ext.admin.model import filters AND
class MyBaseFilter(filters.BaseFilter)
and then I inherited "filters.BaseSQLAFilter" in my filter class.
But still, How can I use "class MyBaseFilter(filters.BaseFilter)", It is still throwing an error

Related

constructing a mongo doc using pymodm from_document

I am trying to construct a pymodm document from a python dictionary using from_document api. I am receiving a error "ValueError: Unrecognized field name 'prim_key'"
Here is the sample code that I have written to make this happen with minimum code.
from pymodm import connect, EmbeddedMongoModel, MongoModel, fields
from pymodm.errors import ValidationError, ConfigurationError
from pymongo.write_concern import WriteConcern
import pprint
from datetime import datetime
class sample_doc(MongoModel):
prim_key = fields.CharField(primary_key=True)
another_field = fields.CharField()
class Meta:
write_concern = WriteConcern(j=True)
connection_alias = 'pymodm-tester'
connect("mongodb://localhost:27017/pymodm-tester", alias="pymodm-tester")
q = {'prim_key' : 'prim_val', "another_field" : "another_filed1" }
sample_doc.from_document(q).save()
In the docs:
document: A Python dictionary describing a MongoDB document. Keys
within the document must be named according to each model field’s
mongo_name attribute, rather than the field’s Python name.
It looks that, in order to instantiate a Model as you try, it needs to be specified the mongo_name Field. It would work for you something like:
class sample_doc(MongoModel):
prim_key = fields.CharField(primary_key=True, mongo_name="prim_key")
another_field = fields.CharField(mongo_name="another_field")
class Meta:
write_concern = WriteConcern(j=True)
connection_alias = 'pymodm-tester'

Sqlalchemy + Postgres: synthetic/artificial id mixin with sequence

I've found the mixin pattern to be really handy for staying DRY, but I am having trouble with sequences. Note, I'm using postgres.
We use alembic migrations, and I'd really like the --autogeneration to work with this sequence, though I understand this might not be possible right now. However, it looks like setting up the sequence without an ORM identifier, prevents the sequence from being dropped later if I wanted to perform a downgrade.
Through googling, I found some explanation on how to properly setup a sequence. Essentially: separate the id and its sequence.
Current Code looks a bit like this:
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declared_attr
class AutoIdMixin(object):
"""Generates an synthetic identifier primary key.
"""
# See: http://docs.sqlalchemy.org/en/latest/core/defaults.html#associating-a-sequence-as-the-server-side-default
#declared_attr
def id_seq(cls):
bases = cls.__bases__
Base = bases[0]
sequence_prefix = 'seq'
schema = cls._schema_name
sequence_id = '_'.join((sequence_prefix, schema, cls.__tablename__, 'id'))
sequence = sa.Sequence(sequence_id, 1, 1, metadata=Base.metadata)
return sequence
#declared_attr
def id(cls):
column_id = sa.Column(sa.types.Integer, cls.id_seq.next_value(), primary_key=True)
return column_id
With the code above, I end up with a non-helpful error:
AttributeError: Neither 'next_value' object nor 'Comparator' object has an attribute '_set_parent_with_dispatch'
In an RTM moment, it looks like I missed a keyword: server_default.
#declared_attr
def id(cls):
sequence = cls.id_seq
column_id = sa.Column(sa.types.Integer, server_default=sequence.next_value(), primary_key=True)
return column_id

plone.formwidget - Is it possible to set a MasterSelect Field as an AutocompleteFieldWidget?

I am trying to set a MasterSelect field to an AutocompleteFieldWidget.
I'm using AutocompleteFieldWidget from plone.formwidget.autocomplete and the MasterSelectField from plone.formwidget.MasterSelect. The slave field belonging to the MasterSelectField is also a MasterSelectField.
The autocomplete functions as it should (retrieving the values based on input), but the slave field's choices do not change. However, when its not set as an autocomplete, everything works as it should.
Edit:
In my buildout-cache, I looked at widget.py in plone.formwidget.masterselect and tried placing a print statement in getSlaves and that function wasn't getting called. I tried the render function and that wasn't getting called either. Then I placed a print statement in MasterSelectField and that was notgetting called. Setting the field to an Autocomplete widget removes any trace that its a Master Select field.
Edit: In the init.py file in plone.formwidget.masterselect, I placed a print statement in the init function of the MasterSelectField, and the slave widget does print, where as in getSlaves in widget.py it doesn't. This is the output I'm getting from printing in the init and what I should be getting in getSlaves:
({'action': 'vocabulary', 'masterID': 'form-widgets-IMyForm-master_field',
'control_param': 'master_value', 'name': 'IMyForm.slave_field',
'vocab_method': <class 'my.product.vocabulary.SlaveVocab'>},)
I have my interface:
from plone.directives import form
class IMyForm(model.Schema):
form.widget(master_field=AutocompleteFieldWidget)
master_field = MasterSelectField(
title=_(u'Master'),
slave_fields=({'name':'IMyForm.slave_field',
'action':'vocabulary',
'source':MySource,
'control_param':'master_value'
}),
required=True,
)
slave_field = MasterSelectField(title=_(u'Slave Field'),
source=SlaveVocab,
slave_fields=(....
)
required=False,
)
I have my source object for the master field:
class MySource(object):
implements(IQuerySource)
def __init__(self, context):
simple_terms = []
#Query portal catalog for unique indexes, and fill with simple terms
self.vocab = SimpleVocabulary(simple_terms)
def __contains__(self, term):
return self.vocab.__contains__(term)
def getTermByToken(self, token):
return self.getTermByToken(token)
def getTerm(self, value):
return self.getTerm(value)
def search(self, query_string):
return [term for term in self.vocab if query_string in term.title.lower()]
class MySourceBinder(object):
implements(IContextSourceBinder)
def __call__(self, context):
return MySource(context)
My slave field's source is:
class SlaveVocab(object):
grok.implements(IContextSourceBinder)
def __init__(self, **kw):
self.master_value = kw.get('master_value', None)
def __call__(self, context):
if self.master_value is None or self.master_value == "--NOVALUE--"
self.master_value = getattr(context,'master_field',None)
#Still nothing, return empty vocabulary
if self.master_value is None or self.master_value == '--NOVALUE--':
return SimpleVocabulary([])
terms = []
#If not null, building a simple vocabulary to return
return SimpleVocabulary(terms)
I did a print statement in call of the Slave Vocabulary and it was being called, but nothing was being passed in.
I also tried using another widget, ChosenFieldWidget. I get the same results in that it functions as it should, but the slave field's choices do not change. Is it possible to set a master select field to an autocomplete? If so, what am I doing wrong?
Also, I'm using Solgema.fullcalendar and the content type extends the IEventBasic behavior, so I don't have access to using my own form class I would've liked to have used since Solgema seems to render its own forms.
Edit:
I am using Plone 4.3

how to use composite data types (e.g. geomval) in SQLAlchemy?

I'm trying to replicate a nested raw PostGreSQL/PostGIS raster query using SQLAlchemy(0.8)/GeoAlchemy2(0.2.1) and can't figure how to access the components of a geomval data type. It's a compound data type that returns a 'geom' and a 'val'.
Here is the raw query that works:
SELECT (dap).val, (dap).geom
FROM (SELECT ST_DumpAsPolygons(rast) as dap FROM my_raster_table) thing
And the SQLAlchemy query I'm currently working with:
import geoalchemy2 as ga2
from sqlalchemy import *
from sqlalchemy.orm import sessionmaker
metadata = MetaData()
my_raster_table = Table('my_raster_table', metadata,
Column('rid', Integer),
Column('rast', ga2.Raster))
engine = create_engine(my_conn_str)
session = sessionmaker(engine)()
q = session.query(ga2.func.ST_DumpAsPolygons(my_raster_table.c.rast).label('dap'))
And then I'd like to access that in a subquery, something like this:
q2 = session.query(ga2.func.ST_Area(q.subquery().c.dap.geom))
But that syntax doesn't work, or I wouldn't be posting this question ;). Anyone have ideas? Thanks!
The solution ended up being fairly simple:
First, define a custom GeomvalType, inheriting geoalchemy2's CompositeType and specifying a typemap specific to geomval:
class GeomvalType(ga2.types.CompositeType):
typemap = {'geom':ga2.Geometry('MULTIPOLYGON'),'val':Float}
Next, use type_coerce to cast the ST_DumpAsPolygons result to the GeomvalType in the initial query:
q = session.query(type_coerce(ga2.func.ST_DumpAsPolygons(my_raster_table.c.rast), GeomvalType()).label('dap'))
Finally, access it (successfully!) from the subquery as I was trying to before:
q2 = session.query(ga2.func.ST_Area(q.subquery().c.dap.geom))

Django-Nonrel with Mongodb listfield

I am trying to implement manytomany field relation in django-nonrel on mongodb. It was suggessted at to:
Django-nonrel form field for ListField
Following the accepted answer
models.py
class MyClass(models.Model):
field = ListField(models.ForeignKey(AnotherClass))
i am not sure where the following goes, it has been tested in fields.py, widgets,py, models.py
class ModelListField(ListField):
def formfield(self, **kwargs):
return FormListField(**kwargs)
class ListFieldWidget(SelectMultiple):
pass
class FormListField(MultipleChoiceField):
"""
This is a custom form field that can display a ModelListField as a Multiple Select GUI element.
"""
widget = ListFieldWidget
def clean(self, value):
#TODO: clean your data in whatever way is correct in your case and return cleaned data instead of just the value
return value
admin.py
class MyClassAdmin(admin.ModelAdmin):
form = MyClassForm
def __init__(self, model, admin_site):
super(MyClassAdmin,self).__init__(model, admin_site)
admin.site.register(MyClass, MyClassAdmin)
The following Errors keep popping up:
If the middle custom class code is used in models.py
name 'SelectMultiple' is not defined
If custom class code is taken off models.py:
No form field implemented for <class 'djangotoolbox.fields.ListField'>
You just need to import SelectMultiple by the sound of it. You can put the code in any of those three files, fields.py would make sense.
Since it's pretty usual to have:
from django import forms
at the top of your file already, you probably just want to edit the code below to:
# you'll have to work out how to import the Mongo ListField for yourself :)
class ModelListField(ListField):
def formfield(self, **kwargs):
return FormListField(**kwargs)
class ListFieldWidget(forms.SelectMultiple):
pass
class FormListField(forms.MultipleChoiceField):
"""
This is a custom form field that can display a ModelListField as a Multiple Select GUI element.
"""
widget = ListFieldWidget
def clean(self, value):
#TODO: clean your data in whatever way is correct in your case and return cleaned data instead of just the value
return value
You probably also want to try and learn a bit more about how python works, how to import modules etc.