Mongoengine Document.update() example - mongoengine

Assuming that Venue is:
from mongoengine import *
from mongoengine_extras.fields import AutoSlugField
class Venue(Document):
name = StringField(required=True)
venue_slug = AutoSlugField()
I want to update all my venue_slug fields based on the name. I try:
for v in Venue.objects():
v(venue_slug = str(v.name)).update()
But I get:
v(venue_slug = str(v.name)).update()
TypeError: Error when calling the metaclass bases
'Venue' object is not callable
Is my update function correct? If you are not familiar with AutoSlugField() could you write an example for a StringField() update?

Your code incorrect. Try:
for v in Venue.objects():
v.update(set__venue_slug=str(v.name))
See documentation: http://docs.mongoengine.org/guide/querying.html#atomic-updates.

Related

Peewee Model, dicts()

I'm debugging existing code. I'm trying to find out the intention of the obviously wrong access to .dicts of a peewee Model in the warning statement in MyDbBackend.store and how I could correct that.
I guess that the warning message should add more detailed output to the model which could not be saved. However, the .dicts attribute exists in orm.BaseQuery class, only.
The output message is currently not very helpful. I want to provide an improved warning message given that the i.save fails. With "improved" i mean to provide some meta informations about the record which failed to be saved.
So, how can i obtain the BaseQuery from the model and what would .dicts output, then? Would that information be useful in the context of the warning message?
import peewee as orm
database = orm.Proxy()
class ModelBase(orm.Model):
class Meta:
database = database
class MyModel(ModelBase):
dtfield = orm.DateTimeField(null=True)
intfield = orm.IntegerField(null=True)
floatfield = orm.FloatField(null=True)
class MyDbBackend:
def __init__(self, database):
self.db = database
self.records = [] # Holds objects derived from ModelBase
[...]
def store(self):
with self.db.atomic():
for i in self.records:
try:
i.save()
except Exception as e:
logger.warning("could not save record: {}".format(i.dicts()))
raise e
self.clear()
->
logger.warning("could not save record: {}".format(i.dicts()))
AttributeError: 'MyModel' object has no attribute 'dicts'
I guess that the original code was meant to make use of playhouse.shortcuts.model_to_dict.
This is the only idea I have why the original code uses i.dict().
Perhaps some misunderstanding.
import peewee as orm
from playhouse.shortcuts import model_to_dict
[...]
logger.warning(f"Model dict: {model_to_dict(i, recurse = True, max_depth = 2)}")
[...]

Load InboundReferencedBeans for Insight add-on in JIRA

I'm working on Insight automation groovy script, but I got stuck in one point.
I have Insight object called "Agreement".
This object has Inbound References called "Services".
Each Agreement can have any number of Services. I need to get list of all Services for any Agreement. I found the method findObjectInboundReferencedBeans(int id) in the docs, but apparently, I'm missing something as when I run the script, I get an error in log:
AutomationRuleGroovyScriptAction, Unexpected error: No signature of method: com.riadalabs.jira.plugins.insight.channel.external.api.facade.impl.ObjectFacadeImpl.findObjectInboundReferencedBeans() is applicable for argument types: (java.lang.Integer) values: [15748]
Here is my script:
import com.atlassian.jira.component.ComponentAccessor;
import com.riadalabs.jira.plugins.insight.services.model.ObjectAttributeBean;
import com.riadalabs.jira.plugins.insight.services.model.ObjectBean;
import com.riadalabs.jira.plugins.insight.services.model.MutableObjectAttributeBean;
import com.riadalabs.jira.plugins.insight.services.model.MutableObjectBean;
Class objectFacadeClass = ComponentAccessor.getPluginAccessor().getClassLoader().findClass("com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectFacade")
def objectFacade = ComponentAccessor.getOSGiComponentInstanceOfType(objectFacadeClass)
// def agreementStatusId = 2641
// def serviceStatusId = 2180
// def activeStatus = 1
// def stoppedStatus = 6
def attributeRef = "Status smlouvy"
def objectKey = object.getObjectKey();
def insightObject = objectFacade.loadObjectBean(objectKey)
int objectId = insightObject.getId()
----------------------------------
**// Here is the line I need help with
def inRef = objectFacade.findObjectInboundReferencedBeans(objectId)**
----------------------------------
def objectAttribute = objectFacade.loadObjectAttributeBean(objectId, attributeRef)
def objectAttributeValue = objectAttribute.getObjectAttributeValueBeans()[0].getValue()
log.warn(objectKey.toString())
log.warn(insightObject.toString())
log.warn(inRef)
I use this script also to get attribute value from Agreement object, which works fine.
I guess the problem is that I call the method on wrong object, but when I try to call in dirrectly on "insightObject" , I got the same error.
Thank you!
As answered on the Atlassian Community Page.
The method was removed with the release of Insight 5.1, see the upgrade notes here.
However, you can just use this to solve your issue:
def inRef = iqlFacade.findObjects(/object HAVING outboundReferences(Key = ${objectKey})/)

