How to rename keys in response from database by pydantic schema - FastAPI - python-3.x

I have a model from my database in models.py:
class Something(Base):
__tablename__ = "something"
DATE = Column(Date, primary_key=True, index=True )
a = Column(String, primary_key=True, index=True)
b = Column(Integer, primary_key=True, index=True)
c = Column(Float, index=True)
d = Column(Integer, index=True)
e = Column(Integer, index=True)
f = Column(Float, index=True)
g = Column(Float, index=True)
h = Column(Integer, index=True)
and a pydantic model in schema.py:
class Something(BaseModel):
DATE: date
a: str
b: int
c: float = None
d: int = None
e: int = None
f: float = None
g: float = None
h: int = None
class Config:
orm_mode = True
I get data from the database which go through the ORM and in app.get() I declare the response model equal to List[schema.Something], but I want to change the names from the database a, b, c, d to more beautiful names.
Is there a solution like mapping names in NestJS?

Try to use aliases, this is what option allow_population_by_field_name allows to do, for example:
class Person(BaseModel):
first_name: str = Field(..., alias='first')
last_name: str = Field(..., alias='second')
class Config:
allow_population_by_field_name = True
p = Person(**{'first': 'John', 'second': 'White'})
print(p.__dict__)
# {'first_name': 'John', 'last_name': 'White'}

Related

Index a relationship in SQLAlchemy and Almbic

I have two tables like bellow:
Table 1:
class Table1(Base):
__tablename__ = "table1"
id = Column(UUID, primary_key=True)
created_at = Column(DateTime(True), nullable=False, server_default=func.now())
status_id = Column(ForeignKey("lookups.id"), index=True)
status = relationship(
"Lookup",
primaryjoin="Tables.status_id == Lookup.id",
backref="table1_statuses",
)
Table 2:
class Lookup(Base):
__tablename__ = "lookups"
id = Column(UUID, primary_key=True)
type = Column(String(64))
value = Column(String(256))
maximum = Column(Float(53), server_default="0")
sys_period = Column(TSTZRANGE, nullable=False, index=True)
HOW CAN I do a full text search on Table1 and find the status value. My query will look like this:
model = Table1
# search_term is `value` in the Lookup table
result = (session.query(model)
.filter(model.__ts_vector__.match(search_term)).all)

SQLalchemy query not updating relationship columns in put api

I have a model.py with a class Histogram and a table histogram_axes -
histograms_axes = Table(
"histograms_axes",
_ORMBase.metadata,
Column("histogram_id", ForeignKey("histograms.id"), primary_key=True),
Column("axis_id", ForeignKey("axes.id"), primary_key=True),
)
class Histogram(Base):
block = Column(Integer)
num = Column(Integer)
id = Column(Integer, ForeignKey("s.id"))
axes = relationship(
"Axis", secondary=histograms_axes, backref="histograms", order_by="asc(Axis.name)"
)
I have written a put API in FastAPI to update the rows based on id, but it only updates the columns not the relationship in Histogram class.
#router.put("/histograms")
def put_histograms(response: HistogramSchema, id: int, axes: List[int], db: Session = Depends(get_db)):
histogram = db.query(Histogram).filter(Histogram.id == id)
if not histogram.first():
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Histogram id {id} is not found!")
histogram.axes = db.query(Axis).filter(Axis.id.in_(axes)).all()
response = response.dict(exclude_unset=True)
histogram.update(response)
db.commit()
return histogram.one_or_none()
How can I update the relationship table as well.

Django - 'Merging' or Sorting similar objects from a queryset

