Flutter Python: Firebase like backend in Flutter using Python! (MongoDB and WebSocket) Published by on

Create a rest API using Python with MongoDB, then notify changes through WebSocket in a flutter. In this flutter python blog, we will implement Rxdart for making HTTP request Reactive.

In this, we will not deal with model classes in Flutter as I tried to make it as like as the firebase database backend.

Before diving into code make sure of installing the following for backend!

Create a new project in Pycharm then Install dependencies in python project.in this project, we will use Aiohttp server for python

pip install aiohttp pip install pymongo pip install bson pip install python-socketio 1 2 3 4 pip install aiohttp pip install pymongo pip install bson pip install python - socketio

Websocket notify any changes made in the database, data will be pass-through socket.emit() and socket.on() will listen.

socket.emit() to emit data to an event.

socket.on() get data from emit.

Create new python file api.py and check if the server is running properly!

from aiohttp import web import json async def apitest(request): result ={"status":"200"} return web.Response(text=json.dumps(result), status=200) app = web.Application() app.router.add_get('/apitest',apitest) web.run_app(app) 1 2 3 4 5 6 7 8 9 10 from aiohttp import web import json async def apitest ( request ) : result = { "status" : "200" } return web . Response ( text = json . dumps ( result ) , status = 200 ) app = web . Application ( ) app . router . add_get ( '/apitest' , apitest ) web . run_app ( app )

Type terminal python api.py to run this file then check http://localhost:8080/apitest in postman

As server is running properly, let’s add MongoDB in and create two functions one for adding data in database and second one for fetching data.

from aiohttp import web import json import pymongo from bson import json_util mongourl = "mongodb://localhost:27017/" #Database url async def apitest(request): result ={"status":"200"} return web.Response(text=json.dumps(result), status=200) async def create(request): try: collection = request.match_info.get('collection', "Anonymous") #Get collection name from params myclient = pymongo.MongoClient(mongourl) mydb = myclient["database"] # Database Name mycol = mydb["collection"] # Collection name j = await request.json() x = mycol.insert_one(j) # emit something is changed notify event through webSocket await sio.emit('notify',str(x.inserted_id)) response_obj = {'status': 'success',"_id":str(x.inserted_id)} return web.Response(text=json.dumps(response_obj), status=200) except Exception as e: response_obj = {'status': 'failed', 'reason': str(e)} web.Response(text=json.dumps(response_obj), status=500) async def show(request): try: collection = request.match_info.get('collection', "Anonymous") #Get collection name from params myclient = pymongo.MongoClient(mongourl) mydb = myclient["database"] # Database Name mycol = mydb["collection"] # Collection name mydoc = list(mycol.find()) # add all data in a List # convert list into json response_obj = json.loads(json_util.dumps(mydoc)) res = {"Data":response_obj} return web.Response(text=json.dumps(res), status=200) except Exception as e: response_obj = {'status': 'failed', 'reason': str(e)} web.Response(text=json.dumps(response_obj), status=500) app = web.Application() #Add Routers app.router.add_get('/apitest',apitest) app.router.add_post('/create/{collection}',create) app.router.add_get('/show/{collection}',show) if __name__ == '__main__': web.run_app(app) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 from aiohttp import web import json import pymongo from bson import json_util mongourl = "mongodb://localhost:27017/" #Database url async def apitest ( request ) : result = { "status" : "200" } return web . Response ( text = json . dumps ( result ) , status = 200 ) async def create ( request ) : try : collection = request . match_info . get ( 'collection' , "Anonymous" ) #Get collection name from params myclient = pymongo . MongoClient ( mongourl ) mydb = myclient [ "database" ] # Database Name mycol = mydb [ "collection" ] # Collection name j = await request . json ( ) x = mycol . insert_one ( j ) # emit something is changed notify event through webSocket await sio . emit ( 'notify' , str ( x . inserted_id ) ) response_obj = { 'status' : 'success' , "_id" : str ( x . inserted_id ) } return web . Response ( text = json . dumps ( response_obj ) , status = 200 ) except Exception as e : response_obj = { 'status' : 'failed' , 'reason' : str ( e ) } web . Response ( text = json . dumps ( response_obj ) , status = 500 ) async def show ( request ) : try : collection = request . match_info . get ( 'collection' , "Anonymous" ) #Get collection name from params myclient = pymongo . MongoClient ( mongourl ) mydb = myclient [ "database" ] # Database Name mycol = mydb [ "collection" ] # Collection name mydoc = list ( mycol . find ( ) ) # add all data in a List # convert list into json response_obj = json . loads ( json_util . dumps ( mydoc ) ) res = { "Data" : response_obj } return web . Response ( text = json . dumps ( res ) , status = 200 ) except Exception as e : response_obj = { 'status' : 'failed' , 'reason' : str ( e ) } web . Response ( text = json . dumps ( response_obj ) , status = 500 ) app = web . Application ( ) #Add Routers app . router . add_get ( '/apitest' , apitest ) app . router . add_post ( '/create/{collection}' , create ) app . router . add_get ( '/show/{collection}' , show ) if __name__ == '__main__' : web . run_app ( app )

