Tortoise ORM many to many field insert - python

I have an app build on Fastapi and tortoise orm. With the following models:
MODELS :
class Tratamiento(models.Model):
id = fields.UUIDField(pk=True)
nombre = fields.CharField(max_length=100)
descripcion = fields.CharField(max_length=300)
estado = fields.BooleanField()
costo = fields.IntField()
Tortoise.init_models(["db.models"], "models")
tratamiento_in = pydantic_model_creator(Tratamiento, name="TratamientoIn", exclude_readonly=True)
tratamiento_out = pydantic_model_creator(Tratamiento, name="TratamientoOut")
class Presupuesto(models.Model):
id = fields.UUIDField(pk=True)
paciente = fields.ForeignKeyField('models.Paciente', related_name="presupuesto_paciente", on_delete=fields.CASCADE)
tratamiento = fields.ManyToManyField('models.Tratamiento', related_name="presupuesto_tratamiento", on_delete=fields.CASCADE)
descripcion = fields.CharField(max_length=500)
total = fields.IntField()
fecha = fields.DateField()
Tortoise.init_models(["db.models"], "models")
presupuesto_in = pydantic_model_creator(Presupuesto, name="PresupuestoIn", exclude_readonly=True)
presupuesto_out = pydantic_model_creator(Presupuesto, name="PresupuestoOut")
I'm trying to post some values from vuejs, to this route:
ROUTE:
#router.post("/presupuestos/add", response_model=presupuesto_out)
async def post_presupuesto(presupuesto: presupuesto_in, tratamientos: List[TratamientosPydantic]):
for item in tratamientos:
presupuesto.total += item.costo
insert_result = await Presupuesto.create(**presupuesto.dict(exclude_unset=True))
for item in tratamientos:
tratamiento = await tratamiento_out.from_queryset_single(Tratamiento.get(id=item.tratamiento_id))
insert_related = await insert_result.tratamiento.add(*tratamiento)
And I'm getting the next Error on adding values to many to many field (create works fine), don't know how to solve it...Please help!
AttributeError: type object 'tuple' has no attribute '_meta'
ROUTE PARAM SCHEMA:
class TratamientosPydantic(BaseModel):
paciente_id: str
tratamiento_id: str
costo: int

Related

FastApi/Sqlalchemy "class is not mapped" error

I'm getting this error when I try to post and create a new registry using fastapi and sqlalchemy:
Class 'endpoints.resultados.ResultadoPruebaSerializer.InsertTResultadoRegla' is not mapped
Here is my code, thanks for your help.
Sqlalchemy Models
#as_declarative()
class Base:
def as_dict(self) -> dict:
return {c.key: getattr(self, c.key) for c in inspect(self).mapper.column_attrs}
class TResultadoRegla(Base):
__tablename__ = 'T_resultadoReglas'
idresultadoReglas = Column(Integer, primary_key=True)
idtareas = Column(ForeignKey('T_tareas.idtareas', ondelete='RESTRICT', onupdate='RESTRICT'), nullable=False, index=True)
idreglas = Column(ForeignKey('M_reglas.idreglas', ondelete='RESTRICT', onupdate='RESTRICT'), index=True)
fecCreacion = Column(Date)
resultado = Column(String(30))
M_regla = relationship('MRegla', backref="resultados")
T_tarea = relationship('TTarea')
Pydantic crud and schemas
class InsertTResultadoRegla(BaseModel):
idtareas: int
idreglas: int
fecCreacion: date
resultado: str
class Config:
orm_mode = True
def get_regla(db: Session, skip: int = 0, limit: int = 100):
return db.query(Regla).offset(skip).limit(limit).all()
def check_resultados(db: Session, user_resultados: Dict):
db_item = None
for resultado in user_resultados:
regla = get_regla_per_id(db, resultado["idreglas"])
regla = regla.as_dict()
if resultado["resultado"] >= int(regla["minimo"]) and resultado["resultado"] <= int(regla["maximo"]):
db_item = InsertTResultadoRegla(idtareas=1, idreglas=regla["idreglas"], fecCreacion=datetime.date.today(), resultado="CUMPLE")
db.add(db_item)
db.commit()
db.refresh(db_item)
else:
db_item = InsertTResultadoRegla(idtareas=1, idreglas=regla["idreglas"], fecCreacion=datetime.date.today(), resultado="NO CUMPLE")
db.add(db_item)
db.commit()
db.refresh(db_item)
return db_item
The issue is when you are trying to add it to the db, precisely,
db.add(db_item)
You have to add it like shown below:
db_item = InsertTResultadoRegla(idtareas=1, idreglas=regla["idreglas"], fecCreacion=datetime.date.today(), resultado="CUMPLE")
actual_db_item = models.TableName(** db_item.dict())
db.add(actual_db_item)
db.commit()
Before adding the data to the db you have to convert it into a proper "db_item". I hope this solves you issue.

