Streamlit ile Kullanıcı Girişli Uygulama Yapımı

Oğuzhan Arı
6 min readMay 14, 2024

--

çok basit bir ihtiyacınız için ufak bir kullanıcı girişi olacak uygulamaya ihtiyacınız var ancak ne hosting ne html ne ucu ne bucu hiçbir şeyle uğraşmak istemiyorsunuz. işte size, yine, mükemmel bir fırsat! veri tabanı google sheets olan, tamamen streamlit üzerinde çalışan ve sadece 52 satır koddan oluşan müthiş bir uygulama.

her şeyden önce, kullanıcının mevcut durumunu takip edebilmek adına bir user_state tanımlıyoruz. user_state, o an kullanıcının bulunduğu durumu takip etmemize ve uygulamanın ona göre davranmasını sağlıyor.

import streamlit as st

st.title('Amazing User Login App')

# Create user_state
if 'user_state' not in st.session_state:
st.session_state.user_state = {
'username': '',
'password': '',
'logged_in': False
}

uygulama yüklendiğinde, session_state içerisinde bir user_state bulunmadığı için direkt olarak oluşturuyoruz ve içerisine saklamak istediğimiz bilgileri giriyoruz.

eğer, kullanıcımız giriş yapmamışsa, kullanıcının karşısına bir giriş yap butonu çıkmasını istiyoruz.

if not st.session_state.user_state['logged_in']:
# Create login form
st.write('Please login')
username = st.text_input('Username')
password = st.text_input('Password', type='password')
submit = st.button('Login')

daha sonrasında, kullanıcının doğru bir kullanıcı olup olmadığını test etmemiz gerekiyor. submit değişkenine atadığımız butona basıldığında, giriş yapılmasını istiyoruz. öncelikle genel mantığını test etmek adına kullanıcı adının admin, şifresinin ise 1234 olduğu bir senaryoyu deniyoruz.

    # Check if user is logged in
if submit and st.session_state.user_state['logged_in'] == False:
if username == 'admin' and password == '1234':
st.session_state.user_state['username'] = username
st.session_state.user_state['password'] = password
st.session_state.user_state['logged_in'] = True
st.write('You are logged in')

eğer kullanıcının adı ve şifresi doğruysa, kullanıcıya ait bilgileri session_state içerisindeki user_state’e atıyoruz. eğer bilgiler doğru değilse, bunu ekrana yazdırıyoruz.

        else:
st.warning('Invalid username or password')

bütün giriş sürecimiz şu şekilde görülmelidir.

if not st.session_state.user_state['logged_in']:
# Create login form
st.write('Please login')
username = st.text_input('Username')
password = st.text_input('Password', type='password')
submit = st.button('Login')

# Check if user is logged in
if submit and st.session_state.user_state['logged_in'] == False:
if username == 'admin' and password == '1234':
st.session_state.user_state['username'] = username
st.session_state.user_state['password'] = password
st.session_state.user_state['logged_in'] = True
st.write('You are logged in')
st.rerun()
else:
st.warning('Invalid username or password')

burada, yukarıda olmayan en önemli şey, st.rerun() detayıdır. buradaki amacımız, user_state’i güncelledikten sonra, uygulamanın yeni kullanıcı durumuna göre tekrardan çalışmasını istiyoruz. kullanıcıya ait bilgiler session_state içerisinde saklandığı için kaybolmuyor.

uygulamamız tekrardan çalıştığında, st.session_state.user_state[‘logged_in’] değerimiz artık True olacağı için, bunun için de bir mantık tanımlıyoruz.

elif st.session_state.user_state['logged_in']:
st.write('Welcome to the app')
st.write('You are logged in as:', st.session_state.user_state['username'])

bütün kodumuz şu şekilde görünmekte;

import streamlit as st

st.title('Amazing User Login App')

# Create user_state
if 'user_state' not in st.session_state:
st.session_state.user_state = {
'username': '',
'password': '',
'logged_in': False
}

if not st.session_state.user_state['logged_in']:
# Create login form
st.write('Please login')
username = st.text_input('Username')
password = st.text_input('Password', type='password')
submit = st.button('Login')

