AttributeError:“系列”对象没有属性“翻译”

时间:2018-08-12 10:27:47

标签: python flask-sqlalchemy

我正在按烧瓶开发小型CRM系统。现在,当我通过邮递员测试import_data.py时出现错误。真的不知道如何解决此问题。...我已经测试过将数据手动插入MySQL DB,并且可以正常工作。我不确定是哪一部分导致了问题,但我认为问题应该出在app.py或import_data.py,或者是我在Postman下测试的方式。这是我的项目的结构。

项目结构

这是app.py的编码

# -*- coding:utf-8 -*-
import pandas as pd
from flask import Flask, request
import logging; logging.basicConfig(level=logging.INFO)
import asyncio, os, json, time
from datetime import datetime
from util.template import ReponseTemplate
from aiohttp import web
from api import import_data, statistic, general_search
import sys
import traceback
from werkzeug.utils import secure_filename

# UPLOAD_FOLDER = '/path/to/the/uploads'
ALLOWED_EXTENSIONS = set(['xlsx', 'xls', 'csv'])
app = Flask(__name__)
# app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = 60 * 1024 * 1024

app.register_blueprint(import_data.mold, url_prefix='/api/import')
app.register_blueprint(general_search.mold, url_prefix='/api/show')
app.register_blueprint(statistic.mold, url_prefix='/api/check')


def allowed_file(filename):
    return '.' in filename and \
        filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS


@app.route('/upload', methods=['POST'])
def upload_excel():
    f = request.files['file']
    if f and allowed_file(f.filename):
        filename = secure_filename(f.filename)
        f.save(secure_filename(filename))
        # file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
        df = pd.read_excel(f)
        return ReponseTemplate().jsonify_ok_df_response(df)


@app.errorhandler(Exception)
def default_exception_handler(error):
    exc_type, exc_value, exc_traceback = sys.exc_info()
    trace = traceback.format_exception(exc_type, exc_value,
                                       exc_traceback)
    code = 401 if 'auth' in str(type(error)).lower() else 400
    print('[Error]:{}'.format(trace))

    return ReponseTemplate().jsonify_bad_response(str(error), code)




if __name__ == '__main__':

    app.run(debug=True)

这里是template.py的编码

import math

import simplejson as json
from flask import jsonify


