ก่อนจะไปเขียน python ก็ต้องมี firebase ให้เรียกใช้งานก่อน
เริ่มต้นไปที่
firebase google (ต้องใช้ google account)
firebase คือ อะไร ไปอ่านเวปนี้
ref. เวปนี้จะเน้นไปทาง java
สร้าง project ขึ้นมาก่อน (google ให้เราสร้างได้ฟรี 25 projects)
click ที่ Database ก็จะมีหน้าตาประมาณนี้ ส่วนที่จะเอาไปใช้คือ ลิงค์
[ https://sample-app-a1e7f.firebaseio.com/ ] แต่ละคน จะได้ส่วนนี้แตกต่างกันไป
ลิงค์นี้คือ ส่วนที่เอาไว้เรียกใช้งาน
แต่โดย default ตรง Ruls (กฎ) จะไม่ยอมให้คนอื่น acces ได้เลย ดังนั้น เราต้องเข้าไปแก้ไขซะ
เบื้องต้นก็แก้ให้เป็น true ให้หมดไปก่อน
อ่านที่เวปนี้ เขียนอธิบายไว้ละเอียด
ref.
ตัวอย่างข้อมูล ก็จะได้หน้าตาประมาณนี้ เป็น JSON
ทดสอบว่าสามารถใช้งานได้ สามารถเรียกดูได้จาก
https://sample-app-a2e7f.firebaseio.com/mydata.json
ต่อมาในส่วนของ python
ขั้นแรก import firebase package ตอนนี้ มีอยู่ 3 แหล่งที่ทาง google แนะนำ
ref
ลง package ที่ต้องจำเป็นก่อนที่จะใช้งานตัวนี้คือ requests
$ sudo pip install requests
$ sudo pip install python-firebase
$ sudo pip install python-firebase-gae
** ตัวนี้ถ้าไปใช้กับ google appengine standard จะมีปัญหา เนื่องจากไม่ support multi processor ให้ติดตั้ง python-firebase อีกตัวแทน
ดูรายละเอียดได้ที่
https://github.com/b4oshany/python-firebase-gae/
ใน code python ให้เพิ่ม 2 บรรทัดนี้ลงไป
from firebase import firebase
firebase = firebase.FirebaseApplication('https://sample-app-x.firebaseio.com', None)
ตรงส่วนสีแดง ก็ใส่ URL link ของตัวเองลงไป
วิธีเขียนข้อมูลลง DB
ref
PUT กับ POST ใช้ต่างกันยังไง
- PUT จะต้องระบุ key
- POST จะสร้าง random key ให้
เช่น
result = firebase.post(id, data['comment'])
firebase จะ random key ให้
/id
-Kq7rSDsQRXWKAVu0phH: "comment"
หากอยากระบุ key ของตัวเอง และ ให้ firebase สร้าง key ให้
result = firebase.post(id,{'comment': 'mycomment'})
ได้ nested JSON
/id
-Kq7swawlLJlz07VEBFT
comment: "mycomment"
กรณี PUT จะต้องระบุ key ให้ด้วย
result = firebase.put(id,'comment',{'msg': 'mycomment'})
จะได้ผลลัพธ์แบบนี้
/id
-comment
msg: "mycomment"
ถ้าอ้างอิง id , comment เดิม ข้อมูลที่ put ลงมาจะเขียนทับ ข้อมูลเก่า
PATCH ใช้ update key ที่ระบุไว้ โดยไม่กระทบ กับ ข้อมูลส่วนอื่น
DELETE เอาไว้ลบข้อมูล
firebase.delete(id, 'comment')
วิธีการเรียกอ่านข้อมูล GET
ref
result = firebase.get('/users', '1')
ใส่ option {'print': 'pretty'} เพื่อให้ ผลออกมาอ่านได้ง่ายขึ้น
result = firebase.get('/users/2', None, {'print': 'pretty'}, {'X_FANCY_HEADER': 'VERY FANCY'})
ลองเอา URL นี้วางใน browser https://sample-app-a1e7f.firebaseio.com/mydata.json
จะได้ผลออกมาแบบนี้ ซึ่งอ่านยากมาก
ลองเพิ่ม option print = pretty
https://sample-app-a1e7f.firebaseio.com/mydata.json?print=pretty
จะได้ผลออกมาแบบนี้ ซึ่งอ่านง่ายกว่าเยอะ
Authentication
from firebase import firebase
firebase = firebase.FirebaseApplication('https://your_storage.firebaseio.com', authentication=None)
result = firebase.get('/users', None, {'print': 'pretty'})
print result
{'error': 'Permission denied.'}
authentication = firebase.Authentication('THIS_IS_MY_SECRET', 'ozgurvt@gmail.com', extra={'id': 123})
firebase.authentication = authentication
print authentication.extra
{'admin': False, 'debug': False, 'email': 'ozgurvt@gmail.com', 'id': 123, 'provider': 'password'}
user = authentication.get_user()
print user.firebase_auth_token
"eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJhZG1pbiI6IGZhbHNlLCAiZGVidWciOiBmYWxzZSwgIml
hdCI6IDEzNjE5NTAxNzQsICJkIjogeyJkZWJ1ZyI6IGZhbHNlLCAiYWRtaW4iOiBmYWxzZSwgInByb3ZpZGVyIjog
InBhc3N3b3JkIiwgImlkIjogNSwgImVtYWlsIjogIm96Z3VydnRAZ21haWwuY29tIn0sICJ2IjogMH0.lq4IRVfvE
GQklslOlS4uIBLSSJj88YNrloWXvisRgfQ"
result = firebase.get('/users', None, {'print': 'pretty'})
print result
{'1': 'John Doe', '2': 'Jane Doe'}
เมื่อ sign-in ด้วย email,password ใช้ function Authentication เพื่อ ให้ firebase สร้าง token สำหรับใช้ตรวจสอบว่ากับ rule ว่ามีสิทธิ์มั้ย
authentication = firebase.Authentication('password', 'email', extra={'id': 123})
ดูค่าที่ทาง server return กลับมา
print authentication.extra
{'admin': False,
'debug': False,
'email': 'ozgurvt@gmail.com',
'id': 123,
'provider': 'password'}
provider คือ attribute ที่บอกว่า เรา authen ด้วยวิธีใด
เนื่องจาก firebase รองรับ multi provider คือ login ด้วย google , facebook .. สามารถมี accout id เดียวกันได้ id คือ ตัวบอกว่า login ด้วยวิธีนี้ แล้วจะได้ id อะไร
* ควรใช้กับ python3 หากใช้กับ python2 อาจจะมีข้อผิดพลาด
pip install pyrebase
เรียกใช้
import pyrebase
config = {
"apiKey": "apiKey",
"authDomain": "projectId.firebaseapp.com",
"databaseURL": "https://databaseName.firebaseio.com",
"storageBucket": "projectId.appspot.com",
"serviceAccount": "path/to/serviceAccountCredentials.json"
}
firebase = pyrebase.initialize_app(config)
serviceAccount ไว้สำหรับเมื่อ admin login เข้ามาสามารถใช้งานได้โดยไม่สน rule ที่ประกาศใน firebase
วิธีการ create serviceAccountCredentials
ref
1. เข้าไปที่หน้า
firebase console แล้วเลือก setting (รูปเฟือง) > users and permissions
2. เลือก Service accounts
3. ที่ฝั่งขวา เลือก firebase-adminsdk แล้วกด create key
4. เมื่อได้ไฟล์มา เอาไปวางไว้ที่ server เพื่อ เรียกใช้ (ตัวอย่าง ส่วนหนึ่ง)
Pyrebase เรียกใช้ firebase service ได้ถึง 3 (python-firebase ได้แค่ database , authen)
- firebase.auth() - Authentication
- firebase.database() - Database
- firebase.storage() - Storage
Authentication
sign_in_with_email_and_password() จะส่ง user data และ token เพื่อใช้กับ firebase rule
# Get a reference to the auth service
auth = firebase.auth()
# Log the user in
user = auth.sign_in_with_email_and_password(email, password)
# Get a reference to the database service
db = firebase.database()
# data to save
data = {
"name": "Mortimer 'Morty' Smith"
}
# Pass the user's idToken to the push method
results = db.child("users").push(data, user['idToken'])
ระบุ user['idToken'] ด้วยเพื่อให้มี สิทธิ์ในการ write
ปกติ token จะ expire ภายใน 1 ชม. ดังนั้นหากมีการใช้อยู่ให้เรา refresh ใหม่เรื่อยๆ
user = auth.sign_in_with_email_and_password(email, password)
# before the 1 hour expiry:
user = auth.refresh(user['refreshToken'])
# now we have a fresh token
user['idToken']
Manage User
create user ที่ใช้ email /password
auth.create_user_with_email_and_password(email, password)
* ต้อง enable sign-in method ที่ firebase dashboard ด้วย
Verifying emails
auth.send_email_verification(user['idToken'])
Sending password reset emails
auth.send_password_reset_email("email")
Get account information
auth.get_account_info(user['idToken'])
Database
- Save data
ใช้ child() method ในการสร้าง path ลงไปในแต่ละ level (google support 32 levels)
db = firebase.database()
db.child("users").child("Morty")
push : ใช้เก็บข้อมูลที่ต้องไม่ซ้ำ สร้าง key อัตโนมัติ, timestamp-based key
data = {"name": "Mortimer 'Morty' Smith"}
db.child("users").push(data)
set : เมื่อต้องการระบุ key ของตัวเอง key ที่ระบุคือ "Morty"
data = {"name": "Mortimer 'Morty' Smith"}
db.child("users").child("Morty").set(data)
update : อัพเดทข้อมูลที่มีอยู่แล้ว
db.child("users").child("Morty").update({"name": "Mortiest Morty"})
remove : ลบข้อมูลที่มีอย่แล้ว
db.child("users").child("Morty").remove()
multi-location updates : อัพเดทพร้อมกับหลายที่
data = {
"users/Morty/": {
"name": "Mortimer 'Morty' Smith"
},
"users/Rick/": {
"name": "Rick Sanchez"
}
}
db.update(data)
ใช้ push อัพเดทพร้อมกันหลายที่ต้องใช้คู่กับ generate_key() method.
data = {
"users/"+db.generate_key(): {
"name": "Mortimer 'Morty' Smith"
},
"users/"+db.generate_key(): {
"name": "Rick Sanchez"
}
}
db.update(data)
- Retrieve data
val : เมื่อได้ object มา ใช้ val() ในการ
users = db.child("users").get()
print(users.val())
# {"Morty": {"name": "Mortimer 'Morty' Smith"},
"Rick": {"name": "Rick Sanchez"}}
ดึงเฉพาะ value จาก attribute ที่ต้องการ
print(users.val()["name"])
#{ Mortimer 'Morty' Smith ,
# Rick Sanchez }
key : method key() เรียกค่า key อย่างเดียว
user = db.child("users").get()
print(user.key())
# users
each : ดึงค่าออกมาเป็น list แล้วใช้ key() , val() แสดงค่าอีกที
all_users = db.child("users").get()
for user in all_users.each():
print(user.key()) # Morty
print(user.val()) # {name": "Mortimer 'Morty' Smith"}
print(user.val()["name"])
get : ดึงค่าจาก path ทั้งหมด
all_users = db.child("users").get()
shallow : ดึงเฉพาะ ค่า key ออกมาเท่านั้น
all_user_ids = db.child("users").shallow().get()
# {"Morty",
"Rick"}
* shallow() ใช้ร่วมกับ complex querie ไม่ได้
streaming : จับการเปลี่ยนแปลงของข้อมูลทันที ที่มีการเปลี่ยน
def stream_handler(message):
print(message["event"]) # put
print(message["path"]) # /-K7yGTTEp7O549EzTYtI
print(message["data"]) # {'title': 'Pyrebase', "body": "etc..."}
my_stream = db.child("posts").stream(stream_handler)
อย่างน้อยควรจะ put หรือ patch ข้อมูลด้วย
Streaminig from the REST API
ถ้ามีการทำ multiple stream ควรระบุ stream_id ด้วย
my_stream = db.child("posts").stream(stream_handler, stream_id="new_posts")
close the stream
my_stream.close()
Complex Queries
Queries สามารถใช้ method ต่อกันได้เรื่อยๆ
users_by_name = db.child("users").order_by_child("name").limit_to_first(3).get()
ผลลัพธ์จะได้ 3 users แรกเรียงตามชื่อ
order_by_child : เรียงตาม level ที่กำหนด ตาม key
users_by_name = db.child("users").order_by_child("name").get()
equal_to : คืนค่าที่มี value ตามที่กำหนด
users_by_score = db.child("users").order_by_child("score").equal_to(10).get()
คืนค่า users ที่มี score เท่ากับ 10
start_at and
end_at : ระบุ range ของข้อมูล
users_by_score = db.child("users").order_by_child("score").start_at(3).end_at(10).get()
คืนค่า users เรียงตาม score ที่มี score อยู่ระหว่าง 3-10
limit_to_first and
limit_to_last : limit ข้อมูลที่รับ
users_by_score = db.child("users").order_by_child("score").limit_to_first(5).get()
order_by_key : เรียง key ตาม ascending (น้อยไปมาก)
users_by_key = db.child("users").order_by_key().get()
order_by_value : เรียงตาม value
users_by_value = db.child("users").order_by_value().get()
Storage
ใช้เก็บข้อมูลรูปภาพ ไฟล์
child : ระบุ path ที่จะใช้เก็บ
storage.child("images/example.jpg")
put : รับ path จาก local file และ ใส่ token เป็น option ได้
storage = firebase.storage()
# as admin
storage.child("images/example.jpg").put("example2.jpg")
# as user
storage.child("images/example.jpg").put("example2.jpg", user['idToken'])
หากรับ filename มาจาก <input type="file" name="image" />
ตอนรับข้อมูลให้ส่ง request.files.get('image') มาให้ put
storage.child("images/example.jpg").put(request.files.get('image'))
download : ดึงข้อมูลมาเก็บลง local และ สามารถเปลี่ยนชื่อได้
storage.child("images/example.jpg").download("downloaded.jpg")
get_url : คืนค่า url สำหรับ access ผ่าน http
storage.child("images/example.jpg").get_url()
# https://firebasestorage.googleapis.com/v0/b/storage-url.appspot.com/o/images%2Fexample.jpg?alt=media
generate_key : db.generate_key() ใช้ตาม Firebase's key generation algorithm
sort : ปกติ เราจะใช้ orderby แต่ถ้าเราต้องการเรียงอีกที ให้ใช้ sort() method
.
articles = db.child("articles").order_by_child("date").start_at(startDate).end_at(endDate).get()
articles_by_likes = db.sort(articles, "likes")
*Storage ยังไม่มี method delete()