Unable to get results from related documents in FastAPI-Users and Beanie - fastapi

I have a couple of models:
class Message(Document):
phone: str
message_body: str
user: Indexed(PydanticObjectId)
class Settings:
name = "Message"
class User(BeanieBaseUser[PydanticObjectId]):
messages: Optional[List[Link[Message]]]
They have a relationship using Beanie Link.
The Message model is a custom Model and User is the default of FastAPI-Users.
When I save a record with insert() on a Message that is the child model, it does not establish a relationship with the parent. Returning the dict with null messages field.
Any idea what could be the error?

One way to do this is with fetch_link
#app.get("/messages")
async def list_messages(user: User = Depends(current_active_user)):
await user.fetch_link(User.messages)
return user.messages
Checkout the response from FastAPI-Users creator
https://github.com/fastapi-users/fastapi-users/discussions/1006#discussion-4101669

Related

FastAPI: where to set exclude_unset=True?

I am learning fastAPI and don't know how to update user info partially. The given solution is to set exclude_unset=True, but I don't know where to write it. Here are my pieces of code:
routers/user.py:
#router.patch('/{id}', status_code=status.HTTP_202_ACCEPTED)
def update_user(id, request: sUser, db: Session = Depends(get_db)):
user = db.query(mUser).filter(mUser.id == id)
if not user.first():
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f'The User with the id {id} is not found')
user.update(request.dict(exclude={'createdAt'}, exclude_unset=True))
db.commit()
return user.first()
PS exclude = {'createdAt'} works, but exclude_unset=True doesn't..
Here is my user schema:
schemas.py
class User(BaseModel):
username: str
dob: datetime.date
password: str
createdAt: datetime.datetime
that's because you are using it on a User model instance.
If you want to receive partial updates, it's very useful to use the parameter exclude_unset in Pydantic's model's .dict().
so use it on Pydantic object.
more info in documentation: https://pydantic-docs.helpmanual.io/usage/exporting_models/#modeldict
Set it as follows:
a.dict(exclude_unset=True)
where a is the object, see the example here:
https://github.com/samuelcolvin/pydantic/issues/1399

Flutter listen to one document change using provider

I have seen examples of listening to document changes in streambuilder, but is it possible to use it in providers? I want to listen to changes in the document in userinfo collection.
Here is my code:
in databaseservice.dart
Stream <DocumentSnapshot> get info{
return userinfo.doc(uid).snapshots();
}
In main
return MultiProvider(
providers: [
StreamProvider<DocumentSnapshot>.value(
value: DatabaseService().info
), // other providers
In wrapper where I need to see the change:
final info = Provider.of<DocumentSnapshot>(context).data();
However, I'll first get error:
The method 'data' was called on null.
Receiver: null
Tried calling: data()
And later, the info variable is giving me null instead of a map.
I want to let users input their name and age after their first signup, but not when they sign in. So my idea is that when users sign up, there will be a new document in the collection, "userinfo", which sets their age and name as null at first.
Then the wrapper checks if the name is null. If null, it will turn to the gather information page. If it has a value, it will turn to the home page.
Could anyone tell me where I am doing wrong with my document snapshot thing, or have a better idea to implement this?

How to trigger onCreate() when a new field is created in an existing Firestore document?

I want to create a new node in firebase realtime database when a field is created in an existing Firestore document.
I have been trying this:
exports.addUserCredentials = functions.firestore
.document(`Users/{UserID}/{username}`)
.onCreate((snapshot, context) => {
const newUserData = snapshot.data()
const newUserUsername = newUserData
const newUserUidDoc = context.params.UserID
return admin.database().ref(`/userCredentials/${newUserUsername}`).set({"UID": newUserUidDoc})
})
I have searched around the web I saw the path must be directed towards a document only and not a collection. BUT username in the path is a FIELD in the document.
I am getting this error while deploying and I have seen all similar questions but those didn't perfectly answered mine:
! functions: failed to update function addUserCredentials
HTTP Error: 400, The request has errors
The reason is can't change my path to Users/{UserID} which will make my code run perfectly is the fields of document are not added at once.
Here is screenshot of my firestore structure:
The 4 fields of document are updated in 2 batches.
The EMAIL and timeCreated fields are added first and those create the document.
While on the other hand, phoneData and username are fields are CREATED [not updated] after 5 seconds of Email and timeCreated.
So if I use onCreate() on the path Users/{UserID}, it will return UNDEFINED to my realtime database as the username field is ABSENT at that instant.
Is there any way to apply onCreate() on a specific field of the document?
[I am doing this to create a separate node which contains username and UID, this is to check if an username exists when a new user is trying to sign up]
So if the node is created with value undefined it will be an issue.
It will be like this:
The EMAIL and timeCreated fields are added first and those create the document. While on the other hand, phoneData and username are fields are CREATED [not updated] after 5 seconds of Email and timeCreated.
No matter what fields are adding once you created a document,it will be considered as an update operation against that document.As you mentioned in the question,there will be no field with field name called username with a document while you creating document.So it is not possible to get the value of username while you creating the document.
According to your explanation the field username will be only available with the onUpdate trigger.
So the code should be something like below
exports.addUserCredentials = functions.firestore
.document(`Users/{UserID}`)
.onUpdate((snapshot, context) => {
const beforeData = snapshot.before.data()
const afterData = snapshot.after.data()
if(!beforeData.username && afterData.username){
return admin.database().ref(`/userCredentials/${newUserUsername}`).set({"UID": newUserUidDoc})
}
})

How to allow Flutter to get a value that it stored in a firebase server or any server?

Right now I am using an http 0.11.3+16 and I am able to add a true value to an item on the site using the following function:
if (newAcceptStatus) {
response = await http.put('https://example.com/example1/${selectedOrder.id}/example2/${_authenticatedUser.id}.json?auth=${_authenticatedUser.token}',
body: json.encode(true));
this function is only called when the admin is logged in and the admin is the only one that can change the status of the Boolean, so the value is stored under the admins id and token. so I tried the following to help show if the item was changed by the admin to the user but i keep getting that the value is null when i decode the response with the following function:
Future<Null> checkAccept() async{
http.Response response;
response = await http.get('https://example.com/example1/${selectedOrder.id}/example2/(admin id goes here).json?auth=${_authenticatedUser.token}');
accepted = json.decode(response.body);
}
not sure what i am doing wrong. any help would be appreciated!
I was calling the wrong list of items which were very similar, thus giving me an empty list

firebase function af.database.object unable to return each object in a variable

I want get the user profile data from firebase of a specified user.
By instance I want return the displayName and the email address of the user where UID HBJKD12345
I use this function :
this.userProfile = this.af.database.object('/users/'+this.authInfo.uid)
But with a console.log(this.userProfile.email) I get a "Undefined"
In my view I have to use : {{(userProfile | async )?.email}}
With this line I can show the email address of the user but why I get "Undefined" when I try with console.log ?
Your view works because of async. It unwraps the actual value. For console.log(), you would need to do something similar. Try this.userProfile.$value().
Take a look at https://github.com/angular/angularfire2/blob/master/docs/2-retrieving-data-as-objects.md#meta-fields-on-the-object or https://github.com/angular/angularfire2/blob/master/docs/2-retrieving-data-as-objects.md#meta-fields-on-the-object

Resources