I am currently build microservice using FastAPI + Strawberry GraphQL. I want to expose filters for the models with and/or condition. For example,
{
Student(where:{and[{AgeGt: 15},{PercentageLt: 75}]}) {
edges {
node {
Name
Age
Percentage
}
}
}
Is this possible? Any reference or example would greatly help.
In Strawberry you can use input types to define arguments for your queries
Here's an example what should help you with definining filters using strawberry:
from typing import Optional, List, TypeVar, Generic
from datetime import date
import strawberry
T = TypeVar("T")
#strawberry.input
class AbelFilter(Generic[T]):
eq: Optional[T] = None
gt: Optional[T] = None
lt: Optional[T] = None
#strawberry.input
class WhereFilter:
foo: Optional[AbelFilter[str]] = None
bar: Optional[AbelFilter[int]] = None
baz: Optional[AbelFilter[str]] = None
#strawberry.type
class Query:
#strawberry.field
def student(self, where: WhereFilter) -> str:
return str(where)
schema = strawberry.Schema(query=Query)
See this on the Strawberry Playground
Related
I want to assign a value of None to a field that fails to validate in Pydantic. The validator has a list of fields that it tries to validate.
To validate each field using data, fields_set, e = validate_model(model, raw_data) I need to know the model of each field.
I would like to have something like this for a validator.
Is there a way to discover the type of the field that is being validated???
#validator('*', pre=True)
def validate_name(cls, value: str):
model_of_field = ..... Some method to discover the field's Type(s)
data, fields_set, e = validate_model(model_of_field, value)
return value
Example that declares a separate validator method for each field
Note that the field is named "name1" on purpose to fail the validation and make it return None.
from typing import Any, Optional
from pydantic import BaseModel, validator, validate_model, ValidationError
class NameModel(BaseModel):
name: str
class AgeModel(BaseModel):
age: int
class MyModel(BaseModel):
name_data: Optional[NameModel]
age_data: Optional[AgeModel]
#classmethod
def pre_validate_any_field_and_return_none_on_validation_error(cls, model: Any, value: Any):
data, fields_set, e = validate_model(model, value)
if e:
return None
else:
return value
#validator('name_data', pre=True)
def validate_name(cls, value: str):
return cls.pre_validate_any_field_and_return_none_on_validation_error(NameModel, value)
#validator('age_data', pre=True)
def validate_age(cls, value: int):
return cls.pre_validate_any_field_and_return_none_on_validation_error(AgeModel, value)
my_data = {
'name_data': {'name1': 'Hello_a'},
'age_data': {'age': 120}
}
my_object: MyModel = MyModel(**my_data)
print(my_object)
You should use the __fields__ property as documented here: https://pydantic-docs.helpmanual.io/usage/models/#model-properties. It will give you something like this:
class Model(BaseModel):
value: int
#validator("value", pre=True)
def validate_value(cls, v):
print(cls.__fields__)
# Do your logic here
return v
Model(1)
This would print:
{'value': ModelField(name='value', type=int, required=True)}
I've started to write python, and I come into the self that you write inside of a class.
def start_simulator(self):
while True:
cloud = o3d.io.read_point_cloud(str(i) + '.ply')
self.vis.clear_geometries()
self.vis.add_geometry(cloud)
self.vis.poll_events()
self.vis.update_renderer()
if self.inputQueue.qsize() > 0:
input_str = self.inputQueue.get()
if input_str == "stop":
self.inputQueue.empty()
break
now I see myself writing a lot of self.
is there a way to use a destructor to self? Like in javascript:
const hero = {
name: 'Batman',
realName: 'Bruce Wayne'
};
const { name, realName } = hero; //something like this
Thanks for the help.
you can use dataclasses decorator in python its the closest data structure in python i know
from dataclasses import dataclass
#dataclass
class hero:
name: str
realName: str
you can check this website:
https://realpython.com/python-data-classes/
I am trying to receive the following JSON:
{
"va": "{1: 5, 2:1, 3:5}"
}
in my main.py I have the following:
from typing import Optional, Dict
from fastapi import FastAPI
from pydantic import BaseModel
class rq(BaseModel):
va: Dict[str, str]
app = FastAPI(debug=True)
#app.post("/hello")
async def create_item(rq: rq):
return 1
but I get
"msg": "value is not a valid dict",
"type": "type_error.dict"
how may I receive va as dict to iterate over it?
When you create a model, every field is actually a key-value pair, so with your example it expects something like this:
{
"va": {"some":"value"}
}
But what you send is
"va": str
So i don't know how you send the value but you are definitely sending a str instead of a Dict[str, str]
I'm currently working on a big code base and i need to send emails from any potential module, that conduct in Circular Dependencies issues in python
so i tried to use apps.get_model() from django.apps but when serializers are declared the models are not ready.
So i'm trying to create a factory function who build the class at runtime instead of launch time
from rest_framework.serializers import ModelSerializer
def make_serializer(model: str, fields: tuple, options = None, **nested_fields) -> ModelSerializer:
"""Generate a new serializer "On the fly", so the model does not have to be imported at launch time.
"""
model_object = apps.get_model(model)
input_fields = fields
if options is None:
options = {}
class Serializer(ModelSerializer):
class Meta:
model = model_object
fields = input_fields
def create(self, validated_data):
# we won't permit to create data from thoses serializers.
raise NotImplementedError
# configure nested serializers.
for nested_field in nested_fields.values():
for key, nested_serializer_class in nested_field.items():
serializer_instance = nested_serializer_class(**options.get(key, {}))
print(model, key, serializer_instance)
setattr(Serializer, key, serializer_instance)
return Serializer
my tests models looks like
class Band(Model):
name = Charfield(max_length=255)
class Influencer(Model):
entity = Charfield(max_length=255)
class Submission(Model):
influencer = ForeignKey(Influencer, ...)
class Campaign(Model):
band = ForeignKey('band.Band', ...)
submissions = ManyToMany(Submission)
and my testing function is:
def test():
serializer = make_serializer(
model='submission.Campaign',
fields=['pk', 'submissions', 'band'],
options={'submissions': {'many': True}},
nested_fields={
'submissions': make_serializer(
model='submission.Submission',
fields=('influencer',),
nested_fields={
'influencer': make_serializer('influencer.Influencer', ('entity',))
},
),
'band': make_serializer('band.Band', ('name',))
}
)
return serializer
instead of having my fields correly with test()(Campaign.objects.last()).data i only got "pks" and my serialiser looks like:
Serializer():
pk = IntegerField(label='ID', read_only=True)
submissions = PrimaryKeyRelatedField(many=True, queryset=Submission.objects.all())
band = PrimaryKeyRelatedField(allow_null=True, queryset=Band.objects.all(), required=False)
i except and output like:
{
"pk": 1,
"band": {
"name": "BobMarley",
},
"submissions": [
{
"influencer": {"entity": "The influencer's name"}
}
]
}
but i got a ReturnDict containing:
{
"pk": 1,
"band": 523,
"submissions": [6, 7, 8]
}
thanks for your time
well after many headcaches i've found out that i CAN'T setattr on a class after it's declaration, so i use a trick based on a dict
def make_serializer(model: str, fields: tuple, options = None, **nested_fields) -> ModelSerializer:
"""Generate a new serializer "On the fly", so the model does not have to be imported at launch time.
"""
name = f'Serializer_{model}'
model_object = apps.get_model(model)
input_fields = fields
if options is None:
options = {}
def create(self, validated_data):
# we won't permit to create data from thoses serializers.
raise NotImplementedError
class Meta:
model = model_object
fields = input_fields
attrs = {"Meta": Meta}
# configure nested serializers.
for key, nested_serializer_class in nested_fields.items():
attrs[key] = nested_serializer_class(**options.get(key, {}))
attrs['create'] = create
return type(ModelDictSerializer)(name, (ModelDictSerializer,), attrs)
the syntax is something like:
campaign_serializer = make_serializer(
model='submission.Campaign',
fields=['pk', 'submissions', 'band'],
options={'submissions': {'many': True}},
submissions=make_serializer(
model='submission.Submission',
fields=('influencer',),
influencer=make_serializer('influencer.Influencer', ('entity',))
),
band=make_serializer('band.Band', ('name',))
)
and it's working like a charm:
Serializer_submission.Campaign(<Campaign: Campaign object (9665)>):
pk = IntegerField(label='ID', read_only=True)
submissions = Serializer_submission.Submission(many=True):
influencer = Serializer_influencer.Influencer():
entity = CharField(allow_blank=True, max_length=255, required=False)
band = Serializer_band.Band():
name = CharField(max_length=255)
i hope this will help someone else
My project uses flask+mongoengine+marshmallow,When I used marshmallow to serialize the model, the returned value lacked field, and the missing field value was None.When using Django to serialize fields, the None value is still output
model
class Author(db.Document):
name = db.StringField()
gender = db.IntField()
books = db.ListField(db.ReferenceField('Book'))
def __repr__(self):
return '<Author(name={self.name!r})>'.format(self=self)
class Book(db.Document):
title = db.StringField()
serializers
class AuthorSchema(ModelSchema):
class Meta:
model = Author
class BookSchema(ModelSchema):
class Meta:
model = Book
author_schema = AuthorSchema()
When I do this:
author = Author(name="test1")
>>> author.save()
<Author(name='test1')>
>>> author_schema.dump(author)
MarshalResult(data={'id': '5c80a029fe985e42fb4e6299', 'name': 'test1'}, errors={})
>>>
not return the books field
I hope to return
{
"name":"test1",
"books": None
}
what should I do?
When I looked at the source code of the marshmallow-mongoengine library, I found the solution model_skip_values=() in the tests file.
def test_disable_skip_none_field(self):
class Doc(me.Document):
field_empty = me.StringField()
list_empty = me.ListField(me.StringField())
class DocSchema(ModelSchema):
class Meta:
model = Doc
model_skip_values = ()
doc = Doc()
data, errors = DocSchema().dump(doc)
assert not errors
assert data == {'field_empty': None, 'list_empty': []}