How to use `from_orm` if the pydantic model defines aliases? - orm

Though the pydantic's ORM mode is documented here, unfortunately there is no documentation for usage with aliases.
How to use from_orm if the pydantic model defines aliases?
It seems that the from_orm factory forgets about all non-aliased names if aliases exist. - See error message and the corresponding code below. Is that a bug or a feature?
The code snippet below fails unexpectedly with a validation error:
pydantic.error_wrappers.ValidationError: 1 validation error for SimpleModel
threeWordsId
field required (type=value_error.missing)
from sqlalchemy import Column, String
from sqlalchemy.ext.declarative import declarative_base
from pydantic import BaseModel, Field
Base = declarative_base()
class SimpleOrm(Base):
__tablename__ = 'simples'
three_words_id = Column(String, primary_key=True)
class SimpleModel(BaseModel):
three_words_id: str = Field(..., alias="threeWordsId")
class Config:
orm_mode=True
simple_orm = SimpleOrm(three_words_id='abc')
simple_oops = SimpleModel.from_orm(simple_orm)

Use allow_population_by_field_name = True in config.
Like
from sqlalchemy import Column, String
from sqlalchemy.ext.declarative import declarative_base
from pydantic import BaseModel, Field
Base = declarative_base()
class SimpleOrm(Base):
__tablename__ = 'simples'
three_words_id = Column(String, primary_key=True)
class SimpleModel(BaseModel):
three_words_id: str = Field(..., alias="threeWordsId")
class Config:
orm_mode = True
allow_population_by_field_name = True
# allow_population_by_alias = True # in case pydantic.version.VERSION < 1.0
simple_orm = SimpleOrm(three_words_id='abc')
simple_oops = SimpleModel.from_orm(simple_orm)
print(simple_oops.json()) # {"three_words_id": "abc"}
print(simple_oops.json(by_alias=True)) # {"threeWordsId": "abc"}
from fastapi import FastAPI
app = FastAPI()
#app.get("/model", response_model=SimpleModel)
def get_model():
# results in {"threeWordsId":"abc"}
return SimpleOrm(three_words_id='abc')

Related

Flask not storing data to database

Database not storing flask data models. Even though the database gets created.
Using postrges, the tables get created in bash view but not in pgAdmin. I have a simple app that needs to store data. Would appreciate help.'
Code uses SQLAlchemy. DO i need to use different library. I am using psycopg2 and sessions but havent imported sessions.
#!flask/bin/python
#!flask/bin/python
from os import linesep
from typing import Mapping, Type from flask
import Flask, jsonify
from flask import request
from slotscal import results
from flask_sqlalchemy
import SQLAlchemy
import time
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI']= 'postgresql+psycopg2://postgres:test123#localhost:5432/hqw' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db=SQLAlchemy(app)
db.metadata.clear()
#add parenrts
class Contracts(db.Model):
name=db.Column(db.String(100))
address=db.Column(db.String(42), unique=True, primary_key=True)
fileName=db.Column(db.Integer)
Functions= db.relationship('Function')
Variables= db.relationship('Variable')
StateVariables=db.relationship('StateVariable')
def __init__(self,address,fileName,id,StateVariables,name):
self.address=address
self.fileName=fileName
self.id=id
self.StateVariables=StateVariables
self.name=name
class Function(db.Model):
id=db.Column(db.String(42), db.ForeignKey('contracts.address'), primary_key=True)
name=db.Column(db.String)
lines=db.Column(db.Integer)
ReachingTime=db.Column(db.DateTime)
TrackingTime=db.Column(db.DateTime)
Arguments= db.relationship('Arguments')
def __init__(self,address,ReachingTime,id,TrackingTime,name,lines):
self.address=address
self.ReachingTime=ReachingTime
self.TrackingTime=TrackingTime
self.id=id
self.lines=lines
self.name=name
class Argument(db.Model):
id=db.Column(db.String(42), db.ForeignKey('function.id'), primary_key=True)
Type=db.Column(db.String)
Value=db.Column(db.String)
Name=db.Column(db.String)
def __init__(self,Name, id,Type,Value):
self.Name=Name
self.id=id
self.Type=Type
self.Value=Value
class Variable(db.Model):
VariableName=db.Column(db.String)
id=db.Column(db.String(42),db.ForeignKey('contracts.address'),primary_key=True)
Type=db.Column(db.String)
Value=db.Column(db.String)
StateVaruiable=db.Column(db.Boolean)
Mapping=db.Column(db.Boolean)
def __init__(self,address,Value,Type,id,StateVariables,name):
self.address=address
self.Type=Type
self.Value=Value
self.id=id
self.StateVariables=StateVariables
self.name=name
class m(db.Model):
id=db.Column(db.String(42),db.ForeignKey('variable.id'), primary_key=True)
Type=db.Column(db.String)
Source=db.Column(db.String)
def __init__(self,Type,Source,id):
self.Type=Type
self.id=id
self.Source=Source
class StateVariable(db.Model):
id=StateVariableType=db.Column(db.String)
StateVariableValue=db.Column(db.String)
id=db.Column(db.String(42),db.ForeignKey('contracts.address'),primary_key=True)
def __init__(self,id,StateVariableType,StateVariableValue):
self.StateVariableType=StateVariableType
self.StateVariableValue=StateVariableValue
self.id=id
class Key(db.Model):
id=db.Column(db.String(42),db.ForeignKey('m.id'), primary_key=True)
Value=db.Column(db.String)
Type=db.Column(db.String)
def __init__(self,Value,id,Type):
self.id=id
self.Value=Value
self.Type=Type
class Analysis(db.Model):
id=db.Column(db.String(42),db.ForeignKey('contracts.address'),primary_key=True)
FullTime=db.Column(db.DateTime)
StateVariables=db.Column(db.Integer)
def __init__(self,id,FullTime):
self.id=id
self.FullTime=FullTime
#app.route('/') def index():
return "Hello, World!" #app.route('/process', methods=['POST']) def process():
#print ('h')
header=request.json
#print ('g')
code=header['code']
f=open('code.sol','w')
f.write(code)
f.close()
path='./code.sol' #filename
subcon=header['name'] #name
add=header['address'] #address
contract=Contracts(subcon,add,path)
db.session.add(contract)
db.session.commit()
lst=results(path,subcon,add)
return jsonify({'task': lst})
if __name__ == '__main__':
app.run(debug=True)**
I'm not certain what you use the db.metadata.clear() for in your context.
Most likely, you don't see data in your DB, because there's nothing in your code to create the database relations. Standard solutions would include Alembic (Flask-Migrate package) or adding
with app.app_context():
db.create_all()
to your code.
The particulars are really up to you. Flask-Migrate is quite easy:
Install: pip install flask-migrate
Add to model:
from flask-migrate import Migrate
...
app = Flask(...)
...
#db init code
...
migrate = Migrate(app, db)
Run:
initialize: flask db init
migrate: flask db migrate -m "[YOUR MESSAGE]"
upgrade: flask db upgrade
Here's a good source in addition to the official docs: https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-iv-database

