is it possible to search null objects in mongoengine? - python

I'm trying to search null object with python NoneType but got the below error message:
raise ValidationError(message, errors=errors, field_name=field_name) mongoengine.errors.ValidationError: 'null' is not a valid ObjectId, it must be a 12-byte input or a 24-character hex string
Code for reproducing this issue:
class User(mongoengine.Document):
meta = {
"db_alias": 'core',
"collection": 'so_users_details'
}
user_name = mongoengine.StringField(required=True)
tag_details = mongoengine.ObjectIdField(null=True)
User(user_name='Sam').save() # This will create a new user with null value in tag_details
User.objects().filter(tag_details=None) # Getting the above error

I will recommend you to change the default value of tag_details to :
tag_details = mongoengine.ObjectIdField(blank=True)
so you can search for null objects like this:
User.objects(Q(tag_details__exists=False))

Related

with Pydantic, how can i create my own ValidationError reason

it seems impossible to set a regex constraint with a __root__ field like this one:
class Cars(BaseModel):
__root__: Dict[str, CarData]
so, i've resorted to doing it at the endpoint:
#app.post("/cars")
async def get_cars(cars: Cars = Body(...)):
x = cars.json()
y = json.loads(x)
keys = list(y.keys())
try:
if any([re.search(r'^\d+$', i) is None for i in keys]):
raise ValidationError
except ValidationError as ex:
return 'wrong type'
return 'works'
this works well in that i get wrong type returned if i dont use a digit in the request body.
but i'd like to return something similar to what pydantic returns but with a custom message:
{
"detail": [
{
"loc": [
"body",
"__root__",
],
"msg": "hey there, you can only use digits!",
"type": "type_error.???"
}
]
}
You can pass your own error string by using raise ValidationError("Wrong data type").
Hope it helps.
if it helps anyone, here is how i validated a dynamic field:
class Cars(BaseModel):
__root__: Dict[str, CarData]
#pydantic.root_validator(pre=True)
#classmethod
def car_id_is_digit(cls, fields):
car_ids = list(list(fields.values())[0].keys())
print(car_ids)
if any([bool(re.search(r'^\d+$', car_id)) == False for car_id in car_ids]):
raise ValueError("car_id must be a string that is a digit.")
else:
return fields
since a regular field validator requires a field name as an argument, i used the root_validator which validates all fields - and does not require that argument.
all this, because __root__ cannot be referenced in the regular field validator, it seems.
however, this means you can only have __root__ fields - and they will all be under the same validation rules...not sure how to added more fields with this.

Access nested property in pymongo

I'm trying to access "msgId", which is nested. However, it returns the property name instead of the value. What am I doing wrong?
Code:
def get_captain_message_id(game_id, user):
data = {
"gameId":game_id,
"messageIds":str(user.id)
}
return mongo.db['GameData'].find_one(data)['msgId']
That's because you're trying to access a property of the inner document as if it belonged to the outer one.
First you have to change your query data to match the document whose messageIds object contains the user.id property.
data = {
"gameId":game_id,
f"messageIds.{user.id}": {"$exists": True}
}
Then you can access msgId value with the appropriate indexing pipeline:
return mongo.db['GameData'].find_one(data)['messageIds'][str(user.id)]['msgId']

zeep.exceptions.Fault - Invalid Enum Value | Python Zeep Enum Attribute Error

def generate_waybill(shipper, consignee, services, profile):
success = True
request = {
"Shipper": shipper,
"Consignee": consignee,
"Services": services
}
client = Client(url)
res = client.service.GenerateWayBill(Request=request, Profile=profile)
print("RESPONSE GENERATE WAYBILL: \n\n", res, res.json())
if not res:
success = False
return res, success
While calling the generate_waybill function i get an execption from zeep >>> 'Invalid enum value 'ProductType.Dutiables'
In the services object it has a key named as ProductType and its Data Type ProductType [Enumerator] and the allowed values for this fields are ProductType.Docs, ProductType.Dutiables.
The services object
services = {
"ProductCode": shipping_options['bluedart']['product_code'],
"ProductType": shipping_options['bluedart']['product_type'],
"PieceCount": return_request_line_items.all().count(),
"ActualWeight": weight,
"CreditReferenceNo": reference_id,
"PickupDate": timezone.now() + timezone.timedelta(days=2),
"PickupTime": '1052',
"RegisterPickup": True,
"IsReversePickup": True
}
In the "ProductType": field I have passed hard coded string value as 'ProductType.Dutiables'
I have also tried creating a calss with Enum type like
from enum import Enum
class ProductType(Enum):
Dutiables = "Dutiables"
and used this as ProductType.Dutiables in the 'ProductType' field.
But nothing seems to work for me. Please help!
zeep.exceptions.Fault: The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:Request. The InnerException message was 'Invalid enum value 'ProductType.Dutiables' cannot be deserialized into type 'SAPI.Entities.Enums.AWBGeneration.ProductType'. Ensure that the necessary enum values are present and are marked with EnumMemberAttribute attribute if the type has DataContractAttribute attribute.'. Please see InnerException for more details.

