Django and Dash - ead's Method

I cloned the dash-django-example from git hub into my Virtualenv and run: python manage.py run server and got the AttributerError:
File “/Users/pzhang/dash-django-example/dash_test/viz/router.py”, line 14, in
routes = {f"{app.url_base_pathname}{path}": layout for path, layout in pages}
AttributeError: ‘Dash’ object has no attribute ‘url_base_pathname’

I got the same if I run: python manage.py migrates

Please help me to know what I did wrong.

Thanks.
Pengchu

Hey Ned!!!

Thank you very much for your solution!!! Its very intuitive and as you mentioned, the dash app doesn’t get reloaded every time the dispatcher runs. I have a question in regard to the code. How you would handle this code fashion, if you were going to use data from the Django models instead of generating random numbers as input to the plots??

I believe it’s fairly straightforward to access your Django models from any other app. You first need to make sure your Django app is initialised (since you won’t be interacting with manage.py, which does all that for you). This gist, has instructions for how to do that: https://gist.github.com/amatellanes/11119500. You would need to put that at the top of your Dash app.

Then in your Dash app just import your models as you normally would in the Dango app.

Check the requirements given. I suspect you have all the latest versions for dash, dash renderer, dash components, and dash html. The code doesn’t work with the latest versions.

The trouble I have is what happens when one has user logins involved. How would you separate the data based on the current user, if one can’t pass the request object to obtain the current user’s id or username?? I’ve tried by passing User.username, but that’s a Deffered Attribute, and doesn’t return the logged in user.

Ead’s method in this case works, because a request is passed into the create_app . I did try this, and its bloody slow , because of the app reload, and even slower when callbacks are involved. I really prefer your method any day, but its become a conundrum for days now trying to find a hack to get the User’s id or username without involving the request object

Ah that does complicate matters doesn’t it. I can’t think of anything off the top of my head, but I don’t really have my head in the Django space these days, so might need to ponder a pit.

Yep, a very delicate problem , lol. I’ve been pondering over this for some days already. Thanks a lot though for your quick response though !! _/\ _

Hi, I’m also interested in this part and didn’t get the time to tinker with it.
Have you found a solution? Did you try @delism 's implementation and rely on Django for authentication/authorization ?
Using @login_required decorator ?I used the same approach in flask and I’m working on migrating to Django.

Hi

I’m using Django-plotly-Dash to integrate my charts with my Django app.

The csv data that my charts are based on get updated every day (by a stand-alone script). What I’ve noticed is that when the charts are viewed they are not picking up the new data. Currently I am restarting the server each day to force the charts to pick up the latest day’s data but this is not ideal for a number of reasons.

I assume this falls under the “live updating” mentioned in DPD docs and the solution is Redis from what I recall. But I’m on Python Anywhere which doesn’t have Redis.

They have redis lite - should that work in the same way?

Or is there another solution that would avoid having to restart the server?

Thanks

Hard to be sure without sight of the code, but from the sound of it the only way your standalone script runs at the moment is when you (re)start your server. To get it to run more often, you need to provide some way of invoking it, such as through a callback.

If you have a regular update schedule then dcc.Interval is going to be more than adequate; set the interval to be an acceptable amount of latency, say every few minutes, and use it to trigger the update. If your update script is particularly intensive then maybe also add some way of avoiding recalculation on each call.

The standalone script I referred to is a schedule task in python anywhere - it runs at 8am every day. It’s a once a day task as the APIs I seek data from are only updated daily.

The script is a number of modules like this in data_download.py:



def price_data():
    price_url = 'https://api.blockchain.info/charts/market-price?timespan=15years&start=2010-08-17&scale=1&format=csv&sampled=false'
    data = requests.get(price_url).content
    df_marketPrice = pd.read_csv(io.StringIO(data.decode('utf-8')), header=None, names=['Date', 'Price'] )
    df_marketPrice.to_csv('/home/chris/bitcoin/data/price_data.csv')

price_data()

This works and the csv gets refreshed to include yesterday’s data.

My chart app looks something like this:

import plotly.graph_objs as go
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
from django_plotly_dash import DjangoDash
from datetime import datetime, timedelta

app_name = 'chart1'

app = DjangoDash(name='chart1',
                app_name='chart1')

def get_figure():

    df_marketPrice = pd.read_csv('/home/chris/bitcoin/data/price_data.csv')

    x1 = df_marketPrice['Date']]
    y = df_marketPrice['Price']]

    trace1 = go.Scatter(
        x = x1,
        y = y,
        
    )

   figure = {
        'data' : [trace1],
        'layout' : go.Layout(
            )

    }

    return figure


app.layout = html.Div([
    dcc.Graph(
        id='chart',
        figure= get_figure(),
    ),
])

What I’m expecting to happen is every time someone views the chart it fetches the latest data in price_data.csv. What I’m experiencing is the csv is updated at 8am, but the chart is not showing any new data unless I restart the server.

(Just to be clear, I’m not expecting the chart to update automatically if someone happens to be viewing the chart when the new data is downloaded at 8am - just when they next refresh the page.)

Should this work as I’m expecting or am I missing something?

Your app.layout is only set when the module containing your app is loaded. If instead you set it equal to a function - similar to the last example in the tutorial - then it should be invoked each time a page containing an app is rendered.

1 Like

Amazing thank you - I will give this a go!

Unfortunately this doesn’t appear to have worked. Had a look just now - data is in the csv up to and including 20 September, but the charts are showing latest data as 19 September. Refreshed the server and now they are showing latest data as 20 September.

I have changed this:

app.layout = html.Div([
    dcc.Graph(
        id='chart',
        figure= get_figure(),
    ),
])

to this:


def serve_layout():
    return html.Div([
                dcc.Graph(
                    id='chart',
                    figure= get_figure(),
                ),
            ])


app.layout = serve_layout()

Ah I’ve just seen that it needs to be

app.layout = serve_layout and not serve_layout() so will give that a go

That would make more sense. Your layout function will be called multiple times - roughly once per callback - so I’d expect any issue to be around the function being invoked too many times - you will probably want a way of making get_figure not do unnecessary work on each call.

Hi I am trying to run your code and this happens.

If i type http://127.0.0.1:8000/viz it says its “The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.”

Sorry I am probably being very stupid!