Веб-приложение Dash: добавление блока кода портит все приложениеPython

Программы на Python
Anonymous
Веб-приложение Dash: добавление блока кода портит все приложение

Сообщение Anonymous »

Я создаю веб-приложение, используя Python и Dash. Кажется, все идет хорошо, за исключением случая, когда я добавляю последнюю функцию обратного вызова add_new_parcel_submit для обновления моей базы данных. Когда я добавляю это, страница входа не отображается, а панель навигации не реагирует на ссылки изменения.
Вот мой index.py:

Код: Выделить всё

app.layout = html.Div(
[
# Location Variable -- contains details about the url
dcc.Location(id='url', refresh=True),

# LOGIN DATA
# 1) logout indicator, storage_type='session' means that data will be retained
#  until browser/tab is closed (vs clearing data upon refresh)
dcc.Store(id='sessionlogout', data=True, storage_type='session'),

# 2) current_user_id -- stores user_id
dcc.Store(id='currentuserid', data=-1, storage_type='session'),

# 3) currentrole -- stores the role
# we will not use them but if you have roles, you can use it
dcc.Store(id='currentrole', data=-1, storage_type='session'),

# Adding the navbar
html.Div(
cm.navbar,
id='navbar_div'
),

# Page Content -- Div that contains page layout
html.Div(id='page-content', style=CONTENT_STYLE),

]
)

@app.callback(
[
Output('page-content', 'children'),
Output('sessionlogout', 'data'),
Output('navbar_div', 'className'),
],
[
# If the path (i.e.  part after the website name;
# in url = youtube.com/watch, path = '/watch') changes,
# the callback is triggered
Input('url', 'pathname')
],
[
State('sessionlogout', 'data'),
State('currentuserid', 'data'),
]
)

def displaypage (pathname,
sessionlogout, userid):
ctx = dash.callback_context
if ctx.triggered:
eventid = ctx.triggered[0]['prop_id'].split('.')[0]

else:
raise PreventUpdate

if eventid == 'url':
if userid < 0: # if logged out
if pathname == '/':
returnlayout = login.layout
elif pathname == '/signup':
returnlayout = signup.layout
else:
returnlayout = '404: request not found'

else:
if pathname == '/logout':
returnlayout = login.layout
sessionlogout = True

elif pathname == '/' or pathname == '/home':
# From the imported module 'home', we get the layout variable
returnlayout = home.layout

elif pathname == '/parcel_management':
returnlayout = parcel_management.layout

elif pathname == '/parcel_management/add_new_group':
returnlayout = add_new_parcel_group.layout
elif pathname == '/parcel_management/add_new_parcel':
returnlayout = add_new_parcel.layout
elif pathname == '/parcel_management/update_parcel_group':
returnlayout = update_parcel_group.layout
elif pathname == '/parcel_management/update_parcel_status':
returnlayout = update_parcel_status.layout

elif pathname == '/dashboard':
returnlayout = dashboard.layout

elif pathname == '/parcel_forecast':
returnlayout = parcel_forecast.layout

else:
returnlayout = '404: request not found'

# decide sessionlogout value
logout_conditions = [
pathname in ['/', '/logout'],
userid == -1,
not userid
]
sessionlogout = any(logout_conditions)

# hide navbar if logged-out;  else, set class/style to default
navbar_classname = 'd-none' if sessionlogout else ''

return [returnlayout, sessionlogout, navbar_classname]
else:
raise PreventUpdate

if __name__ == '__main__':
webbrowser.open('http://127.0.0.1:8050/', new=0, autoraise=True)
app.run_server(debug=False)

вот мой логин.py

Код: Выделить всё

from app import app
from apps import dbconnect as db

layout = html.Div(
[
html.H2('Please Login'),
html.Hr(),
dbc.Alert('Username or password is incorrect.', color="danger", id='login_alert',
is_open=False),
dbc.Row(
[
dbc.Label("Username", width=2),
dbc.Col(
dbc.Input(
type="text", id="login_username", placeholder="Enter username"
),
width=6,
),
],
className="mb-3",
),
dbc.Row(
[
dbc.Label("Password", width=2),
dbc.Col(
dbc.Input(
type="password", id="login_password", placeholder="Enter password"
),
width=6,
),
],
className="mb-3",
),
dbc.Button('Login', color="secondary", id='login_loginbtn'),
html.Hr(),
html.A('Signup Now!', href='/signup'),
]
)

@app.callback(
[
Output('login_alert', 'is_open'),
Output('currentuserid', 'data'),
],
[
Input('login_loginbtn', 'n_clicks'), # begin login query via button click
Input('sessionlogout', 'modified_timestamp'), # reset session userid to -1 if logged out
],
[
State('login_username', 'value'),
State('login_password', 'value'),
State('sessionlogout', 'data'),
State('currentuserid', 'data'),
State('url', 'pathname'),
]
)
def loginprocess(loginbtn, sessionlogout_time,

username, password,
sessionlogout, currentuserid,
pathname):

ctx = callback_context

if ctx.triggered:
openalert = False
eventid = ctx.triggered[0]['prop_id'].split('.')[0]
else:
raise PreventUpdate

if eventid == 'login_loginbtn': # trigger for login process

if loginbtn and username and password:
sql = """SELECT user_id
FROM users
WHERE
user_name = %s AND
user_password = %s AND
NOT user_delete_ind"""

# we match the encrypted input to the encrypted password in the db
encrypt_string = lambda string: hashlib.sha256(string.encode('utf-8')).hexdigest()

values = [username, encrypt_string(password)]
cols = ['userid']
df = db.querydatafromdatabase(sql, values, cols)