Odoo 14 overriding method

I'm trying to create an Odoo module which override Sales order confirm button. I followed the information I found, and I created the following code, but it doesn't work.
from odoo import models, fields, api
import logging
_logger = logging.getLogger(__name__)
class saleoverride(models.Model):
_name = 'saleoverride.saleoverride'
_description = 'saleoverride'
_inherit = 'sale.order'
name = fields.Char()
# value = fields.Integer()
# value2 = fields.Float(compute="_value_pc", store=True)
description = fields.Text()
transaction_ids = fields.Many2many('payment.transaction', 'saleoverride_transaction_rel', 'saleoverride_id', 'transaction_id',
string='Transactions', copy=False, readonly=True)
tag_ids = fields.Many2many('crm.tag', 'saleoverride_tag_rel', 'saleoverride_id', 'tag_id', string='Tags')
#api.model
def action_confirm(self):
res = super(SaleOrder, self).action_confirm()
_logger.info("saleoverride_action_confirm")
_logger.info(self)
return res
I tried to search the message in the log file, but can't find anything. Can someone help me?
Thanks!
The problem is that you are not extending the sale.order model, but creating a new one (saleoverride.saleoverride) based on sale.order.
Check odoo docs: Inheritance and extension
from odoo import models, fields, api
import logging
_logger = logging.getLogger(__name__)
class saleoverride(models.Model):
_description = 'saleoverride'
_inherit = 'sale.order'
name = fields.Char()
# value = fields.Integer()
# value2 = fields.Float(compute="_value_pc", store=True)
description = fields.Text()
transaction_ids = fields.Many2many('payment.transaction', 'saleoverride_transaction_rel', 'saleoverride_id', 'transaction_id',
string='Transactions', copy=False, readonly=True)
tag_ids = fields.Many2many('crm.tag', 'saleoverride_tag_rel', 'saleoverride_id', 'tag_id', string='Tags')
def action_confirm(self):
res = super(SaleOrder, self).action_confirm()
_logger.info("saleoverride_action_confirm")
_logger.info(self)
return res
Removing _name = 'saleoverride.saleoverride' from your class adds new features to sale.order.
Also remove the decorator since the original function doesn't have one.
When you want to override the code in addons, all you can do is just inheriting it. So, you can't define name while overriding the existing code.
Remove:
_name ='saleoverride.saleoverride'

How to add one more entry in selection field of an already defined odoo model using inheritance