sqlalchemy.exc.DataError: (psycopg2.errors.InvalidTextRepresentation) invalid input syntax for type integer: "None"

I am developing the Web Application in Flask built on top of Docker images. One image stores the Postgres Database. I am struggling with inserting None into the Integer column defined followingly:
release = db.Column(db.Integer, nullable=True)
Row initialization:
def __init__(self, name: str, env: str, mode: ExecutionMode, status: ExecutionStatus, date: datetime, user_id: int,
release_id: int):
self.execution_name = name
self.environment = env
self.execution_mode = mode
self.execution_status = status
self.execution_date = date
self.user_id = user_id
self.release = release_id
db.session.add(self)
db.session.commit()
Caller's method:
if request.method == "POST":
execution = Execution(name=data['result']['name'], env=Environment[data['result']['env']],
mode=ExecutionMode[data['result']['mode']],
status=ExecutionStatus[data['result']['status']],
date=datetime.datetime.strptime(data['result']['date'], "%Y-%m-%d %H:%M:%S.%f"),
user_id=current_user.id,
release_id=(data['result']['release'] if data['result'][
'release'] != "null" else sqlalchemy.null()))
Whenever I encounter the case, that the value of the Release is None, the following exception is triggered:
sqlalchemy.exc.DataError: (psycopg2.errors.InvalidTextRepresentation) invalid input syntax for type integer: "None"
Does anyone know, how to insert the None respectively NULL value into the database?
Thank you for any help.
The problem is actually on the front-end in the form that accepts the data. There was supposed to be the value of "null" in the select box; however, "None" was the value of the select. I missed that. It seems that the issue is solved.

Flask Pymongo Objectid link not working

I am tring to access a new document from a mongo database collection named games by the _id. But for example if I access localhost:5000/solutie/5ae71f3e8e442b090e4c313bit is giving me the error: ValueError: View function did not return a response so it doesn't go through the if and I think I should convert the value of the _id to another type but I don't know how.
This is my flask code:
#app.route('/solutie/<id>')
def solu(id):
games = mongo.db.games
game_user = games.find_one({'_id' : id})
if game_user:
return id
This is my mongo database collection named games:
{
"_id": {
"$oid": "5ae71f3e8e442b090e4c313b"
},
"sursa1": "nothingfornow",
"sursa2": "nothing4now",
"corectat": 0,
"player2": "test",
"player1": "test2",
"trimis1": 1,
"trimis2": 1
}
There's an object type converter you can use for URL routing:
#app.route('/solutie/<ObjectID:game_id>')
def solu(game_id):
games = mongo.db.games
game_user = games.find_one_or_404({'_id' : game_id})
return game_user
See:
https://flask-pymongo.readthedocs.io/en/latest/#flask_pymongo.BSONObjectIdConverter
Also, don't override id() because this is an in-built Python function.
The second parameter of the find() method is an object describing which fields to include in the result.
This parameter is optional and if omitted, all fields are included in the result.
# #app.route('/solutie/<int:id>') # or
#app.route('/solutie/<string:id>')
def solu(id):
myclient = pymongo.MongoClient("mongodb://localhost:27017/")
mydb = myclient["mydatabase"]
games = mydb["games"]
game_user = games.find({},{ "_id": id})
if game_user is not None:
return id
else:
return render_template("index.html")
Also you should use "else" condition.

Categories

Resources