TypeError: add_info() missing 1 required positional argument: 'writer' in Flask

I have passed on all the variables that are needed in add_info function. But still it show this error. (TypeError: add_info() missing 1 required positional argument: 'writer'). Can't figure out the problem here. I have included all the three files needed.
This is my Table file
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Type(db.Model):
__tablename__ = "types"
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String, nullable = False)
def add_info(self,name,genre,director,lead_actor,lead_actress,writer):
m = Movie(name = name, director = director, lead_actor = lead_actor, lead_actress= lead_actress, writer = writer, mov_id= self.id)
db.session.add(m)
db.session.commit()
d = Director(name = director, dir_id = self.id)
db.session.add(d)
db.session.commit()
w = Writer(name = writer, wri_id = self.id)
db.session.add(w)
db.session.commit()
This is my funtion inside flask app:
#app.route('/success', methods= ["POST"])
def success():
name = request.form.get("name")
genre = int(request.form.get("value"))
director = request.form.get("director")
actor = request.form.get("lead_actor")
actress = request.form.get("lead_actress")
writer = request.form.get("writer")
type = Type.add_info(name,genre,director,actor,actress,writer)
return render_template("addedinfo.html", message = "success")
if __name__ == "__main__":
with app.app_context():
app.run(debug=True)
here in your function gets name as self.
try to write your function call like this
type = Type().add_info(name,genre,director,actor,actress,writer)

Why do I get NameError for the column that is defined in SQLAlchemy model

I am developing REST APIs with Flask. One of the tables is modeled as follows:
class AudioSessionModel(db.Model):
__tablename__ = 'audio_session'
id = db.Column('audio_session_id', db.Integer, primary_key = True)
cs_id = db.Column(db.Integer)
session_id = db.Column(db.Integer)
facility = db.Column(db.Integer)
description = db.Column(db.String(400))
def __init__(self, cs_id, session_id, facility):
self.cs_id = cs_id
self.session_id = session_id
self.facility = facility
Business logics are defined in a DAO class:
class AudioSessionDAO(object):
def update(self, data):
audio = AudioSessionModel.query.filter(cs_id == data['CSID'], session_id == data['Session'])
audio.description = data['Desc']
db.session.commit()
return audio
This upate function is called in my endpoint for PUT request:
#api.route('/OperatorAccessment')
class OperatorAssessment(Resource):
#api.expect(assessment)
def put(self):
as_dao = AudioSessionDAO()
as_dao.update(request.json)
The model assessment looks like this:
assessment = api.model('Operator Assessment', {
'CSID': fields.Integer(required=True, description='Central Station ID'),
'Session': fields.Integer(required=True, description='Session ID'),
'Desc': fields.String(description='Description')
})
When I test the PUT request with the following json in request body:
{
"CSID": 1,
"Session": 1,
"Desc": "Siren"
}
I got the following error:
File "C:\Users\xxx_app\model\dao.py", line 63, in update
audio = AudioSessionModel.query.filter(cs_id == data['CSID'], session_id == data['Session'])
NameError: name 'cs_id' is not defined
Apparently, cs_id is defined. Why am I still getting this error?
You have to use the attributes of the class, i.e.
AudioSessionModel.query.filter(
AudioSessionModel.cs_id == data['CSID'],
AudioSessionModel.session_id == data['Session'])
Or filter_by with keyword arguments using just =:
AudioSessionModel.query.filter_by(
cs_id=data['CSID'],
session_id=data['Session'])
See What's the difference between filter and filter_by in SQLAlchemy?