class ResponseTemplate():
    response_template = {
        "success": "Success",
        "data": [],
        "meta": {
            "code": 200,
            "message": "OK",
            "errors": [],
            "pages": {}
        }
    }

    def jsonify_ok_row_response(self, rows, page_index=1, page_size=10, total=0):
        self.response_template['meta']['errors'] = []
        self.response_template['meta']['code'] = 200

        if rows is None:
            self.response_template['data'] = []
        else:
            json_result = [{key.lower(): value for (key, value) in row.items()} for row in rows]
            self.response_template['data'] = json_result

        pages = {"limit": 1, "page": 1, "total": 0, "count": 0}
        pages['limit'] = page_size
        pages['page'] = page_index
        pages['count'] = int(math.ceil(float(total) / page_size))
        pages['total'] = total if total > 0 else len(self.response_template['data'])
        self.response_template['meta']['pages'] = pages

        return jsonify(self.response_template)

    def jsonify_ok_list_response(self, data, page_index=1, page_size=10, total=0):
        self.response_template['meta']['errors'] = []
        self.response_template['meta']['code'] = 200

        if data is None:
            self.response_template['data'] = []
        else:
            json_result = [{key.lower(): value for (key, value) in d.items()} for d in data]
            self.response_template['data'] = json_result

        pages = {"limit": 1, "page": 1, "total": 0, "count": 0}
        pages['limit'] = page_size
        pages['page'] = page_index
        pages['count'] = int(math.ceil(float(total) / page_size))
        pages['total'] = total if total > 0 else len(self.response_template['data'])
        self.response_template['meta']['pages'] = pages

        return jsonify(self.response_template)

    def jsonify_ok_str_response(self, json_str, page_index=1, page_size=10, total=0):
        self.response_template['meta']['errors'] = []
        self.response_template['meta']['code'] = 200

        if json_str is None or json_str == '':
            self.response_template['data'] = []
        else:
            json_result = json.loads(json_str)
            self.response_template['data'] = json_result

        pages = {"limit": 1, "page": 1, "total": 0, "count": 0}
        pages['limit'] = page_size
        pages['page'] = page_index
        pages['count'] = int(math.ceil(float(total) / page_size))
        pages['total'] = total if total > 0 else len(self.response_template['data'])
        self.response_template['meta']['pages'] = pages

        return jsonify(self.response_template)

    def jsonify_ok_obj_response(self, obj, page_index=1, page_size=10, total=0):
        self.response_template['meta']['errors'] = []
        self.response_template['meta']['code'] = 200

        if obj is None:
            self.response_template['data'] = []
        else:
            self.response_template['data'] = obj

        pages = {"limit": 1, "page": 1, "total": 0, "count": 0}
        pages['limit'] = page_size
        pages['page'] = page_index
        pages['count'] = int(math.ceil(float(total) / page_size))
        pages['total'] = total if total > 0 else len(self.response_template['data'])
        self.response_template['meta']['pages'] = pages

        return jsonify(self.response_template)

    def jsonify_ok_df_response(self, df, page_index=1, page_size=10, total=0, orient='records'):
        self.response_template['meta']['errors'] = []
        self.response_template['meta']['code'] = 200

        if df is None:
            self.response_template['data'] = []
        else:
            json_str = df.to_json(orient=orient)
            json_result = json.loads(json_str)
            self.response_template['data'] = json_result

        pages = {"limit": 1, "page": 1, "total": 0, "count": 0}
        pages['limit'] = page_size
        pages['page'] = page_index
        pages['count'] = int(math.ceil(float(total) / page_size))
        pages['total'] = total if total > 0 else len(self.response_template['data'])
        self.response_template['meta']['pages'] = pages

        return jsonify(self.response_template)

    def jsonify_bad_response(self, errors, code):
        self.response_template['meta']['errors'] = errors
        self.response_template['meta']['code'] = code
        self.response_template['data'] = []
        self.response_template['meta']['pages'] = {}
        return jsonify(self.response_template)

这是import_data.py

# -*- coding:utf-8 -*-

import json
from flask import Blueprint, request
from util.template import ResponseTemplate
import logging
from model.dbmodel import Customers, Transaction
from sqlalchemy.orm import mapper, sessionmaker
from sqlalchemy import create_engine
import config
import pandas as pd
from sqlalchemy.ext.declarative import declarative_base


mold = Blueprint('import', __name__)

conn = config.conn_str
Base = declarative_base()


@mold.route('/customer', methods=['POST'])
def import_customer():
    engine = create_engine(conn)
    # df = pd.read_excel(request.data)
    cum = json.loads(request.data)
    if cum is None:
        logging.info("Not able to get the data from request.")
    # Customers.name = cum.get('name', '')
    # Customers.address = cum.get('address', '')
    # Customers.phone = cum.get('phone', '')
    # Customers.source_from = cum.get('source_from', '')
    name = cum.get('name', '')
    address = cum.get('address', '')
    phone = cum.get('phone', '')
    source_from = cum.get('source_from', '')

    Base.metadata.create_all(engine)

    Session_class = sessionmaker(bind=engine)  
    session = Session_class() 
    # generate the object for the data we would like to insert
    customer_obj = Customers(name=name, address=address,
                             phone=phone, source_from=source_from)
    # nothing yet, print to check
    print(customer_obj.id, customer_obj.name,
          customer_obj.phone, customer_obj.address,
          customer_obj.source_from)

    session.add(customer_obj)  # put the data obj into session, will insert together
    # check again. but still nothing yet....
    print(customer_obj.id, customer_obj.name,
          customer_obj.phone, customer_obj.address,
          customer_obj.source_from)
    session.commit()  # insert the data into database
    return ResponseTemplate.jsonify_ok_obj_response(customer_obj)