if df.shape[0]: # if query returns rows
currentuserid = df['userid'][0]
else:
currentuserid = -1
openalert = True

elif eventid == 'sessionlogout' and pathname == '/logout': # reset the userid if logged out
currentuserid = -1

else:
raise PreventUpdate

return [openalert, currentuserid]

@app.callback(
[
Output('url', 'pathname'),
],
[
Input('currentuserid', 'modified_timestamp'),
],
[
State('currentuserid', 'data'),
]
)
def routelogin(logintime, userid):
ctx = callback_context
if ctx.triggered:
if userid >  0:
url = '/home'
else:
url = '/'
else:
raise PreventUpdate
return [url]
вот мой update_parcel_status.py

Код: Выделить всё

dash.register_page(__name__, path='/')

layout = dbc.Container([
html.H1("Update Parcel Status"),
dbc.Form([
dbc.CardGroup([  # Use CardGroup instead of FormGroup
dbc.Label("Parcel ID*"),
dcc.Dropdown(
id='parcel-id',
placeholder="Select Status",
style={'width': '100%'}
),
]),
dbc.CardGroup([  # Use CardGroup instead of FormGroup
dbc.Label("Status*"),
dcc.Dropdown(
id='status-id',
placeholder="Select Status",
style={'width': '100%'}
),
]),
dbc.CardGroup([  # Use CardGroup instead of FormGroup
dbc.Label("Location"),
dbc.Input(type="text", id="location"),
]),
html.Br(),
dbc.Button("Update Status", id="update-button", color="primary"),
html.Div(id='output-container-button'),  # Placeholder for callback output
]),
dcc.Interval(
id='interval-component',
interval=60000,  # in milliseconds
n_intervals=0
)
], fluid=True)

@app.callback(
Output('status-id', 'options'),
[Input('interval-component', 'n_intervals')]
)
def update_status_options(n):
print("Callback1")  # Debug statement to check if callback is triggered
try:
# Fetch data from the parcelstatus_mapping table
query = """
SELECT status_id, status_desc
FROM parcelstatus_mapping;
"""
df = db.querydatafromdatabase(query, values=[], dfcolumns=['status_id', 'status_desc'])
# print (df)
# Convert DataFrame to a list of dictionaries suitable for dropdown options
options = [{'label': desc, 'value': str(status_id)} for status_id, desc in zip(df['status_id'], df['status_desc'])]

except Exception as e:
print(f"Error fetching data for status options: {e}")
options = []

return options

@app.callback(
Output('parcel-id', 'options'),
[Input('interval-component', 'n_intervals')]
)
def update_parcel_options(n):

print("Callback2")  # Debug statement to check if callback is triggered
try:
# Fetch data from the parcel_status table

# print('a')

query = """
SELECT parcel_id
FROM parcel_status;
"""

df = db.querydatafromdatabase(query, values=[], dfcolumns=['parcel_id'])

# Convert DataFrame to a list of dictionaries suitable for dropdown options
options = [{'label': str(parcel_id), 'value': str(parcel_id)} for parcel_id in df['parcel_id']]
except Exception as e:
print(f"Error fetching data for parcel options: {e}")
options = []

return options

@app.callback(
Output('output-container-button', 'children'),
[Input('update-button', 'n_clicks'),
Input('url', 'pathname')],
[State('parcel-id', 'value'),
State('location', 'value')]

)
def add_new_parcel_submit(n_clicks, parcel_id, location, pathname):
if pathname != '/parcel_management/update_parcel_status':
raise PreventUpdate  # Callback only runs when URL matches '/parcel_management/update_parcel_status'

if not n_clicks:
raise PreventUpdate
# return [html.Div([f"Parcel ID: {parcel_id}, Location: {location}"])]
print("Callback triggered with n_clicks:", n_clicks)  # Debug statement to check if callback is triggered
if not n_clicks:
raise PreventUpdate

alert_open = True
alert_color = 'danger'
alert_text = 'Failed to add new parcel.'
modal_open = False

if not all([parcel_id,  location]):
alert_text = 'Check your inputs.  Please fill in all the required fields.'
print("Not all fields filled:", parcel_id,  location)  # Debug statement for incomplete fields
else:
try:
# Constructing the SQL query
sql = '''
INSERT INTO parcel_status (parcel_id,  update_timestamp, location)
'''
# Adding the values to the values list
values = [parcel_id, 1, datetime.now(), location]
print("SQL values:", values)  # Debug statement for SQL values

sql += ') VALUES (' + ', '.join(['%s'] * len(values)) + ')'
print("SQL query:", sql)  # Debug statement for constructed SQL query

# db.modifydatabase(sql, values)
print("Database modification successful")  # Debug statement for successful database modification

alert_open = True
alert_color = 'success'
alert_text = 'New parcel added successfully.'
modal_open = True
except Exception as e:
alert_text = f'Failed to add new parcel: {str(e)}'
print("Exception occurred:", e)  # Debug statement for exception

return [html.Div(alert_text, className=f'alert alert-{alert_color}', role='alert'), modal_open]
Я попробовал проверить идентификаторы, вроде все правильно. я пытался установить предотвращение обновления для
add_new_parcel_submit, чтобы он вызывался только тогда, когда он находится в этом URL-адресе, но добавление этого обратного вызова все равно нарушает код, даже если он находится за пределами этого URL-адреса. Можете ли вы помочь, пожалуйста? Я застрял здесь на несколько дней, хаха

Подробнее здесь: https://stackoverflow.com/questions/784 ... entire-app

Вернуться в «Python»