@delsim My current goal is to decuple django-plotly-dash, this diagram should help at doing my project justice.
The problem I have with django-plotly-dash is the speed and I really see dash as being able to scale better as a separate entity with pages:
For example believe django-plotly-dash is running the dash app in a way that causes lag and I’m trying to keep dash a quick independent hosted frontend framework:
[Django->[<~[[Postgres]-> [Session]->Dash->html render]]
where I’m trying to setup:
[channels->app.py]<-~- <(0.0)> ~-~>[API<-Django<~>Postgres]
The only issue I’m currently facing with this setup is establishing a save of the validators I get returned from django, to be saved to a location within dash where the app keeps a fixed key, value storage. think Logged in = True or cookies → Sent to dash → Saved in sessions → if cookie in sessions → return logged in navbar else retun default navbar type of problem.
This is what I was able to build on the Django side of things is a basicAuth to manage the API Request and Login user authentication (working):
api = NinjaAPI()
class BasicAuth(HttpBasicAuth):
def authenticate(self, request, username, password):
# Request all Users on Application
users = User.objects.all()
# check username vs user in database
user_in_users = users.values_list('username', flat=True)
# print('user_in_users', list(user_in_users))
emails = users.values_list('email', flat=True)
# print('emails', list(emails))
# check if username or email in database return login or none
if username in list(user_in_users):
user = auth_authenticate(username=username, password=password)
if user is not None:
def cookie_save_user_id_function(request, current_time):
signer = Signer()
user_id = User.objects.get(username=username).id
signed_obj = signer.sign_object({'username': username, 'email': user.email,'id': user_id, 'logged_in': True, 'time_logged_in': current_time})
return {'username': username, 'email': user.email,'id': user_id, 'logged_in': True, 'time_logged_in': current_time, 'signed_obj': signed_obj}
user = authenticate(request, username=username, password=password)
if user is not None:
# login user
login(request, user)
central_time = pytz.timezone('US/Central')
current_time = datetime.now(central_time)
current_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
cookie = cookie_save_user_id_function(request, current_time)
# grab httpresponse
response = HttpResponse('You are logged in')
# set cookie
response.set_cookie('cookie', cookie['signed_obj'])
print(Color.GREEN+'Was able to login user, saved cookie of user_id to logged in', cookie)
print(Color.CYAN + 'User:', user, Color.RESET + f'Just logged into the application at: {current_time}')
# the credentials are valid
return cookie
else:
print(Color.RED +'User was found but not able to authenticate on django')
# the credentials are invalid
return None
else:
# the credentials are invalid
return None
elif username in list(emails):
print(Color.YELLOW + 'Wasn\'t able to find Username, trying email')
print(Color.GREEN + 'Email in database')
# gets username from email
u = User.objects.get(email=username)
def cookie_save_user_id_function(request, current_time):
signer = Signer()
user_id = User.objects.get(email=username).id
signed_obj = signer.sign_object(
{'username': username, 'email': user.email, 'id': user_id, 'logged_in': True,
'time_logged_in': current_time})
return {'username': u.username ,'email': username, 'id': user_id, 'logged_in': True, 'time_logged_in': current_time, 'signed_obj': signed_obj}
# checks authentication but doesn't login
# user = auth_authenticate(username=u, password=password)
# authenticate
user = authenticate(request, username=u, password=password)
if user is not None:
print('testing username')
print(u.username)
# login user
login(request, user)
central_time = pytz.timezone('US/Central')
current_time = datetime.now(central_time)
current_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
cookie = cookie_save_user_id_function(request, current_time)
# grab httpresponse
response = HttpResponse('You are logged in')
# set cookie
response.set_cookie('cookie', cookie['signed_obj'])
print(Color.GREEN + 'Was able to login user, saved cookie of user_id to logged in', cookie['signed_obj'])
print(Color.CYAN + 'User:', user, Color.RESET + f'Just logged into the application at: {current_time}')
# the credentials are valid
return cookie
else:
print(Color.RED + 'Username / Email not in database')
# the credentials are invalid
return None
This just checks username & password in the Django database and returns either dic or None. Then a data file in dash hosts a request that provides users username & password from a forum on dash side of the application that looks like this (working):
import requests
import colorama
def login(username, password):
# point to django domain for api login
url_login = f'http://{username}:{password}@127.0.0.1:8000/api/login'
response = requests.get(url_login, auth=(username, password))
if response.status_code == 200:
print(colorama.Fore.GREEN + f"Login Successful: {response.json()['httpuser']}")
print(colorama.Fore.YELLOW + f'{response.headers}')
print(colorama.Fore.RESET)
print(response.json())
return response.json()
else:
print(colorama.Fore.RED + f"Login Failed: {username}")
print(colorama.Fore.RESET)
return False
if __name__ == '__main__':
# login('pip@gmail.com', 'NeverTellMeTheOdds')
# login('pip', 'NeverTellMeTheOdds')
Then in my dash app.py file, I have the initial setup:
from flask import Flask
from uuid import uuid4
import dash
from dash.dependencies import Output, Input, State, DiskcacheManager
from dash_labs.session import session, setup_sessions
from dash_labs.session.backends.diskcache import DiskcacheSessionBackend
import dash_mantine_components as dmc
import dash_bootstrap_components as dbc
from dash_iconify import DashIconify
import diskcache
server = Flask(__name__)
launch_uid = uuid4()
app = Dash(
__name__,
assets_url_path="assets",
external_stylesheets=[
"https://use.fontawesome.com/releases/v6.2.1/css/all.css",
dbc.themes.SKETCHY,
],
use_pages=True,
server=server,
)
setup_sessions( app, DiskcacheSessionBackend(directory='./session-cache'))
.....html layout components for body.....
login_form = dbc.Form(
[
dbc.Col(
[
dmc.Stack(
children=[
dmc.TextInput(
label="Your Username or Email:",
style={"width": "100%"},
id="login-username",
),
],
)
]
),
dbc.Col(
[
dmc.PasswordInput(
label="Your password:",
style={"width": "100%"},
placeholder="Your password",
icon=DashIconify(icon="bi:shield-lock"),
id="login-password",
)
]
),
],
className="mb-5",
)
login_modal = dmc.Card(
children=[
dmc.CardSection(
dmc.Image(
src=dash.get_asset_url("gif/login_banner.gif"),
height=160,
)
),
dmc.Group(
[
dmc.Text("Access Account", weight=500),
],
position="apart",
mt="md",
mb="xs",
),
login_form,
dmc.Button(
"Login",
variant="light",
color="blue",
fullWidth=True,
mt="md",
radius="md",
id="login-button",
),
],
withBorder=True,
shadow="sm",
radius="md",
style={"width": 350},
id="login-modal-form",
)
login_to_account = dmc.Modal(
children=[
html.Div(id="welcome-back-alert"),
html.Div(id="User-Avatar"),
login_modal,
],
id="login-account-modal",
overflow="outside",
opened=False,
size="sm",
)
layout=html.Div([login_to_accoun, dmc.Button(
"Login",
variant="light",
color="blue",
fullWidth=True,
mt="md",
radius="md",
id="login-button",
),])
Lastly I setup a @app.callback to manage the adding user into a dash-hosted variable that will carry over multiple pages (NOT WORKING):
# Store Data through Callbacks
@app.callback(
# Output("store", "data"), hiding the modal on success
[
Output("welcome-back-alert", "children"),
Output("login-modal-form", "hidden"),
Output("User-Avatar", "children"),
],
[
Input("login-button", "n_clicks"),
Input("login-username", "value"),
Input("login-password", "value"),
],
prevent_initial_call=True,
)
def get_data(login_button, username, password):
if login_button is None:
pass
elif login_button:
if username and password is not None:
login_test = login(username, password)
if login_test:
utils.cookieJar.set(f"ActiveUsers", login_test['httpuser']['signed_obj'], path='/')
utils.add_user(cookie=login_test["httpuser"]["signed_obj"], user_id=login_test["httpuser"]["id"], username=login_test["httpuser"]["username"], email=login_test["httpuser"]["email"], time_logged_in=login_test["httpuser"]["time_logged_in"], avatar='https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fvignette.wikia.nocookie.net%2F2007scape%2Fimages%2F0%2F0a%2FWise_Old_Man.png%2Frevision%2Flatest%3Fcb%3D20171211175901&f=1&nofb=1&ipt=33ca4010bb53bcedb0cf0c745a4732c5dff3282fd9dbbf1dbc97efff2582ada4&ipo=images')
# todo: Added a cache option might use might remove depending on how I want to handle the user data
cache = diskcache.Cache(
f"./cache/accounts/{login_test['httpuser']['signed_obj']}"
)
DiskcacheManager(cache, cache_by=[lambda: launch_uid], expire=259200)
# Idk if i should use cache for this problem?? Think session would work 👀
# cache["username"] = login_test["HTTP user"]["username"]
# cache["email"] = login_test["httpuser"]["email"]
# cache["user_id"] = login_test["httpuser"]["id"]
# cache["logged_in"] = True
# cache["time_logged_in"] = login_test["httpuser"]["time_logged_in"]
# cache["signed_obj"] = login_test["httpuser"]["signed_obj"]
session.clear()
session.user = login_test["httpuser"]
print('Testing Session')
print(session)
print()
values = session.values
print('values')
session_value = session.user
print("testing session on login This is the session value")
print(session_value())
print(type(session_value()))
print(session_value()["username"])
welcome_back_alert = dmc.Alert(
f'Hey, {login_test["httpuser"]["username"]} you just logged in. Best way to take full advantage of this powerful Ai is to build up your account and we will help get you new upgrades, tips, tools & cheatcodes.',
title="Welcome Back to Maply.io",
color="green",
id="welcome-back-alert",
withCloseButton=True,
hide=False,
)
# TODO: Add a smart render for the logged in users avator to show the user's avitar is logged in
# currently hardcoded Wise Old Man
# saving it to store, and hiding the modal
return (
welcome_back_alert,
True,
html.Center(
html.Img(
src=dash.get_asset_url(
f"static/profile_images/Wise_Old_Man.png"
),
style={"width": "100px", "height": "250px"},
)
),
)
else:
pass
else:
pass
Hope that explains the situation more clearly. I’m able to retreave the django login authentication from the @callback but not able to setup much past that point. Figure what I need is a way to refer to session.user but when I attempt to open it i’m unable on anything other than the @callback
if cookie in session. user.keys:
return html.div(''logged in)
else:
return html.dive('Annonymous user')

Also, would like to thank @jinnyzor & @AnnMarieW helping me get this far. (Still Active Problem: 12-31-22)