基于python 的股市行情查询系统开发(三)

一、django框架构建项目

1)下载django

pip install django ''' 使用清华源加快下载速度'''

2)构建项目

选择一个文件目录,在目录下输入:django-admin startproject 项目名

django-admin startproject stock

文件目录如下:
在这里插入图片描述
在cmd项目根目录下输入后面可以加ip:端口号

在这里插入图片描述
出现以下信息代表项目已经运行成功:
在这里插入图片描述
浏览器输入127.0.0.1:8000(默认端口):
在这里插入图片描述
这样我们的项目的基本框架就已经搭建好了。

3)新建model模型

stock目录下输入:

python .\manage.py startapp stocklist

在生成的文件目录中的model文件中对model对象的数据类型进行定义:

from django.db import models

# Create your models here.
class Stock(models.Model):
    stockcode = models.CharField(max_length=20) '''股票代码'''
    stockname = models.CharField(max_length=20) '''股票名称'''

构建后别忘了在stock目录下的setting.py文件的INSTALLED_APPS中加入stocklist。

......
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'stocklist'
]
......

之后输入如下,用以在数据库中建立stocklist表用于获取之前存储在csv文件中的沪深A股的股票代码和名称:
在这里插入图片描述
我使用的是默认的数据库sqlite3,这里vscode的插件可以对数据库进行可视化,在market中搜索sqlite即可:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看到数据库中的表已经构建成功了。
好了,之后我们就可以把csv数据导入数据库了。
在stock目录下新建accessdata文件。

# /stock/accessdata.py
from stocklist.models import Stock
import csv
from django.http import HttpResponse
from django.views.decorators.csrf import  csrf_exempt 

@csrf_exempt
def write_stock_list(self):
    with open('D:\\股票数据\\stocklist.csv','r',encoding='utf-8') as f:
        reader = csv.reader(f)
        csv_list = []
        for row in reader:
            
            if tuple([row[0]]) not in csv_list:
                obj = Stock( stockcode= row[1],stockname = row[0])
                csv_list.append(obj)
        Stock.objects.bulk_create(csv_list)
    return HttpResponse("OK")

在url.py中加入该方法请求:



# /stock/urls.py
from . import accessdata
from django.conf.urls import url

urlpatterns = [

    url('write/',accessdata.write_stock_list),
]

再次运行一下:在这里插入图片描述
查看数据库:
在这里插入图片描述
OK,准备工作完成。

二、获取实时数据

如何获取到实时的股票数据呢?非常简单,东方财富网就可以。目前的链接为http://push2.eastmoney.com/api/qt/stock/get?fields=f43,f44,f45,f46,f47,f48,f49,f50,f51,f52,f57,f58,f71,f116,f117,f60,f162,f163,f164,f167,f168,f170,f173&secid=股票代码

需要注意的是股票代码前要加1. 代表上海 0.代表深圳。

这里使用grequests来加快请求的速度:获取1700多支的数据大约要5秒钟,

@csrf_exempt
def get_allcode(request):   #获取所有的实时股票信息
    QuerySet = Stock.objects.all()
    list =[]
    dictlist = []
    stockdict = {}
    for stock in QuerySet:
        list.append(get_url+"1."+stock.stockcode)
    '''url=http://push2.eastmoney.com/api/qt/stock/get?fields=f43,f44,f45,f46,f47,f48,f49,f50,f51,f52,f57,f58,f71,f116,f117,f60,f162,f163,f164,f167,f168,f170,f173&secid='''
    tasks = [grequests.get(u) for u in list] 
    datalist = grequests.map(tasks,size= 2000)
    for data in datalist:
        dict ={'data2':json.loads(data.text)}
        dictlist.append(accessformat(dict))
    for i in range(len(dictlist)):
        stockdict[i] = dictlist[i]

    return HttpResponse(json.dumps(stockdict))

注意不要忘记在url.py加入此路径进行匹配:

urlpatterns = [
...
url('get_allcode/',accessdata.get_allcode),
...
]

跑一下看看:
在这里插入图片描述
其实数据已经获取到了,但还是unicode编码,我们需要将其进行转化一下。
另:使用grequests是会报如下异常:
在这里插入图片描述
但是不影响程序运行,有没有同样使用的小伙伴告诉一下怎么解决啊啊
将数据进行处理一下:


def accessformat(LIST):
    stocknowdata = LIST['data2']['data']
    if(stocknowdata ==None):
        return 'None'
    listnow = list(stocknowdata.values())
    listnew = [listnow[10],listnow[11],listnow[0],listnow[1],
                listnow[21],listnow[2],listnow[3],listnow[12],
                listnow[8],listnow[9],listnow[4],listnow[5],
                listnow[6],listnow[7],listnow[13],listnow[14],
                listnow[15],listnow[16],listnow[17],listnow[18],
                listnow[12],listnow[20],listnow[22]]
    #print(listnew)
    label = ['股票代码','股票名称','最新价','最高价','涨跌幅','最低价','开盘价','昨收',
                '涨停','跌停','成交量(手)','成交额','外盘','量比','均价',
                '总市值','流通市值','市盈(动)','静市盈率','滚动市盈率','市净率',
                '换手率','ROE']
    #df = pd.DataFrame(columns=label)
    b=dict(zip(label,listnew))
    return b

打印看看:
在这里插入图片描述
可以看到数据其实是已经处理好的,就是传到前端时又转为unicode了。
这时候我们就需要vue来将数据显示一下了。

三、将数据实时显示在前端页面

下载npm后,进行vue脚手架的搭建:

npm  install -g vue-cli

之后进行一路选择默认后进入项目目录

npm install

安装完成后,输入

npm run serve

