Is there any way to have multiple response models in FastAPI/OpenAPI? - openapi

I am writing an app where I need to have two completely different set of response structures depending on logic.
Is there any way to handle this so that I can have two different response models serialized, validated and returned and reflect in OpenAPI JSON?
I am using pydantic to write models.

Yes this is possible. You can use Union for that in the response_model= parameter in your path decorator (I used the new python 3.10 style below). Here is a full example, this will work as is.
from typing import Union
from fastapi import FastAPI, Query
from pydantic import BaseModel
class responseA(BaseModel):
name: str
class responseB(BaseModel):
id: int
app = FastAPI()
#app.get("/", response_model=responseA|responseB )
def base(q: int|str = Query(None)):
if q and isinstance(q, str):
return responseA(name=q)
if q and isinstance(q, int):
return responseB(id=q)
raise HTTPException(status_code=400, detail="No q param provided")
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000, )
Result in your documentation:

Related

Is there a way to create a "Verify Element Text is Not" keyword?

I need to verify an element had been randomized from a fixed starting state. I already have a test step that verifies the fixed state is working that uses "Verify Element Text" is "inserttexthere".
So I need a way to verify that the text is not "inserttexthere" after I click the randomizing button.
Is there anyway to do this that wouldn't require too much programming knowledge? (I use katalon studio because I have limited tech knowledge)
or is there an if else statement I can use that would pass the step only if the text is different?
Background and other methods I do know of or tried:
I can create another verify text command and just accept it as an intended to fail step. However that's harder to be aware of, especially if the text doesnt change because the test step will pass and I have to remember thats bad.
The other commands that are available only cover if the element no longer has text or if the element is no longer visible/clickable. There is nothing that lets me verify an attribute as "!=" or "NOT"
This is how you need to create a custom keyword in Katalon: Click
Code:
class help_keyword_elemtnotPresent {
#Keyword
def isElemetNotPresent() {
WebUI.verifyElementNotPresent(findTestObject(‘someobject’, timeout, FailureHandling.OPTIONAL)
}
for : if/else
More example
Here's a short beginners' practical tutorial:
Create a keyword in Keywords (1) (right-click, new keyword).
Create a package (2) (right-click, new package) called examplePackage.
Create a new class called ExampleClass inside that package:
public class ExampleClass {
#Keyword
public static verifyElementTextIsNot(String text1, String text2){
assert text1 != text2
}
}
Example test case showing how you can call the above keyword (Keyword is Katalon's name for method):
import static com.kms.katalon.core.checkpoint.CheckpointFactory.findCheckpoint
import static com.kms.katalon.core.testcase.TestCaseFactory.findTestCase
import static com.kms.katalon.core.testdata.TestDataFactory.findTestData
import static com.kms.katalon.core.testobject.ObjectRepository.findTestObject
import static com.kms.katalon.core.testobject.ObjectRepository.findWindowsObject
import com.kms.katalon.core.checkpoint.Checkpoint as Checkpoint
import com.kms.katalon.core.cucumber.keyword.CucumberBuiltinKeywords as CucumberKW
import com.kms.katalon.core.mobile.keyword.MobileBuiltInKeywords as Mobile
import com.kms.katalon.core.model.FailureHandling as FailureHandling
import com.kms.katalon.core.testcase.TestCase as TestCase
import com.kms.katalon.core.testdata.TestData as TestData
import com.kms.katalon.core.testobject.TestObject as TestObject
import com.kms.katalon.core.webservice.keyword.WSBuiltInKeywords as WS
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
import com.kms.katalon.core.windows.keyword.WindowsBuiltinKeywords as Windows
import internal.GlobalVariable as GlobalVariable
import examplePackage.ExampleClass
String someText = "It is a rainy day"
String someOtherText = "It is a sunny day"
ExampleClass.verifyElementTextIsNot(someText, someOtherText)

constructing a mongo doc using pymodm from_document

I am trying to construct a pymodm document from a python dictionary using from_document api. I am receiving a error "ValueError: Unrecognized field name 'prim_key'"
Here is the sample code that I have written to make this happen with minimum code.
from pymodm import connect, EmbeddedMongoModel, MongoModel, fields
from pymodm.errors import ValidationError, ConfigurationError
from pymongo.write_concern import WriteConcern
import pprint
from datetime import datetime
class sample_doc(MongoModel):
prim_key = fields.CharField(primary_key=True)
another_field = fields.CharField()
class Meta:
write_concern = WriteConcern(j=True)
connection_alias = 'pymodm-tester'
connect("mongodb://localhost:27017/pymodm-tester", alias="pymodm-tester")
q = {'prim_key' : 'prim_val', "another_field" : "another_filed1" }
sample_doc.from_document(q).save()
In the docs:
document: A Python dictionary describing a MongoDB document. Keys
within the document must be named according to each model field’s
mongo_name attribute, rather than the field’s Python name.
It looks that, in order to instantiate a Model as you try, it needs to be specified the mongo_name Field. It would work for you something like:
class sample_doc(MongoModel):
prim_key = fields.CharField(primary_key=True, mongo_name="prim_key")
another_field = fields.CharField(mongo_name="another_field")
class Meta:
write_concern = WriteConcern(j=True)
connection_alias = 'pymodm-tester'

how to make a custom filter in flask admin

What am I doing wrong in this?? I am getting an exception thrown.
Exception: Invalid field : does not contains any columns.
I actually want to filter results from three different columns containing the cost of rooms.If any room satisfies a certain condition from the three rooms then it should appear on the list. That's why I want to make a custom filter.
Please help me. Thanks in advance.
from flask.ext.admin.babel import lazy_gettext
from flask.ext.admin.model import filters
class MyBaseFilter(filters.BaseFilter):
"""
Base SQLAlchemy filter.
"""
def __init__(self, column, name, options=None, data_type=None):
"""
Constructor.
:param column:
Model field
:param name:
Display name
:param options:
Fixed set of options
:param data_type:
Client data type
"""
super(MyBaseFilter, self).__init__(name, options, data_type)
self.column = column
class Views():
class HotelAdmin(ModelView):
class FilterCost(MyBaseFilter):
def apply(self, query, value):
return query.filter(self.column > value)
def operation(self):
return lazy_gettext('Cost')
column_labels = {'hotel_name':'Hotel Details'}
column_list = ('hotel_name','website')
column_searchable_list = ('city',)
column_filters = (FilterCost(Table.Hotel.deluxe_room,'Cost'),'state')
I did the following and it worked:
added:
from flask.ext.admin.contrib.sqla import filters
removed:
from flask.ext.admin.model import filters AND
class MyBaseFilter(filters.BaseFilter)
and then I inherited "filters.BaseSQLAFilter" in my filter class.
But still, How can I use "class MyBaseFilter(filters.BaseFilter)", It is still throwing an error

how to use composite data types (e.g. geomval) in SQLAlchemy?

I'm trying to replicate a nested raw PostGreSQL/PostGIS raster query using SQLAlchemy(0.8)/GeoAlchemy2(0.2.1) and can't figure how to access the components of a geomval data type. It's a compound data type that returns a 'geom' and a 'val'.
Here is the raw query that works:
SELECT (dap).val, (dap).geom
FROM (SELECT ST_DumpAsPolygons(rast) as dap FROM my_raster_table) thing
And the SQLAlchemy query I'm currently working with:
import geoalchemy2 as ga2
from sqlalchemy import *
from sqlalchemy.orm import sessionmaker
metadata = MetaData()
my_raster_table = Table('my_raster_table', metadata,
Column('rid', Integer),
Column('rast', ga2.Raster))
engine = create_engine(my_conn_str)
session = sessionmaker(engine)()
q = session.query(ga2.func.ST_DumpAsPolygons(my_raster_table.c.rast).label('dap'))
And then I'd like to access that in a subquery, something like this:
q2 = session.query(ga2.func.ST_Area(q.subquery().c.dap.geom))
But that syntax doesn't work, or I wouldn't be posting this question ;). Anyone have ideas? Thanks!
The solution ended up being fairly simple:
First, define a custom GeomvalType, inheriting geoalchemy2's CompositeType and specifying a typemap specific to geomval:
class GeomvalType(ga2.types.CompositeType):
typemap = {'geom':ga2.Geometry('MULTIPOLYGON'),'val':Float}
Next, use type_coerce to cast the ST_DumpAsPolygons result to the GeomvalType in the initial query:
q = session.query(type_coerce(ga2.func.ST_DumpAsPolygons(my_raster_table.c.rast), GeomvalType()).label('dap'))
Finally, access it (successfully!) from the subquery as I was trying to before:
q2 = session.query(ga2.func.ST_Area(q.subquery().c.dap.geom))

Django-Nonrel with Mongodb listfield

I am trying to implement manytomany field relation in django-nonrel on mongodb. It was suggessted at to:
Django-nonrel form field for ListField
Following the accepted answer
models.py
class MyClass(models.Model):
field = ListField(models.ForeignKey(AnotherClass))
i am not sure where the following goes, it has been tested in fields.py, widgets,py, models.py
class ModelListField(ListField):
def formfield(self, **kwargs):
return FormListField(**kwargs)
class ListFieldWidget(SelectMultiple):
pass
class FormListField(MultipleChoiceField):
"""
This is a custom form field that can display a ModelListField as a Multiple Select GUI element.
"""
widget = ListFieldWidget
def clean(self, value):
#TODO: clean your data in whatever way is correct in your case and return cleaned data instead of just the value
return value
admin.py
class MyClassAdmin(admin.ModelAdmin):
form = MyClassForm
def __init__(self, model, admin_site):
super(MyClassAdmin,self).__init__(model, admin_site)
admin.site.register(MyClass, MyClassAdmin)
The following Errors keep popping up:
If the middle custom class code is used in models.py
name 'SelectMultiple' is not defined
If custom class code is taken off models.py:
No form field implemented for <class 'djangotoolbox.fields.ListField'>
You just need to import SelectMultiple by the sound of it. You can put the code in any of those three files, fields.py would make sense.
Since it's pretty usual to have:
from django import forms
at the top of your file already, you probably just want to edit the code below to:
# you'll have to work out how to import the Mongo ListField for yourself :)
class ModelListField(ListField):
def formfield(self, **kwargs):
return FormListField(**kwargs)
class ListFieldWidget(forms.SelectMultiple):
pass
class FormListField(forms.MultipleChoiceField):
"""
This is a custom form field that can display a ModelListField as a Multiple Select GUI element.
"""
widget = ListFieldWidget
def clean(self, value):
#TODO: clean your data in whatever way is correct in your case and return cleaned data instead of just the value
return value
You probably also want to try and learn a bit more about how python works, how to import modules etc.