Closed Nicialy closed 9 months ago
Hi! Could you please provide on-module example of this behavior which I can run locally to check, what is happening?
Example: main.py.txt
@roman-right
from motor.motor_asyncio import AsyncIOMotorClient
from typing import Optional
from pydantic import Field
import asyncio
from beanie import init_beanie,Document,BackLink,Link
from beanie.odm.fields import PydanticObjectId
class Country(Document):
id: PydanticObjectId = Field(default_factory=PydanticObjectId)
cities: list[Link["City"]] = Field(default_factory=list)
class City(Document):
id: PydanticObjectId = Field(default_factory=PydanticObjectId)
country: Optional[BackLink["Country"]] = Field(default=None, original_field="cities", exclude=True)
__beanie_models__=[Country,City]
async def fillSomeData():
session:AsyncIOMotorClient = AsyncIOMotorClient("mongodb://localhost:27017")
await init_beanie(database=session.example, document_models=__beanie_models__)
cityOk = City()
await cityOk.create()
# cityOk.country = <beanie.odm.fields.BackLink object at > expected None
country = Country()
country.cities.append(cityOk)
await country.save()
cityErr = City()
await cityErr.create()
# cityErr.country = <beanie.odm.fields.BackLink object at > expected None
id = cityOk.id
id1 = cityErr.id
city = await City.find_one(City.id==id, fetch_links=True)
city1 = await City.find_one(City.id==id1, fetch_links=True)
print(city.country)# country = Country(id=ObjectId('6548dd0f4 ...
print(city1.country)# country = <beanie.odm.fields.BackLink object at > expected None
if __name__ == "__main__":
asyncio.run(fillSomeData())
they forgot about us...
Hi @Nicialy and @Nasochec , Sorry for the delay.
I investigated this problem. It is a bit of trade off. BackLink is a virtual field. It means Beanie never stores this field to the database, it only populates it on finds with fetch_links=True
. It means that if fetch_links != True
Beanie has no information about if such relations exist or not. But Links (and BackLinks) can be fetched directly using fetch
method. But to be able to run this method this field should be an object of BackLink. And, as Beanie on the filed level doesn't know if there is no such relation or relation was not fetched, it always creates an empty BackLink object for such fields.
I understand, that it is confusing. But I didn't find a good solution to handle it equally for all the cases. Like I can understand, that nothing was returned back using fetch_links==True
and put None there, but I can not understand, what should be set there, if fetch_links==False
. And I can not handle these two scenarios differently, as it will not be consistent.
I'm open for suggestions. If you have any ideas about this case, please share. We can discuss it in real-time on the Discord server. Or here, for sure.
Thank you for the catch. This topic definitely needs more investigation.
This issue is stale because it has been open 30 days with no activity.
This issue was closed because it has been stalled for 14 days with no activity.
Describe the bug A clear and concise description of what the bug is. BackLink with None Create return dont None
To Reproduce
Expected behavior I want issue.sprint == None true