# Check if user is logged in
if submit and st.session_state.user_state['logged_in'] == False:
if username == 'admin' and password == '1234':
st.session_state.user_state['username'] = username
st.session_state.user_state['password'] = password
st.session_state.user_state['logged_in'] = True
st.write('You are logged in')
st.rerun()
else:
st.write('Invalid username or password')
elif st.session_state.user_state['logged_in']:
st.write('Welcome to the app')
st.write('You are logged in as:', st.session_state.user_state['username'])

ancak burada herhangi bir kullanıcı ekleme, yani uygulamamızı uzaktan güncelleme gibi bir durumumuz yok. bunun için bir veri tabanına ihtiyacımız var, onun için ise google sheets’ten yardım alacağız.

öncelikle bir google sheet oluşturuyoruz. bunun içerisine mail_adress, name_surname, user_type, password ve fixed_user_message değişkenlerini tanımlıyoruz.

bu google sheets’i herkes tarafından erişilebilir hale getiriyoruz. daha sonrasında linkini kopyalıyoruz

çalışmamızın içerisine .streamlit isminde bir klasör oluşturuyoruz. bu klasörün içerisine secrets.toml isimli bir dosya ekliyoruz. söz konusu linkin herkes tarafından görüntülenebilir olmasını istemediğinizden, sheetse ait url’i bu dosya içerisinde saklayacağız. urlimiz şu şekilde görünmekte

https://docs.google.com/spreadsheets/d/1UduSnVilnrfISEg2uVWqdKLl8aiHGQbsPo_UjyBbj4s/edit?usp=sharing

bu linkin sonundaki /edit?usp=sharing kısmını /export?format=csv olarak değiştiriyoruz ve secrets.toml dosyamıza database_url isimli değişkenle beraber atıyoruz.

çalışma dosyamıza request ve pandas kütüphanelerini ekleyerek, söz konusu dosyayı çağırıp database isimli değişkene bir pandas dataframe’i olarak kaydedecek kodumuzu hazırlıyoruz

import streamlit as st
import pandas as pd
import requests as rs

st.title('Amazing User Login App')

sheet_csv = st.secrets["database_url"]
res = rs.get(url=sheet_csv)
open('database.csv', 'wb').write(res.content)
database = pd.read_csv('database.csv', header=0)

yukarıdaki kod, linki secrets dosyasından okuyarak onu database.csv isimli dosyaya kaydediyor. daha sonrasında onu pandas kütüphanesi ile okuyoruz.

user_state’i veritabanımıza göre güncelliyoruz.

# Create user_state
if 'user_state' not in st.session_state:
st.session_state.user_state = {
'name_surname': '',
'password': '',
'logged_in': False,
'user_type': '',
'mail_adress': '',
'fixed_user_message': ''
}

aynı şekilde giriş kontrol mantığımızı da güncelleyeceğiz.

if not st.session_state.user_state['logged_in']:
# Create login form
st.write('Please login')
mail_adress = st.text_input('E-Mail')
password = st.text_input('Password', type='password')
submit = st.button('Login')

# Check if user is logged in
if submit:
user_ = database[database['mail_adress'] == mail_adress].copy()

yukarıdaki kod, kullanıcının e-mail yerine girilen mail adresi ile dataframe’ı sınırlandırarak, sadece mevcut kullanıcı için kontrolleri gerçekleştiriyor.

if user_['mail_adress'].values[0] == mail_adress and user_['password'].values[0] == password:
st.session_state.user_state['mail_adress'] = mail_adress
st.session_state.user_state['password'] = password
st.session_state.user_state['logged_in'] = True
st.session_state.user_state['user_type'] = user_['user_type'].values[0]
st.session_state.user_state['mail_adress'] = user_['mail_adress'].values[0]
st.session_state.user_state['fixed_user_message'] = user_['fixed_user_message'].values[0]
st.write('You are logged in')
st.rerun()

söz konusu user_ değişkeni hala bir pandas dataframe’i olduğu için, her sütunun sıfırıncı indeksine göre kontrolleri gerçekleştiriyoruz. buradaki önemli detay, programımız henüz kullanıcı veri tabanında mevcut mu değil mi bunun kontrolünü gerçekleştirmiyor. aklımızdayken bunu da ekleyelim.