Why doesn't Peewee fill in my object's id?

I am trying to build a database driver for Peewee and i'm having trouble getting the save() method to fill in the primary key/id for objects. Here's some sample code:
from datetime import date
from peewee import BooleanField
from peewee import CharField
from peewee import DateField
from peewee import ForeignKeyField
from peewee import IntegerField
from peewee import Model
from SQLRelay import PySQLRDB
from sqlrelay_ext import SQLRelayDatabase
DB = SQLRelayDatabase('test2', host='<host>', user='<un>', password='<pwd>')
class BaseModel(Model):
class Meta:
database = DB
class Person(BaseModel):
name = CharField()
birthday = DateField()
is_relative = BooleanField()
class Pet(BaseModel):
owner = ForeignKeyField(Person, backref='pets')
name = CharField()
animal_type = CharField()
DB.connect()
Person.create_table(safe=False)
Pet.create_table(safe=False)
uncle_bob = Person(name='Bob', birthday=date(1960, 1, 15), is_relative=True)
uncle_bob.save() # bob is now stored in the database
print('Uncle Bob id: {}'.format(uncle_bob.id))
print('Uncle Bob _pk: {}'.format(uncle_bob._pk))
Both uncle_bob.id and uncle_bob._pk are None after .save(). From digging into the peewee.py code, it seems that the _WriteQuery.execute() method is supposed to set the _pk attribute, but that isn't happening. My best guess is that the cursor implementation isn't acting properly. Does anyone have more insight than this that can maybe help me track down this problem?
Thanks!
Edit to answer:
For SQL Server, the following code allows you to return the last inserted id:
def last_insert_id(self, cursor, query_type=None):
try:
cursor.execute('SELECT SCOPE_IDENTITY()')
result = cursor.fetchone()
return result[0]
except (IndexError, KeyError, TypeError):
pass
In your SQLRelayDatabase implementation, you will probably need to correctly implement the last_insert_id() method. For python db-api 2.0 drivers, this typically looks like cursor.lastrowid.
The default implementation is:
def last_insert_id(self, cursor, query_type=None):
return cursor.lastrowid
Where cursor is the cursor object used to execute the insert query.
Databases like Postgresql do not implement this -- instead you execute an INSERT...RETURNING query, so the Postgres implementation is a bit different. The postgres implementation ensures that your insert query includes a RETURNING clause, and then grabs the id returned.
Depending on your DB and the underlying DB-driver, you'll need to pull that last insert id out somehow. Peewee should handle the rest assuming last_insert_id() is implemented.

Serialise a WKB into WKT or geojson in flask marshmallow/marshmallow-sqlalchemy

