如何实现仅在Firestore文档的NewImageRequested字段从False切换为True时触发Storage图片上传
Absolutely, you can tweak your listener to only trigger the image upload exactly when NewImageRequested switches from False to True—no more unwanted runs from other field changes or resetting the field itself. Here's how to fix it:
The Core Issue
Right now, your code reacts to any modification to the document, regardless of which field changed or what the value transition was. We need to add checks to validate both the field that changed and the specific state shift we care about.
Modified Listener Code
Update your on_snapshot function with these conditional checks to narrow down the trigger:
def on_snapshot(doc_snapshot, changes, read_time): for change in changes: if change.type.name == 'MODIFIED': # Get the old and new values of the target field old_value = change.before.get(u'NewImageRequested') new_value = change.after.get(u'NewImageRequested') # Only proceed if the field switched from False to True if old_value is False and new_value is True: print('\tNew image requested, uploading to storage') # Upload the image to Storage storage.child('images/ipcam/upload_test.png').put('non_local_networks.png') # Reset the field back to False change.after.reference.update({u'NewImageRequested': False}) print('\tNew image uploaded and request flag reset')
Key Improvements Explained
- Track Value Transitions: By comparing
change.before(the state before modification) andchange.after(the new state), we can confirm the exact shift fromFalsetoTrue. - Avoid Unwanted Triggers: This skips any modifications to other fields, and also ignores when we reset the field back to
False(since that transition would beTrue→False, which doesn't meet our condition). - Use Document Reference: Using
change.after.referenceinstead of the globaldoc_refmakes the code more flexible (useful if you ever expand to listen to multiple documents).
Full Updated Code Context
Here's how the rest of your code fits with this change (I also added a graceful shutdown handler for the listener):
import time import pyrebase import firebase_admin from firebase_admin import credentials, firestore db_credentials_file = 'local_file.json' firebase_config = { 'apiKey': "AIzaSyCi2_82wp1txEv6PbmY7TpPJCA-tlKfXnc", 'authDomain': "coachmylife-dev.firebaseapp.com", 'databaseURL': "https://coachmylife-dev.firebaseio.com", 'projectId': "coachmylife-dev", 'storageBucket': "coachmylife-dev.appspot.com", 'messagingSenderId': "317036767832", 'appId': "1:317036767832:web:6a5a4e61f794bd7db6382d", 'measurementId': "G-HGE4Q3R0GM", 'serviceAccount': db_credentials_file } firebase_storage = pyrebase.initialize_app(firebase_config) storage = firebase_storage.storage() cred = credentials.Certificate(f"{db_credentials_file}") firebase_data = firebase_admin.initialize_app(cred) db = firestore.client() print('Connection initialized') doc_ref = db.collection(u'CollectionName').document(u'DocumentName') def main(): doc_watch = doc_ref.on_snapshot(on_snapshot) try: while True: time.sleep(5) except KeyboardInterrupt: doc_watch.unsubscribe() print("Listener unsubscribed gracefully") def on_snapshot(doc_snapshot, changes, read_time): for change in changes: if change.type.name == 'MODIFIED': old_value = change.before.get(u'NewImageRequested') new_value = change.after.get(u'NewImageRequested') if old_value is False and new_value is True: print('\tNew image requested, uploading to storage') storage.child('images/ipcam/upload_test.png').put('non_local_networks.png') change.after.reference.update({u'NewImageRequested': False}) print('\tNew image uploaded and request flag reset') if __name__ == '__main__': main()
内容的提问来源于stack exchange,提问作者Carlo