if submit:
user_ = database[database['mail_adress'] == mail_adress].copy()
if len(user_) == 0:
st.error('User not found')

tüm giriş sürecimiz şu şekilde görünmekte.

if not st.session_state.user_state['logged_in']:
# Create login form
st.write('Please login')
mail_adress = st.text_input('E-Mail')
password = st.text_input('Password', type='password')
submit = st.button('Login')

# Check if user is logged in
if submit:
user_ = database[database['mail_adress'] == mail_adress].copy()
if len(user_) == 0:
st.error('User not found')
else:
if user_['mail_adress'].values[0] == mail_adress and user_['password'].values[0] == password:
st.session_state.user_state['mail_adress'] = mail_adress
st.session_state.user_state['password'] = password
st.session_state.user_state['logged_in'] = True
st.session_state.user_state['user_type'] = user_['user_type'].values[0]
st.session_state.user_state['mail_adress'] = user_['mail_adress'].values[0]
st.session_state.user_state['fixed_user_message'] = user_['fixed_user_message'].values[0]
st.write('You are logged in')
st.rerun()
else:
st.write('Invalid username or password')

peki, yavaş yavaş sona yaklaşıyoruz. peki ya kullanıcı bilgileri doğruysa? öncelikle veri tabanımızı güncelleyelim. 2 kullanıcımız olsun.

admin kullanıcısı için bu şekilde görünmekte,

ve user kullanıcısı için de bu şekilde görünmekte,

admin kullanıcımızın, standart kullanıcıdan bir farkı olsun ve veri tabanını da görebilsin.

elif st.session_state.user_state['logged_in']:
st.write('Welcome to the app')
st.write('You are logged in as:', st.session_state.user_state['mail_adress'])
st.write('You are a:', st.session_state.user_state['user_type'])
st.write('Your fixed user message:', st.session_state.user_state['fixed_user_message'])
if st.session_state.user_state['user_type'] == 'admin':
st.write('You have admin rights. Here is the database')
st.table(database)

son olarak, 54 satırlık uygulamamız şöyle görünmekte,

import streamlit as st
import pandas as pd
import requests as rs

st.title('Amazing User Login App')

sheet_csv = st.secrets["database_url"]
res = rs.get(url=sheet_csv)
open('database.csv', 'wb').write(res.content)
database = pd.read_csv('database.csv', header=0)

# Create user_state
if 'user_state' not in st.session_state:
st.session_state.user_state = {
'name_surname': '',
'password': '',
'logged_in': False,
'user_type': '',
'mail_adress': '',
'fixed_user_message': ''
}

if not st.session_state.user_state['logged_in']:
# Create login form
st.write('Please login')
mail_adress = st.text_input('E-Mail')
password = st.text_input('Password', type='password')
submit = st.button('Login')

# Check if user is logged in
if submit:
user_ = database[database['mail_adress'] == mail_adress].copy()
if len(user_) == 0:
st.error('User not found')
else:
if user_['mail_adress'].values[0] == mail_adress and user_['password'].values[0] == password:
st.session_state.user_state['mail_adress'] = mail_adress
st.session_state.user_state['password'] = password
st.session_state.user_state['logged_in'] = True
st.session_state.user_state['user_type'] = user_['user_type'].values[0]
st.session_state.user_state['mail_adress'] = user_['mail_adress'].values[0]
st.session_state.user_state['fixed_user_message'] = user_['fixed_user_message'].values[0]
st.write('You are logged in')
st.rerun()
else:
st.write('Invalid username or password')
elif st.session_state.user_state['logged_in']:
st.write('Welcome to the app')
st.write('You are logged in as:', st.session_state.user_state['mail_adress'])
st.write('You are a:', st.session_state.user_state['user_type'])
st.write('Your fixed user message:', st.session_state.user_state['fixed_user_message'])
if st.session_state.user_state['user_type'] == 'admin':
st.write('You have admin rights. Here is the database')
st.table(database)

hepsi bu kadar! umarım işinize yarar. eğer ilgilenirseniz, kullanıcı kaydı ve onaylanmasıyla ilgili de bir bölüm yazabilirim. o zamana dek kendinize iyi bakın! ♥️

--

--