@mold.route('/transactions/<file_name>', methods=['POST'])
def import_transactions(file_name):
    engine = create_engine(conn)

    #df = pd.read_excel(request.data)
    #tran = json.loads(request.data)
    tran = pd.read_excel(file_name)
    if tran is None:
        logging.info("Not able to get the data from file.")
    name = tran.get('name', '')
    # print(name)
    date = tran.get('date', '')
    # print(date)
    product = tran.get('product', '')
    # print(product)
    quantity = tran.get('quantity', '')
    amount = tran.get('amount', '')

    Base.metadata.create_all(engine)

    Session_class = sessionmaker(bind=engine)  
    session = Session_class()  
    # generate the object for the data we would like to insert

    transaction_obj = Transaction(name=name, date=date, product=product,
                                  quantity=quantity, amount=amount)
    # print to check, there should be nothing yet
    print(transaction_obj.name, transaction_obj.product, transaction_obj.date,
          transaction_obj.quantity, transaction_obj.amount)
    session.add(transaction_obj)  # put the data into obj
    # check again, there should be nothing still
    print(transaction_obj.name, transaction_obj.product, transaction_obj.date,
          transaction_obj.quantity, transaction_obj.amount)
    session.commit()  # insert
    return ResponseTemplate.jsonify_ok_obj_response(transaction_obj)

此处为数据库中的两个表编码:dbmodel.py

# -*- coding:utf-8 -*-

from sqlalchemy import Table, MetaData, Column, Integer, String, DATE, DECIMAL, ForeignKey, DateTime
from sqlalchemy.orm import mapper
from sqlalchemy.ext.declarative import declarative_base

#metadata = MetaData()
Base = declarative_base()

# customers = Table('customers', metadata,
#                   Column('id', Integer, primary_key=True, autoincrement=True),
#                   Column('name', String(20)),
#                   Column('phone', String(20)),
#                   Column('address', String(45)),
#                   Column('source_from', String(45))
#                   )


class Customers(Base):
    # def __init__(self, id, name, phone, address, source_from):
    #     self.id = id
    #     self.name = name
    #     self.phone = phone
    #     self.address = address
    #     self.source_from = source_from
    #
    # def __repr__(self):
    #     return "<Customer(name='%s', phone='%s', address='%s', " \
    #            "source_from='%s')" % (self.name, self.phone, self.address,
    #                                   self.source_from)
    __tablename__ = 'customers'
    id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
    name = Column(String(20))
    phone = Column(String(20))
    address = Column(String(45))
    source_from = Column(String(45))

# mapper(Customers, customers)


# the table metadata is created separately with the Table construct,
# then associated with the User class via the mapper() function


# transaction = Table('transaction', metadata,
#                     Column('id', Integer, primary_key=True, autoincrement=True),
#                     Column('name', String(20)),
#                     Column('date', DateTime),
#                     Column('product', String(20)),
#                     Column('quantity', Integer),
#                     Column('amount', DECIMAL(2))
#                     )


class Transaction(Base):
    # def __init__(self, id, name, date, product, quantity, amount):
    #     self.id = id
    #     self.name = name
    #     self.date = date
    #     self.product = product
    #     self.quantity = quantity
    #     self.amount = amount
    #
    # def __repr__(self):
    #     return "<Transaction(name='%s', date='%s', product='%s'," \
    #            "quantity='%s', amount='%s')>" % (self.name, self.date,
    #                                              self.product, self.quantity,
    #                                              self.amount)
    __tablename__ = 'transaction'
    id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
    name = Column(String(20))
    date = Column(DATE)
    product = Column(String(20))
    quantity = Column(Integer)
    amount = Column(Integer)

# mapper(Transaction, transaction)

下面的链接是我测试api后邮递员结果的屏幕截图:

邮递员测试结果