Good day, I have a django model that represents users (node) that have a relation (edge) with other users. User A is a friend of User B and User A interacted with User B .
class Node(BaseInfo):
firstname = models.CharField(max_length=200,blank = True, null=True)
lastname = models.CharField(max_length=200,blank = True,null=True)
dob = models.DateField(blank=True,null=True)
username = models.CharField(max_length=200, blank=True, null=True)
picture_url = models.CharField(max_length=200,blank = True,null =True)
phone_number = models.CharField(max_length=200,blank = True, null=True)
email = models.CharField(max_length=200,blank = True, null=True)
gender= models.CharField(max_length=200,blank = True, null=True)
uid = models.CharField(max_length=200,blank=True,null=True)
url = models.CharField(max_length=2000,blank=True,null=True)
edges = models.ManyToManyField('self', through='Edge',blank = True)
task = models.ManyToManyField('Task',blank = True)
location = models.ManyToManyField('Location',blank = True)
case = models.ManyToManyField('case',blank = True)
class Edge(BaseInfo):
source = models.ForeignKey('Node', on_delete=models.CASCADE,related_name="is_source")
target = models.ForeignKey('Node', on_delete=models.CASCADE,related_name="is_target")
class Meta:
constraints = [
models.UniqueConstraint(fields=['source','target','label'], name="unique_edge"),
]
def __str__(self):
return '%s' % (self.label)
At this point i query the relations with:
result = Edge.objects.filter(source = User A);
The result will contain a query set with
[Edge(User A , User B , "Friends"),[Edge(User A, User B , "Interacted")]
I want to show the relations (Grouped By ? ) of User A in a template
So it says , Profile A is a friend and has interacted with B. Rather then having to iterate over the queryset and having 2 lines in my template :User A is friends with B , User A interacties with user B.
I already looked in aggregation functions of Django but cant get any further.
Thanks in advance for youre guidance.

SQLAlchemy Order joined table by field in another joined table

My project requires that Orders are split into their individual lines which can be displayed in their own views I want these views to order the lines by eta which is a value in the Order table.
I have 3 tables with a 1>1 join on tables 1&2 and a many>many join on tables 2 and 3 defined by table 4 as follows:
class Order(db.Model):
id = db.Column(db.Integer, primary_key=True)
eta = db.Column(db.DateTime())
order_lines = db.relationship('Line', backref='order', order_by=lambda: Line.id)
def __repr__(self):
return '<Order No. {}>'.format(self.increment_id)
class Line(db.Model):
id = db.Column(db.Integer, primary_key=True)
line_name = db.Column(db.String())
order_id = db.Column(db.Integer, db.ForeignKey('order.id'))
product_id = db.Column(db.String, db.ForeignKey('product.product_id'))
def __repr__(self):
return '<Line SKU: {}>'.format(self.line_sku)
class Line_view(db.Model):
id = db.Column(db.Integer, primary_key=True)
view_name = db.Column(db.String())
view_lines = relationship('Line',
secondary='line_view_join',
backref='views',
lazy='dynamic',
order_by= ***???*** ) #ordery by eta on Order table
def __repr__(self):
return '<View: {}>'.format(self.view_name)
class Line_view_join(db.Model):
__tablename__ = 'line_view_join'
id = db.Column(db.Integer(), primary_key=True)
line_id = db.Column(db.Integer(), db.ForeignKey('line.id', ondelete='CASCADE'))
view_id = db.Column(db.Integer(), db.ForeignKey('line_view.id', ondelete='CASCADE'))
I am trying to work out how to query table 3, Line_View and have the joined Lines ordered by the eta of Order table.
Such that when querying:
chosen_view = Line_view.query.filter_by(id = 1).one()
chosen_view.view_lines are ordered by Order.eta
I have Tried
class Line_view(db.Model):
id = db.Column(db.Integer, primary_key=True)
view_name = db.Column(db.String())
view_lines = relationship('Line',
secondary='line_view_join',
backref='views',
lazy='dynamic',
**order_by=lambda: asc(Line.order.eta))**
def __repr__(self):
return '<View: {}>'.format(self.view_name)
But this results in the error:
AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with Line.order has an attribute 'eta'
Do you need to store the Line_views in the database? If not, you can query the Lines sorted by the eta attribute of the related order. Below, I create two orders with one line each, and then query the lines sorted by the eta attribute of their order:
eta = datetime(2019,10,10)
o = Order(eta = eta)
l = Line(order=o, line_name="sample")
db.session.add(o)
db.session.add(l)
eta = datetime(2019,11,11)
o1 = Order(eta = eta)
l1 = Line(order=o1, line_name="sample1")
db.session.add(o1)
db.session.add(l1)
db.session.commit()
lines = Line.query.join(Order).order_by(Order.eta)

how can I make an insert of a select field with sqlalchemy?

I have a form where I have a text field and a selection field and the question I have is how can I insert the bd in the selection field, this field in the table is an external key and what I need is to insert the value of the selection field.
I would greatly appreciate your help.
#detalle_grupo_estadisticas.route("/show/<id>", methods = ['GET', 'POST'])
def show(id):
title = 'Grupo estadisticas'
page = 1
per_page = 3
CamposGrupo = forms.Fields_Detalle_Grupo_Estadisticas(request.form)
grup_list = GrupoEstadisticas.query.all()
if request.method == 'POST' and CamposGrupo.validate():
grupo_edit = DetalleGrupoEstadisticas.query.filter_by(id_detalle_grupo_estadisticas=id).first()
grupo_edit.nombre = CamposGrupo.Nombre.Data
grupo_edit.id_grupoEstadisticas = CamposGrupo.GrupoEstadistica.Value
db.session.add(grupo_edit)
db.session.commit()
return redirect(url_for('detalle_grupo_estadisticas.index'))
grupo = DetalleGrupoEstadisticas.query.filter_by(id_detalle_grupo_estadisticas=id).first()
CamposGrupo.Nombre.data = grupo.nombre
CamposGrupo.GrupoEstadistica.choices=[(g.id_grupoEstadisticas,g.nombre) for g in grup_list]
return render_template('/detalle_grupo_estadisticas/show.html', title=title, CamposGrupo = CamposGrupo, grupo = grupo)
What I want to insert is the value of the field selection field
these are the models
class DetalleGrupoEstadisticas(db.Model):
__tablename__ = 'detalle_grupo_estadisticas'
id_detalle_grupo_estadisticas = db.Column(db.Integer, primary_key=True)
nombre = db.Column(db.String(80), nullable=False)
id_grupoEstadisticas = db.Column(db.Integer, db.ForeignKey('grupo_estadisticas.id_grupoEstadisticas'))
grupoestadistica = db.relationship('GrupoEstadisticas', back_populates='detallesgrupo', lazy=True)
class GrupoEstadisticas(db.Model):
__tablename__ = 'grupo_estadisticas'
id_grupoEstadisticas = db.Column(db.Integer, primary_key=True)
nombre = db.Column(db.String(80), nullable=False)
descripcion = db.Column(db.String(200), nullable=False)
estadisticas= db.relationship('Estadisticas', back_populates='grupoestadisticas', lazy=True)
detallesgrupo= db.relationship('DetalleGrupoEstadisticas', back_populates='grupoestadistica', lazy=True)
This is how I was able to solve the problem.
view
#detalle_grupo_estadisticas.route("/show/<id>", methods = ['GET', 'POST'])
def show(id):
title = 'Grupo estadisticas'
page = 1
per_page = 3
CamposGrupo = forms.Fields_Detalle_Grupo_Estadisticas(request.form)
grup_list = GrupoEstadisticas.query.all()
if request.method == 'POST' and CamposGrupo.validate():
grupo_edit = DetalleGrupoEstadisticas.query.filter_by(id_detalle_grupo_estadisticas=id).first()
grupo_edit.nombre = CamposGrupo.Nombre.data
grupo_edit.grupoestadistica = CamposGrupo.GrupoEstadistica.data
#this is where I had the error that I was inserting in id_grupoStadisticas and it had to be with the variable of the relationship
db.session.add(grupo_edit)
db.session.commit()
return redirect(url_for('detalle_grupo_estadisticas.index'))
grupo = DetalleGrupoEstadisticas.query.filter_by(id_detalle_grupo_estadisticas=id).first()
CamposGrupo.Nombre.data = grupo.nombre
CamposGrupo.GrupoEstadistica.choices=[(g.id_grupoEstadisticas,g.nombre) for g in grup_list]
return render_template('/detalle_grupo_estadisticas/show.html', title=title, CamposGrupo = CamposGrupo, grupo = grupo)
form
class Fields_Detalle_Grupo_Estadisticas(Form):
Nombre = StringField('Grupo', validators=[InputRequired(), Length(min=2, max=30, message = 'Mayor a 2 caracteres y menor a 30')])
GrupoEstadistica = QuerySelectField('Grupo Estadistica',query_factory=lambda: GrupoEstadisticas.query,
get_pk=lambda g: g.id_grupoEstadisticas,
get_label=lambda g: g.nombre)

Resources