在这里插入图片描述
启动成功后,我们在index.html加入前端美化代码:
在这里插入图片描述

<!doctype html>
<html lang="en">

<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/4.7.0/css/font-awesome.css">
    <title>django vue stock</title>
</head>

<body>
    
        <div id="app"></div>
    </div>

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.4.1/dist/jquery.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>

</html>

src目录下的vue文件名修改为Container.vue

<template>
<div class="container">
      <nav class="navbar navbar-expand-lg navbar-light bg-warning">
        <a class="navbar-brand" href="#">Menu</a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
        </button>
      
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
          <ul class="navbar-nav mr-auto">
            <li class="nav-item active">
              <a class="nav-link" href="#">A Stock <span class="sr-only">(current)</span></a>
            </li>
            <li class="nav-item active">
              <a class="nav-link" href="#">find other</a>
            </li>
            <li class="nav-item dropdown">
              <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                Dropdown
              </a>
              <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                <a class="dropdown-item" href="#">Action</a>
                <a class="dropdown-item" href="#">Another action</a>
                <div class="dropdown-divider"></div>
                <a class="dropdown-item" href="#">Something else here</a>
              </div>
            </li>
            <li class="nav-item">
              <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
            </li>
          </ul>
          <form class="form-inline my-2 my-lg-0">
            <input v-model="stockcode" class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
            <button class="btn btn-outline-success my-2 my-sm-0" type="button" @click="getnewstock()">Search</button>
          </form>
        </div>
      </nav>
  <div class="row">

    
    <div class="col-md-12">
      <!-- 右边是博客内容表格部分 -->
      <table class="table table-bordered table-hover">
        <thead>
          <th class="text-center">stockcode</th>
          <th class="text-center">stockname</th>
          <th class="text-center">stocknow</th>
          <th class="text-center">stockhigh</th>
          <th class="text-center">stocklow</th>
          <th class='text-center'>stockopen</th>
          <th class='text-center'>stockchange</th>
          <th class='text-center'>stockyesday</th>
          <th class='text-center'>stockamount</th>
        </thead>
        <tbody>
       <!--    <tr>-->
         <tr v-for='stock in stocks' :key='stock.id' > 
            <td>{{stock.股票代码}}</td>
            <td>{{stock.股票名称}}</td>
            <td>{{stock.最新价}}</td>
            <td>{{stock.最高价}}</td>
            <td>{{stock.最低价}}</td>
            <td>{{stock.开盘价}}</td>
            <td>{{stock.涨跌幅}}</td>
            <td>{{stock.昨收}}</td>
            <td>{{stock.成交额}}</td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</div>
</template>

<script>
import axios from 'axios';
import Qs from 'qs';
export default {
  name: 'Container',

  props: {
  },
  data(){
    return{
      //base_url:'http://172.18.204.60:8000/api/stock/',
      stocks:null,
      url:'',
      title:'',
      content:'',
      stockcode:'',
    }
  },
  methods:{

   // getAll(){
   //   axios.get('http://localhost:8000/api/stock/')
     //   .then(res=>{
     //     this.stocks = res.data;
     //     this.url = '';
      //    this.title = ''
      //    this.content = ''
     //   });
    
    getnewstock(){
      if(this.stockcode=='')
      {
        axios({
          headers:{'Content-Type':'application/x-www-form-urlencoded'},
          method:'get',
          url :'http://localhost:8000/get_allcode/'

        }).then(res=>{
          this.stocks = res.data
          console.log(res.data)
        })

      }
      else
      {
      let data = {stockcode:this.stockcode}
        axios({
          headers:{'Content-Type':'application/x-www-form-urlencoded'},
          method:'post',
          url : 'http://localhost:8000/access_stock_code/',
          data :Qs.stringify(data)
        }).then(res=>{
          this.getnewdata(res.data)
          console.log(res.data)
        })
      }
    },

    getnewdata(stockcode){
      axios({
        headers:{'Content-Type':'application/x-www-form-urlencoded'},
        method:'get',
        url :'http://push2.eastmoney.com/api/qt/stock/get?fields=f43,f44,f45,f46,f47,f48,f49,f50,f51,f52,f57,f58,f71,f116,f117,f60,f162,f163,f164,f167,f168,f170,f173&secid='+stockcode,

      }).then(res=>{
        this.accessdata(res.data)
        console.log(res.data)
      })

    },

    accessdata(data){
      let data1= {data2 :data}
      axios({
        method:'post',
        url :'http://localhost:8000/accessdata/',
        data :JSON.stringify(data1)
      }).then(res=>{
        console.log(res.data)
        this.stocks = {stock:res.data}

  created(){
   // this.getAll();
   this.getnewstock();
  }
  }
}
</script>

<style scoped>

</style>

App.vue文件修改如下:

<template>
  <div id="app">
    <Container />
  </div>
</template>

<script>
import Container from './components/Container.vue'

export default {
  name: 'App',
  components: {
    Container
  }
}
</script>

main.js:


import { createApp } from 'vue'

import App from './App.vue'

createApp(App).mount('#app')

这里还有一个问题,我们使用的是前后端分离的项目模式,所以前端向后端请求会存在跨域问题,因此,在django中的settings.py中INSTALLED_APPS加入django-cores,MIDDLEWARE 中加入’corsheaders.middleware.CorsMiddleware’,‘corsheaders.middleware.CorsPostCsrfMiddleware’,再加入CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL =True即可

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',   
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'stocklist',
    'corsheaders',    #加入#
]

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

ROOT_URLCONF = 'stock.urls'
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL =True

ok,浏览器输入localhost:8080/
在这里插入图片描述
点击search
在这里插入图片描述
成功!可以看到数据已经实时地展现在首页上了

Logo

前往低代码交流专区

更多推荐