Environment :- Odoo 9, Python 2.7
Module A
from openerp import models, fields, api, _, exceptions
class Games(models.Model):
_name = 'moduleA.games'
game = fields.Selection([
('cricket', 'Cricket'),
('hockey', 'Hockey'),
('golf', 'Golf')],
string='Game', default='cricket', required=True
)
Module B
from openerp import models, fields, api, _, exceptions
class ExtraGames(models.Model):
_inherit = 'moduleA.games'
def __init__(self, pool, cr):
res = super(ExtraGames,self)._columns # res = {}
super(ExtraGames,self)._columns['game'].selection.append(
('chess', 'Chess')
)
Now using that code, I want to add one more game Chess inside already defined games list but its not working. Actually I am getting empty dictionary ( {} ) as result of super(ExtraGames,self)._columns and because of that its giving KeyError 'game'.
How can we do it ?
You can use selection_add:
from openerp import fields, models
class ExtraGames(models.Model):
_inherit = 'moduleA.games'
game = fields.Selection(
selection_add=[('chess', 'Chess')],
)

Dynamically changing trait

Is it possible to have two classes
class SimulationDigitizer(HasTraits):
width = Int(1920)
height = Int(1080)
name = 'Simulation'
class FileDigitizer(HasTraits):
Filename = File
name = 'File'
and another class 'Digitizer' having an attribute (or trait) UserDigitizer whose edition dialog will propose a drop-down list with 'Simulation' and 'File' and, depending on the choice, the instance edition of either FileDigitizer or SimulationDigitizer and get the result in UserDigitizer ?
Thanks
Thanks Jonathan, you are right, the problem is to select the appropriate subcomponent among many possible.
I ended with the following code, I guess it can be improved in many ways. I am new both to Python and Traits.
# -*- coding: utf-8 -*-
from traits.api import HasTraits, Int, File, Enum, Instance
from traitsui.api import View, Item, Handler, HGroup, InstanceEditor
class UserComponent ( HasTraits ):
""" An empty class from which all user component classes are
derived.
"""
pass
class SimulationDigitizer(UserComponent):
width = Int(1920)
height = Int(1080)
nature = 'Simulation'
class FileDigitizer(UserComponent):
filename = File
nature = 'Reading a file'
UserDigitizers = [FileDigitizer, SimulationDigitizer]
class UserComponentHandler(Handler):
def __init__(self,_user_components_dict):
Handler.__init__(self)
self._user_components_dict = _user_components_dict
def object_user_component_nature_changed ( self, info ):
# Find new UserComponent class from string in user_component_nature
new_user_component = self._user_components_dict[info.object.user_component_nature]
# If different, change user_component value
if info.object.user_component is not new_user_component:
info.object.user_component = new_user_component
class Digitizer(HasTraits):
user_component_nature = Enum([x().nature for x in UserDigitizers])
_user_file_digitizer = FileDigitizer()
_user_simulation_digitizer = SimulationDigitizer()
# Dictionary with keys = nature and values = user digitizers
_user_digitizers_dict = {x.nature: x for x in [_user_file_digitizer,_user_simulation_digitizer]}
user_component = Enum(_user_file_digitizer,_user_simulation_digitizer)
view = View(HGroup(Item('user_component_nature',
label = 'Nature'),
Item('user_component',
show_label = False,
editor = InstanceEditor(label = 'Edit',
kind = 'modal'))),
handler = UserComponentHandler(_user_digitizers_dict))
d = Digitizer()
if __name__ == '__main__':
d.configure_traits()

OperationalError no such table in Flask with SQLAlchemy

run.py
if __name__ == '__main__':
config()
app.run()
main.py
import database
app = Flask(__name__)
def config():
app.config.from_object('config.DevConfig')
# Run SQLAlchemy _that uses app.config_ and add entities if in DEBUG mode
database.init_db(app)
import blueprints.auth
app.register_blueprint(blueprints.auth.auth)
database.py
db = None
def init_db(app):
global db
db = SQLAlchemy(app)
from models import User, Interest, Event
if app.config['DEBUG']:
print 'Recreating all db'
db.create_all() # I DO create everything
print 'Loading test data'
... (here I add some Users and etc. and everything works fine - tests pass)
models.py
from database import db
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120), unique=True)
...
blueprints/auth.py
from models import User
auth = Blueprint('auth', __name__)
#auth.route('/')
def index():
return str(User.query.get(1).interests)
And so I get
OperationalError: (OperationalError) no such table: user u'SELECT user.id AS user_id, user.username AS user_username, user.email AS user_email, user.passhash AS user_passhash, user.vk_page AS user_vk_page \nFROM user \nWHERE user.id = ?' (1,)
What am I doing wrong?
For anyone trying to use an in memory database:
from sqlalchemy import create_engine
from sqlalchemy.pool import StaticPool
engine = create_engine(
"sqlite://",
connect_args={"check_same_thread": False},
poolclass=StaticPool
)
There were few things I had to change to make everything work.
replace DATABASE_URI with SQLALCHEMY_DATABASE_URI parametr in config
replace :memory: sqlite address with /tmp/test.db
Now it works fine.