sqlalchemy update didn't work

I use sqlalchemy to perform some queries and updates, but now I have trouble with UPDATE operation , when I change the model attribute pet_time(ins.role_time = plus_days(ins.role_time,30)) and use session to commit , sqlalchemy didn't perform the update operation.I don't know what's going on ,can anybody help?
Base = declarative_base()
class User(Base):
__tablename__ = 'user'
id = Column(Integer,primary_key=True)
nick_name = Column(String)
create_time = Column(DateTime, default=datetime.datetime.now)
role_time = Column(DateTime)
# the db connection info is correct
def getDbSession():
return Session()
def queryUserById(id):
sess = getDbSession()
instance = sess.query(User)\
.filter(User.id == id)\
.limit(1).first()
return instance
def increaseRoleTime(id,inc=1):
ins = queryUserById(id)
sess = getDbSession()
if(ins.role_time is None):
ins.role_time = datetime.datetime.now()
inc = inc * 30
# ins.role_time = func.ADDDATE(ins.role_time,inc)
ins.role_time = plus_days(ins.role_time,inc)
sess.commit()
return 1
# import timedelta from datetime to plus days
def plus_days(mydatetime,days):
return mydatetime + timedelta(days=days)
in the function increaseRoleTime,I change attribute role_time and commit,but still not working.

DoesNotExist: [Model] matching query does not exist at id (ObjectId)

I am trying to query a unique document using its ObjectId. However the error comes up:
DoesNotExist: Route matching query does not exist
When, upon passing this to my view as request, it prints out the corresponding ObjectId in ObjectId typeform. Therefore there shouldn't be a problem with the line route_test = Route.objects.get(id=_id).
I have the following code:
views.py
def update(request):
if request.method == "POST":
_id = request.POST.get('_id',ObjectId())
print(_id)
route_id = request.POST.get('route_id','')
geometry = request.POST.get('geometry', '')
properties = request.POST.get('properties','')
#r = Route.objects.get(route_id='LTFRB_PUJ2616') --> I cannot use this
#because it has 5 instances (Not Unique)
#print (r["id"],r["properties"])
test = Route.objects.get(id = ObjectId('587c4c3b203ada19e8e0ecf6'))
print (test["id"], test["properties"])
try:
route_test = Route.objects.get(id=_id)
print(route_test)
Route.objects.get(id=_id).update(set__geometry=geometry, set__properties=properties)
return HttpResponse("Success!")
except:
return HttpResponse("Error!")
ajax
var finishBtn = L.easyButton({
id:'finish',
states: [{
icon:"fa fa-check",
onClick: function(btn){
selectedFeature.editing.disable();
layer.closePopup();
var editedFeature = selectedFeature.toGeoJSON();
alert("Updating:" + editedFeature.route_id);
$.ajax({
url: "/update/",
data: {id:editedFeature.id,
route_id: JSON.stringify(editedFeature.route_id),
geometry: JSON.stringify(editedFeature.geometry),
properties: JSON.stringify(editedFeature.properties)
},
type: 'POST'
});
}
model.py
from __future__ import unicode_literals
from mongoengine import *
class Route(Document):
type = StringField(required=True)
route_id = StringField(required=True)
geometry = LineStringField()
properties = DictField()
meta = {'collection':'routes'}
What should be done? Even the line test = Route.objects.get(id = ObjectId('587c4c3b203ada19e8e0ecf6')) where I directly supplied the incoming _id has the same error...

Categories