2023年7月15日 星期六

整合Dajngo和Dash的百香果交易行情展示網站

1.建置虛擬環境

mkvirtualenv passionfruit
pip install django
django-admin startproject passionfruitproj
cd passionfruitproj
python manage.py startapp passionfruitapp


2.編輯settinds.py設定passionfruitapp以及templates的目錄。
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
"""
Django settings for passionfruitproj project.

Generated by 'django-admin startproject' using Django 4.2.3.

For more information on this file, see
https://docs.djangoproject.com/en/4.2/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.2/ref/settings/
"""
import os
from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-k)=rfq8qzy1bynbyxf#h&baf9^&6o32pjb!!9dp$wrf=5-6_w_'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django_plotly_dash.apps.DjangoPlotlyDashConfig',
    'passionfruitapp',
]
X_FRAME_OPTIONS = 'SAMEORIGIN'

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'passionfruitproj.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'passionfruitproj.wsgi.application'


# Database
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}


# Password validation
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/4.2/topics/i18n/

LANGUAGE_CODE = 'zh-Hant'

TIME_ZONE = 'Asia/Taipei'

USE_I18N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/

STATIC_URL = 'static/'

# Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

STATICFILES_DIRS = [
  os.path.join(BASE_DIR, 'static'),
 ]

3.修改urls.py程式

!-- HTML generated using hilite.me -->
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
"""
URL configuration for passionfruitproj project.

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/4.2/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from passionfruitapp.views import home
from django.conf.urls import include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', home),
    path('django_plotly_dash/', include('django_plotly_dash.urls')),
]

4.修改views.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
from django.shortcuts import render
import pandas as pd
from dash import Dash, dcc, html
from django_plotly_dash import DjangoDash

# 創建交易數據
data = {
    '交易日期': ['085年', '086年', '087年', '088年', '089年', '090年', '091年', '092年', '093年', '094年',
                '095年', '096年', '097年', '098年', '099年', '100年', '101年', '102年', '103年', '104年',
                '105年', '106年', '107年', '108年', '109年', '110年', '111年', '112年'],
    '平均價': [24.8, 20.2, 24.1, 22.4, 23.1, 21.6, 22.3, 20.6, 22.9, 30.5, 25.5, 26.2, 26.7, 28.5, 29.7,
              24.8, 40.2, 39.8, 38.9, 37.1, 54.3, 48.8, 36.7, 47.4, 38.1, 43.0, 47.2, 54.2],
    '交易量': [1239371.0, 1648762.0, 1558996.0, 1759508.7, 1720805.0, 2162901.8, 2208902.0, 2150995.0,
              2157947.5, 2562379.4, 2840040.5, 2650637.8, 3195998.0, 3403571.0, 3570338.4, 4633125.5,
              4088659.4, 4525197.0, 6579937.4, 8522771.8, 8860383.9, 8916824.2, 11390231.7, 9734445.9,
              9878849.5, 8889654.6, 9334203.0, 3084173.7]
}

df = pd.DataFrame(data)
# 創建Dash應用
app = DjangoDash('PassionFruit')  # replaces dash.Dash

# 设置应用布局
app.layout = html.Div(children=[
    html.H1(children='百香果產品交易價量走勢圖'),
    dcc.Graph(
        id='price-volume-chart',
        figure={
            'data': [
                {'x': df['交易日期'], 'y': df['平均價'], 'type': 'line', 'name': '平均價', 'yaxis': 'y1'},
                {'x': df['交易日期'], 'y': df['交易量'], 'type': 'bar', 'name': '交易量', 'yaxis': 'y2'}
            ],
            'layout': {
                'title': '百香果產品交易價量走勢',
                'xaxis': {'title': '交易日期'},
                'yaxis': {'title': '平均價格', 'side': 'left', 'showgrid': False},
                'yaxis2': {'title': '交易量', 'side': 'right', 'showgrid': False, 'overlaying': 'y'},
            }
        }
    )
])

def home(request):
    return render(request, 'index.html', locals())

5.在passionfruitapp目錄下建立templates目錄,並新增一個index.html。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<html>
<head>
{% load plotly_dash %}

</head>
<body>

    {% plotly_app name="PassionFruit" %}

</body>
</html>

執行結果:

很可惜沒看到全圖樣貌,但可以用右邊捲動軸來看圖。

沒有留言:

張貼留言