I've got a bunch of GIS tables in my model that I created in flaskSQLAlchemy. Each of these models has a 'geom' field which is a WKB object.
Which need to be JSON serialized into WKT or geojson, So that The API GET call would work.
I tried to use geoalchemy2 functions, but I'm stuck.
I use a flask marshmallow/marshmallow-sqlalchemy combo, and I tried something like the following, with no luck.
from geoalchemy2 import functions
from marshmallow import fields
class WKTSerializationField(fields.Field):
def _serialize(self, value, attr, obj):
if value is None:
return value
else:
if type(value).__name__ == 'WKBElement':
return functions.ST_AsEWKT(value)
else:
return None
class GISModelTableSchema(ma.ModelSchema):
class Meta:
model = GISModelTable
geom = WKTSerializationField(attribute="geom")
Please provide a code example if you can, how to serialize/deserialize a field in marshmallow alchemy. Or any answer is welcomed at this point.
Try to use marshmallow-sqlalchemy 'fields.Method()' and in the method use another method 'to_shape' from geoalchemy2.shape package. This will help you with serialization issue.
#!schemas.py
from marshmallow import fields
from marshmallow_sqlalchemy import ModelSchema
from geoalchemy2.shape import to_shape
from .models import YourModel
class YourModelSchema(ModelSchema):
your_geom_field = fields.Method("geom_to_dict")
#staticmethod
def geom_to_dict(obj):
point = to_shape(obj.your_geom_field)
return {
lat: point.y,
lon: point.x
}
class Meta:
model = YourModel
exclude = ("your_geom_field")
this migh help you with serialization, for desirialization you may read more detailed in geoalchemy2 api reference
Try to code all required fields by yourself, you may get more specific serialization in a form you want

Mongoengine Link to Existing Collection

I'm working with Flask/Mongoengine-MongoDB for my latest web application.
I'm familiar with Pymongo, but I'm new to object-document mappers like Mongoengine.
I have a database and collection set up already, and I basically just want to query it and return the corresponding object. Here's a look at my models.py...
from app import db
# ----------------------------------------
# Taking steps towards a working backend.
# ----------------------------------------
class Property(db.Document):
# Document variables.
total_annual_rates = db.IntField()
land_value = db.IntField()
land_area = db.IntField()
assessment_number = db.StringField(max_length=255, required=True)
address = db.StringField(max_length=255, required=True)
current_capital_value = db.IntField
valuation_as_at_date = db.StringField(max_length=255, required=True)
legal_description = db.StringField(max_length=255, required=True)
capital_value = db.IntField()
annual_value = db.StringField(max_length=255, required=True)
certificate_of_title_number = db.StringField(max_length=255, required=True)
def __repr__(self):
return address
def get_property_from_db(self, query_string):
if not query_string:
raise ValueError()
# Ultra-simple search for the moment.
properties_found = Property.objects(address=query_string)
return properties_found[0]
The error I get is as follows: IndexError: no such item for Cursor instance
This makes complete sense, since the object isn't pointing at any collection. Despite trolling through the docs for a while, I still have no idea how to do this.
Do any of you know how I could appropriately link up my Property class to my already extant database and collection?
The way to link a class to an existing collection can be accomplished as such, using meta:
class Person(db.DynamicDocument):
# Meta variables.
meta = {
'collection': 'properties'
}
# Document variables.
name = db.StringField()
age = db.IntField()
Then, when using the class object, one can actually make use of this functionality as might be expected with MongoEngine:
desired_documents = Person.objects(name="John Smith")
john = desired_documents[0]
Or something similar :) Hope this helps!
I was googling this same question and i noticed the answer has changed since the previous answer:
According to the latest Mongoengine guide:
If you need to change the name of the collection (e.g. to use MongoEngine with an existing
database), then create a class dictionary attribute called meta on your document, and set collection to the
name of the collection that you want your document class to use:
class Page(Document):
meta = {'collection': 'cmsPage'}
The code on the grey did the trick and i could use my data instantly.

Resources