Now create new flutter project and install these dependencies in pubspec.yaml

rxdart: ^0.23.1 http: ^0.12.0+3 socket_io_client: ^0.9.7+2 1 2 3 rxdart : ^ 0.23.1 http : ^ 0.12.0 + 3 socket_io_client : ^ 0.9.7 + 2

create service.dart and make sure of giving the exact hosted IP address of your machine before port address.

import 'package:rxdart/rxdart.dart'; import 'dart:convert' as convert; import 'package:http/http.dart' as http; import 'package:socket_io_client/socket_io_client.dart' as IO; class Service{ IO.Socket socket =IO.io('http://192.168.0.5:8080' ,<String, dynamic>{ 'transports': ['websocket'] }) ; String initialCount = ''; //if the data is not passed by paramether it initializes with '' BehaviorSubject<String> _subjectCounter; Service({this.initialCount}){ #Show emited data on notify event through websocket! socket.on('notify', (data) { print(data); httpRequest(); }); _subjectCounter = new BehaviorSubject<String>.seeded(this.initialCount); //initializes the subject with element already } Stream<String> get counterObservable => _subjectCounter.stream; void increment(){ httpPostRequest(); httpRequest(); } #Get User Data void httpRequest() async{ var url = 'http://192.168.0.5:8080/show/user'; // Await the http get response, then decode the json-formatted response. var response = await http.get(url); if (response.statusCode == 200) { var jsonResponse = convert.jsonDecode(response.body); var itemCount = jsonResponse; _subjectCounter.sink.add(response.body); print('Number of books about http: $jsonResponse.'); } else { print('Request failed with status: ${response.statusCode}.'); } } #Post User Data void httpPostRequest() async{ var url = 'http://192.168.0.5:8080/create/user'; Map data = { "firstName": "CodeSearch", "lastName": "Online" }; var body = convert.json.encode(data); Map userHeader = {"Content-type": "application/json", "Accept": "application/json"}; // Await the http get response, then decode the json-formatted response. var response = await http.post(url,body:body,headers:{"Content-Type": "application/json"}); if (response.statusCode == 200) { var jsonResponse = convert.jsonDecode(response.body); var itemCount = jsonResponse; print('Number of books about http: $jsonResponse.'); } else { print('Request failed with status: ${response.statusCode}.'); } } void dispose(){ _subjectCounter.close(); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 import 'package:rxdart/rxdart.dart' ; import 'dart:convert' as convert ; import 'package:http/http.dart' as http ; import 'package:socket_io_client/socket_io_client.dart' as IO ; class Service { IO . Socket socket = IO . io ( 'http://192.168.0.5:8080' , < String , dynamic > { 'transports' : [ 'websocket' ] } ) ; String initialCount = '' ; //if the data is not passed by paramether it initializes with '' BehaviorSubject < String > _subjectCounter ; Service ( { this . initialCount } ) { #Show emited data on notify event through websocket! socket . on ( 'notify' , ( data ) { print ( data ) ; httpRequest ( ) ; } ) ; _subjectCounter = new BehaviorSubject < String > . seeded ( this . initialCount ) ; //initializes the subject with element already } Stream < String > get counterObservable = > _subjectCounter . stream ; void increment ( ) { httpPostRequest ( ) ; httpRequest ( ) ; } #Get User Data void httpRequest ( ) async { var url = 'http://192.168.0.5:8080/show/user' ; // Await the http get response, then decode the json-formatted response. var response = await http . get ( url ) ; if ( response . statusCode == 200 ) { var jsonResponse = convert . jsonDecode ( response . body ) ; var itemCount = jsonResponse ; _subjectCounter . sink . add ( response . body ) ; print ( 'Number of books about http: $jsonResponse.' ) ; } else { print ( 'Request failed with status: ${response.statusCode}.' ) ; } } #Post User Data void httpPostRequest ( ) async { var url = 'http://192.168.0.5:8080/create/user' ; Map data = { "firstName" : "CodeSearch" , "lastName" : "Online" } ; var body = convert . json . encode ( data ) ; Map userHeader = { "Content-type" : "application/json" , "Accept" : "application/json" } ; // Await the http get response, then decode the json-formatted response. var response = await http . post ( url , body : body , headers : { "Content-Type" : "application/json" } ) ; if ( response . statusCode == 200 ) { var jsonResponse = convert . jsonDecode ( response . body ) ; var itemCount = jsonResponse ; print ( 'Number of books about http: $jsonResponse.' ) ; } else { print ( 'Request failed with status: ${response.statusCode}.' ) ; } } void dispose ( ) { _subjectCounter . close ( ) ; } }

Show data in list view in main.dart!