热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SQLAlchemy+FlaskRESTful使用(三)

前言顺理成章地,19.3.21起笔了第三章.也就是最近没啥事了,才有时间搞这些.生命不息奋斗不止吧!变更记录#19.3.21起笔#19.3.21增加Flask-RESTful如何获

前言

顺理成章地,19.3.21起笔了第三章.也就是最近没啥事了,才有时间搞这些.生命不息奋斗不止吧!

变更记录

# 19.3.21 起笔

# 19.3.21 增加 Flask-RESTful如何获取body/args/header的值

# 19.4.3 增加 使用sqlalchemy-utils达到类似Django的choices(插入/更新值时限制值)效果

# 19.4.10 增加 建立model时指定排序

# 19.4.12 增加 解决多个model文件使用同一个Base的问题

正文

Flask-RESTful获取body/args/header的值

百度一番没啥思路,最后还是看的官方文档(以下内容取至官方文档+Google翻译)

参数位置

默认下,RequestParser 试着从 flask.Request.values,以及 flask.Request.json 解析值。

在 add_argument() 中使用 location 参数可以指定解析参数的位置。flask.Request 中任何变量都能被使用。例如:

# Look only in the POST body
parser.add_argument('name', type=int, location='form')

# Look only in the querystring
parser.add_argument('PageSize', type=int, location='args')

# From the request headers
parser.add_argument('User-Agent', type=str, location='headers')

# From http COOKIEs
parser.add_argument('session_id', type=str, location='COOKIEs')

# From file uploads
parser.add_argument('picture', type=werkzeug.datastructures.FileStorage, location='files')

我们可以看到,官方文档指出,从特定位置取数据只需要在 add_argument 里指定 location 即可

不指定 location 的话默认从args和form中取(写在header中无法取到)

如果取不到理所当然的报错啦,这里给一个例子

parser.add_argument('token', type=str, help='token error', required=True, location='headers')  # 从headers中获取token

以上代码就达成了从headers中获取token的作用,没有token则会返回 tokenerror

sqlalchemy-utils达到类似Django的choices效果

首先要注明的是这个限制并不是限制在数据库中的,因此不经过ORM的数据不受限制

首先安装模块

pip install sqlalchemy-utils

sqlalchemy-utils 模块有很多功能,choices功能只是其中一个,但是网上该模块的使用比较稀少.

这里只介绍这一个功能

官方文档

https://sqlalchemy-utils.readthedocs.io/en/latest/

使用DEMO

from sqlalchemy.orm import sessionmaker, relationship, backref
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, String, Integer, ForeignKey, DateTime
from sqlalchemy_utils import ChoiceType

class User(mysql_Base):
    # 用户表
    __tablename__ = 'user'  # 表名
    lv_choices = (
        (1, 'vip1'),
        (2, 'vip2')
    )
    id = Column(Integer, primary_key=True)  # 主键
    name = Column(String(15), nullable=False, index=True, unique=True)  # 用户名,不为空,唯一
    pwd = Column(String(20), nullable=False)  # 密码,不为空
    lv = Column(ChoiceType(lv_choices, Integer()))

建立model时指定查询数据时排序

在正常业务中,我们通常会遇到按照某个字段进行排序的需求,在SQLAlchemy中我们既可以在查询时使用 orderby 方式查询

也可以在建立model时指定默认排序

demo如下

class Commodity(mysql_Base):
    # 商品表(非H5)
    __tablename__ = 'commodity'  # 表名
    delete_choices = (
        (0, '未删除'),
        (1, '已删除')
    )
    id = Column(BigInteger, primary_key=True)  # 主键
    name = Column(String(25), nullable=False, unique=True)  # 商品名称,不可为空,唯一
    introduce = Column(Text)  # 商品详细说明(可为空)
    note = Column(String(256))  # 商品备注(后台,可为空)
    title_img = Column(String(256))  # 大图链接(可为空)
    integral = Column(Integer, nullable=False, default=0)  # 商品价格(不为空/默认0)
    vaild_day = Column(Integer, nullable=False, default=30)  # 商品有效时间(天/不为空/默认30)
    repertory = Column(Integer, nullable=False, default=10000)  # 商品库存(不为空/默认1w)
    # putaway_time = Column(DateTime, nullable=False)  # 商品上架时间(不为空)
    # soldout_time = Column(DateTime, nullable=True)  # 商品下架时间(为空代表无限制)
    create_time = Column(DateTime, nullable=False)  #  商品添加时间(不为空)
    update_time = Column(DateTime, nullable=False)  # 商品最后更新时间(不为空)
    delete = Column(ChoiceType(delete_choices, Integer))  # 删除状态
    # 指定默认排序为update_time
    __mapper_args__ = {
        'order_by': update_time.desc()
    }

这种方法有利有弊,利是以后输出无需再写排序/弊是不够灵活(比如我们要求排序先把delete为1的去掉再排序)

所以怎么使用还是要看业务需求

多个model文件使用一个Base

一般情况下,我们的业务表结构比较复杂,一个model文件不利于后期的迭代和维护

关于Flask的文件夹配置是没有标准的,Flask的核心成员之一在 lepture 回答了该问题,他指出目录结构应该是灵活的.舒服就好

这里是我常用的文件结构

SQLAlchemy+Flask-RESTful使用(三)

言归正传

我们虽然可以一个model中创建一个 Base, 但是会出现问题,在使用 alembic 提交数据库的时候,如果我在 modelA中创建表a ,在 modelB中创建表b并有一个字段关联表a