以下是我用邮递员测试api后来自pycharm的错误消息:

     [Error]:['Traceback (most recent call last):\n', '  File 
     "/Applications/anaconda3/envs/Fruit/lib/python3.6/site-packages/flask/app.py", line 1813, in full_dispatch_request\n    rv = self.dispatch_request()\n', 
'  File "/Applications/anaconda3/envs/Fruit/lib/python3.6/site-packages/flask/app.py", line 1799, in dispatch_request\n    

return self.view_functionsrule.endpoint \ n','文件“ /Users/chenneyhuang/PycharmProjects/Fruit/api/import_data.py”,第91行,位于import_transactions \ n session.commit()#insert \ n', '文件“ /Applications/anaconda3/envs/Fruit/lib/python3.6/site-packages/sqlalchemy/orm/session.py”,第943行,位于commit \ n self.transaction.commit()\ n','文件“ /Applications/anaconda3/envs/Fruit/lib/python3.6/site-packages/sqlalchemy/orm/session.py”,第467行,位于commit \ n self._prepare_impl()\ n','File“ / Applications / anaconda3 / envs / Fruit / lib / python3.6 / site-packages / sqlalchemy / orm / session.py“,第447行,位于_prepare_impl \ n self.session.flush()\ n','File'/ Applications /anaconda3/envs/Fruit/lib/python3.6/site-packages/sqlalchemy/orm/session.py“,第2254行,在flush \ n self._flush(objects)\ n','File” / Applications / anaconda3中/envs/Fruit/lib/python3.6/site-packages/sqlalchemy/orm/session.py“,第2380行,在_flush \ n transaction.rollback(_capture_exception = True)\ n','File” / Applications / an aconda3 / envs / Fruit / lib / python3.6 / site-packages / sqlalchemy / util / langhelpers.py“,第66行,位于退出 \ n compat.reraise(exc_type,exc_value,exc_tb)\ n','File“ /Applications/anaconda3/envs/Fruit/lib/python3.6/site-packages/sqlalchemy/util/compat.py”,第249行,以提高\ n提高价值\ n','File' /Applications/anaconda3/envs/Fruit/lib/python3.6/site-packages/sqlalchemy/orm/session.py“,第2344行,位于_flush \ n flush_context.execute()\ n','File” / Applications / anaconda3 / envs / Fruit / lib / python3.6 / site-packages / sqlalchemy / orm / unitofwork.py“,第391行,位于execute \ n rec.execute(self)\ n','File” / Applications / anaconda3 / envs / Fruit / lib / python3.6 / site-packages / sqlalchemy / orm / unitofwork.py“,行556,在execute \ n uow \ n','File” / Applications / anaconda3 / envs / Fruit / lib / python3中.6 / site-packages / sqlalchemy / orm / persistence.py“,第181行,在save_obj \ n映射器中,表中,插入)\ n','File” /Applications/anaconda3/envs/Fruit/lib/python3.6 / site-packages / sqlalchemy / orm / pers istence.py”,第866行,位于_emit_insert_statements \ n execute(statement,params)\ n','File“ /Applications/anaconda3/envs/Fruit/lib/python3.6/site-packages/sqlalchemy/engine/base中。 py”,第948行,在execute \ n中返回meth(self,multiparams,params)\ n','File“ /Applications/anaconda3/envs/Fruit/lib/python3.6/site-packages/sqlalchemy/sql/elements .py“,第269行,位于_execute_on_connection \ n返回连接中。_execute_clauseelement(自身,多参数,参数)\ n','File” /Applications/anaconda3/envs/Fruit/lib/python3.6/site-packages/sqlalchemy/引擎/base.py”中的第1060行,位于_execute_clauseelement \ n中,\ n configure_sql,stilled_pa​​rams \ n',“文件” /Applications/anaconda3/envs/Fruit/lib/python3.6/site-packages/sqlalchemy/engine/base.py “,第1200行,在_execute_context \ n上下文中)\ n','文件” /Applications/anaconda3/envs/Fruit/lib/python3.6/site-packages/sqlalchemy/engine/base.py“,第1416行,在_handle_dbapi_exception \ n util.reraise(* exc_info)\ n','File“ / Applications / anaconda3 / e nvs / Fruit / lib / python3.6 / site-packages / sqlalchemy / util / compat.py”,第249行,以提高\ n提高价值\ n',“文件” / Applications / anaconda3 / envs / Fruit / lib / python3.6 / site-packages / sqlalchemy / engine / base.py“,第1193行,在_execute_context \ n上下文中)\ n','File” /Applications/anaconda3/envs/Fruit/lib/python3.6/site-包/sqlalchemy/engine/default.py”,行509,位于do_execute \ n cursor.execute(语句,参数)\ n','文件“ /Applications/anaconda3/envs/Fruit/lib/python3.6/site-包/pymysql/cursors.py”,第168行,位于execute \ n query = self.mogrify(query,args)\ n','File“ /Applications/anaconda3/envs/Fruit/lib/python3.6/site-软件包/pymysql/cursors.py”,第147行,在mogrify \ n query = query%self._escape_args(args,conn)\ n','File“ /Applications/anaconda3/envs/Fruit/lib/python3.6/ _escape_args \ n中的site-packages / pymysql / cursors.py“,第127行,返回args.items()中(key,val)的dict((key,conn.literal(val)))\ n','File “ / Applications / anaconda3 / envs / Fruit / li b / python3.6 / site-packages / pymysql / cursors.py“,第127行,\ n在args.items()中返回dict((key,conn.literal(val))for(key,val)\ n',“文件” /Applications/anaconda3/envs/Fruit/lib/python3.6/site-packages/pymysql/connections.py”,第469行,字面意思\ n返回self.escape(obj,self.encoders) \ n','文件“ /Applications/anaconda3/envs/Fruit/lib/python3.6/site-packages/pymysql/connections.py”,第462行,位于转义符\ n返回converters.escape_item(obj,self.charset ,mapping = mapping)\ n','文件“ /Applications/anaconda3/envs/Fruit/lib/python3.6/site-packages/pymysql/converters.py”,第27行,位于escape_item \ n val = encoder(val ,映射)\ n','File“ /Applications/anaconda3/envs/Fruit/lib/python3.6/site-packages/pymysql/converters.py”,第118行,在escape_unicode \ n中返回u“ \'%s \'“%_escape_unicode(value)\ n','File” /Applications/anaconda3/envs/Fruit/lib/python3.6/site-packages/pymysql/converters.py“,第73行,在_escape_unicode \ n中返回值.translate(_escape_table)\ n',在 getattr \ n返回对象中的文件“ /Applications/anaconda3/envs/Fruit/lib/python3.6/site-packages/pandas/core/generic.py”第4376行。 > getattribute ((自身,名称)\ n”,“ AttributeError:'Series'对象没有属性'translate'\ n”]

我正在使用python3.6。 这是软件包的详细信息:

aiohttp==3.3.2
aiomysql==0.0.19
asn1crypto==0.24.0
async-timeout==3.0.0
attrs==18.1.0
cffi==1.11.5
chardet==3.0.4
click==6.7
cryptography==2.2.2
Flask==1.0.2
idna==2.7
idna-ssl==1.1.0
itsdangerous==0.24
Jinja2==2.10
MarkupSafe==1.0
multidict==4.3.1
numpy==1.15.0
pandas==0.23.4
pycparser==2.18
PyMySQL==0.9.2
python-dateutil==2.7.3
pytz==2018.5
simplejson==3.16.0
six==1.11.0
SQLAlchemy==1.2.10
Werkzeug==0.14.1
xlrd==1.1.0
yarl==1.2.6

1 个答案:

答案 0 :(得分:0)

之所以发生这种情况,是因为您将一个对象从pandas传递到了一个期望使用纯字符串的操作(如堆栈跟踪所示,它恰好是一个Series对象)。

看看这个顺序:

tran = pd.read_excel(file_name)
name = tran.get('name', '')

tran这里不是普通的Python dictlist,对其应用索引(使用tran[x].get()等)会返回复杂的数据结构,而不是字符串-即使原始输入数据(在excel文件中)是字符串。

如果您的.get('key')操作从类型为str的数据框中选择一个值,则需要将其显式转换为Python字符串,而不能仅将其提供给需要的数据库函数字符串,并神奇地期望它变成字符串:

name = str ( tran.get('name', '' ) )

不过,我怀疑它实际上会为您提供一列值-您需要对代码进行一些更改才能处理该问题。

(顺便说一句,如果您只需要从XLS或CSV到Python数据的简单转换,pandas似乎是一个沉重的怪物。对于CSV,有一个本地Python库;尽管位于顶部我的头,我没有现在可以推荐的XLS转换器。