I have an ndb.Model that contains an ndb.Expando model as a structured property, and I'd like to be able to control indexing, but I cannot find anything in the documentation about it.
class MyModel2(ndb.Expando):
pass
class MyModel(ndb.Model):
sub_entity = ndb.StructuredProperty(MyModel2)
The only piece of documentation I can find is the following:
You can specify the usual property options for structured properties
(except indexed)
I assume this is because the actual indexing should be specified on a per-property basis in the embedded model. However, it is not clear how to enable or disable indexing on Expando model properties.
You can use the _properties object to set if a field should be indexed or not. E.g.
a = MyModel2()
a.value = '3'
a._properties['value']._indexed = False
You can find the docs on _properties have more details.
Related
for example I got:
bpy.types.Modifier.bl_rna.properties['type'].enum_items[12]
(boolean modifier)
The Boolean modifier has a property called "object" for the actual bool mesh.
How can I quickly check if it actually got the "object" property available (through bpy.types) ?
I want to filter modifiers by their properties something like:
[modifier.identifier for modifier in bpy.types.Modifier.bl_rna.properties['type'].enum_items if modifier.object != NULL]
obviously this wont work, just added it for giving you a better idea of what Im trying todo.
bpy.types contains the class definitions. bpy.data contains the instances used to define objects in your blender scene. bpy.context can provide easy access to several points of interest instead of using bpy.data directly, such as the active scene and object as well as lists of selected and visible objects.
As a class definition, bpy.types can only tell you what properties each type can contain, which may be after modifications. For example, an addon can use bpy.props to add properties to an existing data type, this is done on the class definition within bpy.types.
Each subclass of bpy.types.Modifier has its own properties, the BooleanModifier has an object property, this is the second object that will interact with the mesh of the modifiers parent mesh.
To access data on a specific instance of an item, you need to find the relevant data in bpy.data, or bpy.context.
For example, if a Cube had a boolean modifer that unions its mesh with a Sphere mesh, you could get the following in the python console.
>>> bpy.data.objects['Cube'].modifiers['Boolean'].object
bpy.data.objects['Sphere']
>>> bpy.data.objects['Cube'].modifiers['Boolean'].operation
'UNION'
In another forum I was made aware of the python function dir() which lists all properties of an entity.
So:
for mods in orig_active.modifiers:
for properties in dir(mods):
if "__" not in properties:
props=eval("type(mods."+str(properties)+")")
if "Object" in str(props):
print(mods.name + "modifier got a property called 'object'.")
A bit clunky but it works.
I have been trying to define custom django model field in python. I referred the django docs at following location https://docs.djangoproject.com/en/1.10/howto/custom-model-fields/. However, I am confused over the following methods(which I have divided into groups as per my understanding) :-
Group 1 (Methods in this group are inter-related as per docs)
__init__()
deconstruct()
Group 2
db_type()
rel_db_type()
get_internal_type()
Group 3
from_db_value()
to_python()
get_prep_value()
get_db_prep_value()
get_db_prep_save()
value_from_object()
value_to_string()
Group 4
formfield
I am having following questions :-
When deconstruct() is used ? Docs says that, it's useful during migration, but it's not clearly explained. Moreover, when is it called ?
Difference between db_type() and get_internal_type()
Difference between get_prep_value() and get_db_prep_value()
Difference between value_from_object() and value_to_string(). value_from_object() is not given in docs.
Both from_db_value(), value_to_string() and to_python() gives python object from string. Then, why these different methods are exists ?
I know, I have asked a bit lengthy question. But couldn't find any other way to better ask this question.
Thanks in advance.
I'll try to answer them:
Q: When deconstruct() is used ?
A: This method is being used when you have instance of your Field to re-create it based on arguments you just passed in __init__.
As they mentioned in docs, if you are setting max_length arg to a static value in your __init__ method; you do not need it for your instances. So you can delete it in your deconstruct() method. With this, max_length won't show up in your instance while you are using it in your models. You can think deconstruct as a last clean-up and control place before use your field in model.
Q: Difference between db_type() and get_internal_type()
A: They are both related, but belong to different levels.
If your custom field's data type is depends on which DB you are using, db_type() is the place you can do your controls. Again, like they mentioned in docs, if your field is a kind of date/time value, you should / may check if current database is PostgreSQL or MySQL in this method. Because while date/time values called as timestamp in PostgreSQL, it is called datetime in MySQL.
get_internal_type method is kind of higher level version of db_type(). Let's go over date/time value example: If you don't want to check and control each data types belongs to different databases, you can inherit your custom field's data type from built-in Django fields. Instead of checking if it should be datetime or timestamp; you can return simply DateField in your get_internal_type method. As they mentioned in docs, If you've created db_type method already, in most cases, you do not need get_internal_type method.
Q: Difference between get_prep_value() and get_db_prep_value()
A: These guys also share almost same logic between db_type() and get_internal_type(). First of all, both these methods stands for converting db values to python objects. But, like in db_type method, get_db_prep_value() stands for backend specific field types.
Q: Difference between value_from_object() and value_to_string(). value_from_object() is not given in docs
A: From the docs:
To customize how the values are serialized by a serializer, you can
override value_to_string(). Using value_from_object() is the best way
to get the field’s value prior to serialization.
So, Actually we don't need value_from_object as documented. This method is used to get field's raw value before serialization. Get the value with this method, and customize how it should be serialized in value_to_string method. They even put an example code in docs
Q: Both from_db_value(), value_to_string() and to_python() gives python object from string. Then, why these different methods are exists ?
A: While to_python() converts field value to a valid python object, value_to_string() converts field values to string with your custom serialization. They stands for different jobs.
And from_db_value converts the value returned by database to python object. Never heard of it actually. But check this part from docs:
This method is not used for most built-in fields as the database
backend already returns the correct Python type, or the backend itself
does the conversion.
I have a model in Flask-Admin with filter (e.g. based on Foreign Key to other model).
I want to generate links from front-end to this model view in admin with filter value applied. I noticed that it adds ?flt0_0= to the url, so that the whole address looks kinda:
http:/.../admin/model_view_<my model>/?flt0_0=<filter value>
Which is the best way to generate routes like this?
I prefer setting named_filter_urls=True on my base view to get rid of these magic numbers (though you can just set it on any specific view as well):
class MyBaseView(BaseModelView):
...
named_filter_urls = True
class MyView(MyBaseView):
...
column_filters = ['name', 'country']
This creates URLs like: http://.../admin/model/?flt_name_equals=foo&flt_country_contains=bar (*)
With this, your URLs can easily be contructed using the name of the attribute you want to filter on. As a bonus, you don't need to have a view instance available - important if you want to link to a view for a different model.
*(When selecting filters from UI, Flask-Admin will insert integers into the parameter keys. I'm not sure why it does that, but they don't appear necessary for simple filtering.)
Flask-Admin defaults to the flt0_0=<value> syntax to be "robust across translations" if your app needs to support multiple languages. If you don't need to worry about translations, setting named_filter_urls=True is the way to go.
With named_filter_urls=True Flask-Admin generates filter query parameters like:
flt0_country_contains=<value>
The remaining integer after flt (0 in this case) is a sort key used to control the order of the filters as they appear in the UI when you have multiple filters defined. This number does not matter at all if you have a single filter.
For example, in my app I have named filters turned on. If I have multiple filters without the sort key the filters are displayed in the order they appear in the query string:
?flt_balance_smaller_than=100&flt_balance_greater_than=5
Yields: Default filter ordering
With a sort key added to the flt parameters, then I can force those filters to be displayed in a different order (flt1 will come before flt2):
?flt2_balance_smaller_than=100&flt1_balance_greater_than=5
Yields: Forced filter ordering
In practice it looks like this sort key can be any single character, e.g. this works too:
?fltB_balance_smaller_than=100&fltA_balance_greater_than=5
This behavior is ultimately defined in the Flask-Admin BaseModelView._get_list_filter_args() method here:
https://github.com/flask-admin/flask-admin/blob/master/flask_admin/model/base.py#L1714-L1739
Unfortunately, there's no public API for this yet. Here's a short snippet you can use for now to generate fltX_Y query string:
class MyView(BaseModelView):
...
def get_filter_arg(self, filter_name, filter_op='equals'):
filters = self._filter_groups[filter_name].filters
position = self._filter_groups.keys().index(filter_name)
for f in filters:
if f['operation'] == filter_op:
return 'flt%d_%d' % (position, f['index'])
Then you can call this method on a your view instance:
print my_view.get_filter_arg('Name', 'contains')
I'm trying to do:
MyModel({'text': db.Text('text longer than 500 byets')})
But get:
BadValueError: Indexed value fb_education must be at most 500 bytes
I'm thinking this is just a carry over from this issue with the old db api.
https://groups.google.com/forum/?fromgroups#!topic/google-appengine/wLAwrjtsuks
First create entity dynamically :
kindOfEntity = "MyTable"
class DynamicEntity(ndb.Expando):
#classmethod
def _get_kind(cls):
return kindOfEntity
then after to assign Text Properties run time/dynamically as shown below
dbObject = DynamicEntity()
key = "studentName"
value = "Vijay Kumbhani"
textProperties = ndb.TextProperty(key)
dbObject._properties[key] = {}
dbObject._values[key] = {}
dbObject._properties[key] = textProperties
dbObject._values[key] = value
dbObject.put()
then after key properties assign with Text properties
You're trying to use a db.Text, part of the old API, with NDB, which isn't going to work.
To the best of my knowledge, there's no good way to set unindexed properties in an Expando in NDB, currently. You can set _default_indexed = False on your expando subclass, as (briefly) documented here, but that will make the default for all expando properties unindexed.
A better solution would be to avoid the use of Expando alltogether; there are relatively few compelling uses for it where you wouldn't be better served by defining a model (or even defining one dynamically).
Yeah, I know question is old. But I also googled for same solutions and not found any result.
So here receipt that works for me (I expand User() with "permissions" property):
prop = ndb.GenericProperty("permissions", indexed=False)
prop._code_name = "permissions"
user._properties["permissions"] = prop
prop._set_value(user, permissions)
The previous answer was VERY use to me... Thanks!!! I just wanted to add that it appears you can also create a specific property type using this technique (if you know the datatype you want to create). When the entity is later retrieved, the dynamic property is set to the specific type instead of GenericProperty. This can be handy for ndb.PickleProperty and ndb.JsonProperty values in particular (to get the in/out conversions).
prop = ndb.TextProperty("permissions", indexed=False)
prop._code_name = "permissions"
user._properties["permissions"] = prop
prop._set_value(user, permissions)
I was trying to just change one property of an entity to Text. But when you don't map your properties explicitly, Expando/Model seem to change all properties of an entity to GenericProperty (after get).
When you put those entities again (to change the desired property), it affects other existing TextProperties, changing then to regular strings.
Only the low-level datastore api seems to work:
https://gist.github.com/feroult/75b9ab32b463fe7f9e8a
You can call this from the remote_api_shell.py:
from yawp import *
yawp(kind).migrate(20, 'change_property_to_text', 'property_name')
I want to make attributes of GAE Model properties. The reason is for cases like to turn the value into uppercase before storing it. For a plain Python class, I would do something like:
Foo(db.Model):
def get_attr(self):
return self.something
def set_attr(self, value):
self.something = value.upper() if value != None else None
attr = property(get_attr, set_attr)
However, GAE Datastore have their own concept of Property class, I looked into the documentation and it seems that I could override get_value_for_datastore(model_instance) to achieve my goal. Nevertheless, I don't know what model_instance is and how to extract the corresponding field from it.
Is overriding GAE Property classes the right way to provides getter/setter-like functionality? If so, how to do it?
Added:
One potential issue of overriding get_value_for_datastore that I think of is it might not get called before the object was put into datastore. Hence getting the attribute before storing the object would yield an incorrect value.
Subclassing GAE's Property class is especially helpful if you want more than one "field" with similar behavior, in one or more models. Don't worry, get_value_for_datastore and make_value_from_datastore are going to get called, on any store and fetch respectively -- so if you need to do anything fancy (including but not limited to uppercasing a string, which isn't actually all that fancy;-), overriding these methods in your subclass is just fine.
Edit: let's see some example code (net of imports and main):
class MyStringProperty(db.StringProperty):
def get_value_for_datastore(self, model_instance):
vv = db.StringProperty.get_value_for_datastore(self, model_instance)
return vv.upper()
class MyModel(db.Model):
foo = MyStringProperty()
class MainHandler(webapp.RequestHandler):
def get(self):
my = MyModel(foo='Hello World')
k = my.put()
mm = MyModel.get(k)
s = mm.foo
self.response.out.write('The secret word is: %r' % s)
This shows you the string's been uppercased in the datastore -- but if you change the get call to a simple mm = my you'll see the in-memory instance wasn't affected.
But, a db.Property instance itself is a descriptor -- wrapping it into a built-in property (a completely different descriptor) will not work well with the datastore (for example, you can't write GQL queries based on field names that aren't really instances of db.Property but instances of property -- those fields are not in the datastore!).
So if you want to work with both the datastore and for instances of Model that have never actually been to the datastore and back, you'll have to choose two names for what's logically "the same" field -- one is the name of the attribute you'll use on in-memory model instances, and that one can be a built-in property; the other one is the name of the attribute that ends up in the datastore, and that one needs to be an instance of a db.Property subclass and it's this second name that you'll need to use in queries. Of course the methods underlying the first name need to read and write the second name, but you can't just "hide" the latter because that's the name that's going to be in the datastore, and so that's the name that will make sense to queries!
What you want is a DerivedProperty. The procedure for writing one is outlined in that post - it's similar to what Alex describes, but by overriding get instead of get_value_for_datastore, you avoid issues with needing to write to the datastore to update it. My aetycoon library has it and other useful properties included.