会报错,大致翻译是没有找到表a的id

解决方法是所有model使用同一个Base

首先我们在 config 配置文件中直接建立一个Base

# 用户名:密码@访问地址:端口/数据库
mysql_engine = create_engine('mysql+mysqldb://root:***@***:***/boom_web?charset=utf8mb4',
                        pool_recycle=7200,  # 空闲时间后自动关闭
                        pool_size=20,  # 最大连接数
                        pool_timeout=30,  # 连接超时
                        echo=False  # 输出每次执行的sql
                        )

# 创建Base基类
mysql_Base = declarative_base() 

然后我们将 env 中的配置文件改为

from config.config import mysql_Base
# target_metadata = [user_db.metadata, commodity_db.metadata, workorder_db.metadata]  # 多个Base可用列表方式全部写进去,[bs1.metadata, bs2.metadata, ...]
target_metadata = [mysql_Base.metadata]

# 注意引入的时候要注意直接import到Base,多一级比如 config.mysql_Base 也会报错

然后我们在所有model中引入

from config.config import mysql_Base
class User(mysql_Base):
    pass

然后写完一个model记得将表引入到 config 中

在config的下方加到

(不加会导致检测不到model)

from app.commodity.models import *
from app.user.models import *
from app.workorder.models import *

完整 config 为

# -*- coding=utf-8 -*-

from sqlalchemy import create_engine, MetaData
from sqlalchemy.orm import sessionmaker, relationship, backref
from sqlalchemy.ext.declarative import declarative_base


# 用户名:密码@访问地址:端口/数据库
mysql_engine = create_engine('mysql+mysqldb://root:***@***:***/boom_web?charset=utf8mb4',
                        pool_recycle=7200,  # 空闲时间后自动关闭
                        pool_size=20,  # 最大连接数
                        pool_timeout=30,  # 连接超时
                        echo=False  # 输出每次执行的sql
                        )

# 创建Base基类
mysql_Base = declarative_base() 

# 创建DBSession类型
mysql_DBSession = sessionmaker(bind=mysql_engine)

from app.commodity.models import *
from app.user.models import *
from app.workorder.models import *

这样再执行提交即可


推荐阅读
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • XMLhttpREquest_Ajax技术总结之XmlHttpRequest
    Ajax1、 什么是ajax   ... [详细]
  • 学习一门编程语言,除了语法,最重要的是学习解决问题。很多时候单凭自己的能力确实无法做到完美解决,所以无论是搜索引擎、社区、文档还是博客&# ... [详细]
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
  • 开发笔记:Java是如何读取和写入浏览器Cookies的
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Java是如何读取和写入浏览器Cookies的相关的知识,希望对你有一定的参考价值。首先我 ... [详细]
  • 本文介绍了django中视图函数的使用方法,包括如何接收Web请求并返回Web响应,以及如何处理GET请求和POST请求。同时还介绍了urls.py和views.py文件的配置方式。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • 延迟注入工具(python)的SQL脚本
    本文介绍了一个延迟注入工具(python)的SQL脚本,包括使用urllib2、time、socket、threading、requests等模块实现延迟注入的方法。该工具可以通过构造特定的URL来进行注入测试,并通过延迟时间来判断注入是否成功。 ... [详细]
  • Python开源库和第三方包的常用框架及库
    本文介绍了Python开源库和第三方包中常用的框架和库,包括Django、CubicWeb等。同时还整理了GitHub中最受欢迎的15个Python开源框架,涵盖了事件I/O、OLAP、Web开发、高性能网络通信、测试和爬虫等领域。 ... [详细]
  • 嵌入式处理器的架构与内核发展历程
    本文主要介绍了嵌入式处理器的架构与内核发展历程,包括不同架构的指令集的变化,以及内核的流水线和结构。通过对ARM架构的分析,可以更好地理解嵌入式处理器的架构与内核的关系。 ... [详细]
  • 分享css中提升优先级属性!important的用法总结
    web前端|css教程css!importantweb前端-css教程本文分享css中提升优先级属性!important的用法总结微信门店展示源码,vscode如何管理站点,ubu ... [详细]
  • Servlet多用户登录时HttpSession会话信息覆盖问题的解决方案
    本文讨论了在Servlet多用户登录时可能出现的HttpSession会话信息覆盖问题,并提供了解决方案。通过分析JSESSIONID的作用机制和编码方式,我们可以得出每个HttpSession对象都是通过客户端发送的唯一JSESSIONID来识别的,因此无需担心会话信息被覆盖的问题。需要注意的是,本文讨论的是多个客户端级别上的多用户登录,而非同一个浏览器级别上的多用户登录。 ... [详细]
  • Sleuth+zipkin链路追踪SpringCloud微服务的解决方案
    在庞大的微服务群中,随着业务扩展,微服务个数增多,系统调用链路复杂化。Sleuth+zipkin是解决SpringCloud微服务定位和追踪的方案。通过TraceId将不同服务调用的日志串联起来,实现请求链路跟踪。通过Feign调用和Request传递TraceId,将整个调用链路的服务日志归组合并,提供定位和追踪的功能。 ... [详细]
  • 一:跨域问题1、同源策略(浏览器的安全策略)    只允许当前页面朝当前域下发请求,如果向其他域发请求,请求可以正常发送,数据也可以拿回,但是被浏览器拦截了  2、c ... [详细]
author-avatar
子晴一-夏
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有