[已解决] 第8章个人博客,数据库无法创建表,单文件数据库可连接可CURD,代码拆分开无用,求助!

bluelog
faker

#1

按照李辉大大书里第8章个人博客一章,蓝图OK,数据模型OK,表单OK,蓝图能够访问无错,但是就是没办法在数据库中创建表,create_all()了好几天,熬了好几天,满网搜索,无果,是不是我哪里操作有问题?和书中略有不同,想按照自己的理解边看书边写。
求各位及李辉大大指点迷津!
(因为某个问题导致无法创建表,faker也从来没有成功过:joy:


__init.__py代码:

import click
from flask import Flask
from main.admin import admin_bp
from main.front import index_bp
from exts import db
from model import User, Post, Category, Comment, Tags
import config

def create_app():
    app = Flask('vblog')
    app.config.from_object(config)

    register_extensions(app)
    register_blueprints(app)
    register_commands(app)
    register_shell_context(app)
    return app

def register_extensions(app):
    db.init_app(app)

def register_blueprints(app):
    app.register_blueprint(index_bp)
    app.register_blueprint(admin_bp, url_prefix='/admin')

def register_shell_context(app):
    @app.shell_context_processor
    def make_shell_context():
        return dict(db=db, User=User, Post=Post, Category=Category, Comment=Comment, Tags=Tags)

def register_commands(app):
    @app.cli.command()
    @click.option('--drop', is_flag=True, help='Create after drop.')
    def initdb(drop):
        """Initialize the database."""
        if drop:
            click.confirm('此操作将删除数据库,您要继续吗?', abort=True)
            db.drop_all()
            click.echo('删除表')
        db.create_all()
        click.echo('初始化数据库')

    @app.cli.command()
    @click.option('--category', default=10, help='Quantity of categories, default is 10.')
    @click.option('--post', default=50, help='Quantity of posts, default is 50.')
    @click.option('--comment', default=500, help='Quantity of comments, default is 500.')
    def forge(category, post):
        """Generate fake data."""
        from fake import fake_user, fake_category, fake_post

        db.drop_all()
        db.create_all()

        click.echo('生成用户数据...')
        fake_user()

        click.echo('生成分类数据...')
        fake_category(category)

        click.echo('生成文章数据...')
        fake_post(post)

        click.echo('搞定!')

manager.py代码:

from flask_script import Manager
from flask_migrate import Migrate,MigrateCommand
from bak__init__ import create_app
from exts import db
# from model import
app = create_app()
manager = Manager(app)
Migrate(app,db)
manager.add_command('fake',MigrateCommand)
def create_fake_info():
    from fake import fake_user,fake_category,fake_post
    fake_user()
    fake_category()
    fake_post()
    print('虚拟数据生成完毕!')

if __name__ == '__main__':
    manager.run()

因为书中没有说明flask forge这个命令到底是在哪里什么状态下去输入并执行,就在虚拟环境中(venv)的状态下输入,提示没有forge模块。所以就在manage.py文件中强制执行fake虚拟数据,不知道问题出在哪儿,跪求指点。:handshake:
@greyli 请大佬帮忙!


#2

是不是没安装 faker?

(venv) $ pip install faker

为什么说「无法创建表」,有报错吗?


#4
  • 蓝图路由都是可以访问的,但就是没有数据表被创建;
  • faker确认已经安装,在虚拟环境的python shell里能够执行生成虚拟数据,但是按照书中写进 __init__.py 中的forge函数中就没作用了,推测应该是forge函数没有被执行,单独这部分代码出来,在python shell中执行,如上面图中所示,提示没有forge命令;
  • 把主要的部分代码集合在一个python文件中就可以按照数据模型在数据库中创建表,且可以写入数据。

#5
  1. 「没有数据表被创建」的根据是什么?有报错吗?
  2. 数据库配置 SQLALCHEMY_DATABASE_URI 是怎么定义的?
  3. 你把生成虚拟数据的命令放在 manager.py 里定义的命令是 fake,也就是 flask fake。
  4. flask --help 命令输出什么?

#6
  • 没有数据表被创建的依据是查看数据库里,没有任何数据表生成。
    %E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20191227222511
  • 数据库配置如下:
DIALECT = 'mysql'
DRIVER = 'pymysql'
USERNAME = 'root'
PASSWORD = 'root'
HOST = '127.0.0.1'
PORT = '3306'
DATABASE = 'test_blog'

SQLALCHEMY_DATABASE_URI = '{}+{}://{}:{}@{}:{}/{}?charset=utf8'.format(DIALECT,DRIVER,USERNAME,PASSWORD,HOST,PORT,DATABASE)
SQLALCHEMY_TRACK_MODIFICATIONS = False
  • 我又按照您书里面的思路去写了__init__.py文件,代码如下:
import click
from flask import Flask
from main.admin import admin_bp
from main.front import index_bp
from exts import db,migrate
from model import User, Post, Category, Comment, Tags
import config

def create_app():
    app = Flask(__name__)
    app.config.from_object(config)
    register_extensions(app)
    register_blueprints(app)
    register_commands(app)
    register_shell_context(app)
    return app

def register_extensions(app):
    db.init_app(app)
    migrate.init_app(app, db)

def register_blueprints(app):
    app.register_blueprint(index_bp)
    app.register_blueprint(admin_bp, url_prefix='/admin')

def register_shell_context(app):
    @app.shell_context_processor
    def make_shell_context():
        return dict(db=db, User=User, Post=Post, Category=Category, Comment=Comment)

def register_commands(app):
    @app.cli.command()
    @click.option('--drop', is_flag=True, help='Create after drop.')
    def initdb(drop):
        """Initialize the database."""
        if drop:
            click.confirm('This operation will delete the database, do you want to continue?', abort=True)
            db.drop_all()
            click.echo('Drop tables.')
        db.create_all()
        click.echo('Initialized database.')

    @app.cli.command()
    @click.option('--category', default=10, help='Quantity of categories, default is 10.')
    @click.option('--post', default=50, help='Quantity of posts, default is 50.')
    @click.option('--comment', default=500, help='Quantity of comments, default is 500.')
    def forge(category, post, comment):
        """Generate fake data."""
        from fake import fake_user, fake_category, fake_post

        db.drop_all()
        db.create_all()

        click.echo('Generating the administrator...')
        fake_user()

        click.echo('Generating %d categories...' % category)
        fake_category(category)

        click.echo('Generating %d posts...' % post)
        fake_post(post)

        click.echo('Done.')

能够运行,能够访问蓝本路由,但是在Terminal中执行flask forge时提示如下:

(venv) H:\New_test>flask forge
Usage: flask [OPTIONS] COMMAND [ARGS]...
Try "flask --help" for help.

Error: No such command "forge".

运行flask --help的结果如下:

(venv) H:\New_test>flask --help
Traceback (most recent call last):
  File "h:\new_test\venv\lib\site-packages\flask\cli.py", line 556, in list_commands
    rv.update(info.load_app().cli.list_commands(ctx))
  File "h:\new_test\venv\lib\site-packages\flask\cli.py", line 399, in load_app
    "Could not locate a Flask application. You did not provide "
flask.cli.NoAppException: Could not locate a Flask application. You did not provide the "FLASK_APP" environment variable, and a "wsgi.py" or "app.py" module was not found in the curren
t directory.
Usage: flask [OPTIONS] COMMAND [ARGS]...

  A general utility script for Flask applications.

  Provides commands from Flask, extensions, and the application. Loads the
  application defined in the FLASK_APP environment variable, or from a
  wsgi.py file. Setting the FLASK_ENV environment variable to 'development'
  will enable debug mode.

    > set FLASK_APP=hello.py
    > set FLASK_ENV=development
    > flask run

Options:
  --version  Show the flask version
  --help     Show this message and exit.

Commands:
  db      Perform database migrations.
  routes  Show the routes for the app.
  run     Run a development server.
  shell   Run a shell in the app context.

请问您,这是我哪里设置问题吗?
为了便于您查阅,我将其他.py文件代码张贴出来。

exts.py代码:

from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

db = SQLAlchemy()
migrate = Migrate()

fake.py代码:

from model import User,Category,Post
from faker import Faker
import random,requests
from exts import db

fake = Faker('zh_CN')

#生成虚拟【管理员】和【会员】数据
def fake_user(count=10):
    avatar_img = requests.get('https://api.uomg.com/api/rand.avatar').url
    admin=User(user_email='admin@qq.com',
               user_password='123456789',
               user_nickname='Admin',
               user_role='Admin',
               user_avatar=avatar_img,
               user_regip='127.0.0.1'
        )
    db.session.add(admin)

    for i in range(count):
        user_avatar_img = requests.get('https://api.uomg.com/api/rand.avatar').url
        user = User(
            user_email=fake.ascii_email(),
            user_password=fake.password(length=10, special_chars=True, digits=True, upper_case=True, lower_case=True),
            user_nickname=fake.name(),
            user_role='User',
            user_avatar=user_avatar_img,
            user_regip=fake.ipv4(network=False, address_class=None, private=None)
        )
        db.session.add(user)
    db.session.commit()

#生成虚拟【文章分类】数据
def fake_category(count=10):
    category = Category(category_name='默认',category_aka='dafault')
    db.session.add(category)

    for i in range(count):
        current_category = fake.word()
        category = Category(category_name=current_category,category_aka=current_category)
        db.session.add(category)
        db.session.commit()

#生成虚拟【文章】数据
def fake_post(count=50):
    for i in range(count):
        post = Post(post_title=fake.sentence(),
                    post_content=fake.text(2000),
                    category_id=Category.query.get(random.ranint(1,Category.query.count())),
                    user_id=User.query.get(random.randint(1,10)),
                    post_thumb=fake.image_url(width=300, height=300),
                    post_url=fake.url(schemes=None),
                    publish_datetime=fake.date(pattern="%Y-%m-%d %H:%M:%S",end_datetime=None)
                    )
        db.session.add(post)
    db.session.commit()

model.py代码如下:

from exts import db
from datetime import datetime

#先定义文章-标签多对多关联表
post_tags = db.Table('the_post_tags',
    db.Column('post_id',db.Integer,db.ForeignKey('post.post_id'),primary_key=True),
    db.Column('tags_id',db.Integer,db.ForeignKey('tags.tag_id'),primary_key=True),extend_existing=True
)

class User(db.Model):
    __tablename__='user'
    user_id = db.Column(db.Integer,primary_key=True,autoincrement=True,nullable=False,index=True,unique=True)
    user_email = db.Column(db.String(128),nullable=True,unique=True)
    user_password = db.Column(db.String(128),nullable=True)
    user_nickname = db.Column(db.String(128),nullable=True,unique=True)
    user_role = db.Column(db.String(48),nullable=True)
    user_regdate = db.Column(db.DateTime,default=datetime.now())
    user_regip = db.Column(db.String(128),nullable=True)
    user_avatar = db.Column(db.Text,nullable=True,default='https://api.btstu.cn/sjtx/api.php?lx=c1&format=images')
    posts = db.relationship('Post',backref='author')            #作者文章一对多关系
    comments = db.relationship('Comment',backref='commenteby')  #用户评论一对多关系

class Post(db.Model):
    __tablename__='post'
    post_id = db.Column(db.Integer,primary_key=True,autoincrement=True,nullable=False,index=True,unique=True)
    post_title = db.Column(db.String(256),nullable=False)
    post_thumb = db.Column(db.Text,nullable=False,default='https://api.uomg.com/api/rand.avatar?sort=女&format=jpg')
    publish_datetime = db.Column(db.DateTime,default=datetime.now())
    post_content = db.Column(db.Text,nullable=False)
    post_url = db.Column(db.String(256),nullable=False)
    post_view = db.Column(db.Integer,nullable=False,default=0)
    tag_id = db.relationship('Tags', secondary=post_tags, backref=db.backref('posts'))  #文章-标签多对多关系
    category_id = db.Column(db.Integer, db.ForeignKey('category.category_id'))  #文章分类一对多关系
    category = db.relationship('Category', back_populates='category')
    user_id = db.Column(db.Integer, db.ForeignKey('user.user_id'))              #作者文章一对多关系
    comments = db.relationship('Comment',backref='thepost',cascade='all,delete-orphan')                     #文章评论一对多关系

class Category(db.Model):
    __tablename__='category'
    category_id = db.Column(db.Integer,primary_key=True,autoincrement=True,nullable=False,index=True,unique=True)
    category_name = db.Column(db.String(256),nullable=False,unique=True)
    category_aka = db.Column(db.String(256),nullable=False,unique=True)
    parent_category_id = db.Column(db.Integer)
    posts = db.relationship('Post',back_populates='thecategory')       #文章分类一对多关系

class Comment(db.Model):
    __tablename__ = 'comment'
    comment_id = db.Column(db.Integer,primary_key=True,autoincrement=True,nullable=False,index=True,unique=True)
    parent_comment_id = db.Column(db.Integer)
    comment_datetime = db.Column(db.DateTime,default=datetime.now())
    comment_content = db.Column(db.Text,nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.user_id'))      #用户评论一对多关系
    post_id = db.Column(db.Integer,db.ForeignKey('post.post_id'))       #文章评论一对多关系
    post = db.relationship('Post',back_populates='comments')

class Tags(db.Model):
    __tablename__ = 'tags'
    tag_id = db.Column(db.Integer,primary_key=True,autoincrement=True,nullable=False,index=True,unique=True)
    tag_name = db.Column(db.String(256),nullable=False)
    tag_aka = db.Column(db.String(256),nullable=False)

db.create_all()

最后,十分感谢您在百忙之中抽出时间给出的指导意见,谢谢!


#7

明白了,是程序结构的问题。你需要做的不仅仅是拆分代码,还要把你的程序代码放到程序包里,假设 main 文件夹是你的包,你要把 manager.py 以外所有 .py 文件移动进去,更新导入语句,然后这样启动:

$ set FLASK_APP=main
$ flask run

#8

解决了!
太感谢您的帮助了,让我对Flask在这块儿理解更深入了。
您的教程书籍对我的帮助很大,很期待您有更多的新书出版,祝您万事顺遂!


#9

兄弟 你这个编辑器的主题在哪里下载的


#10


软件是Pycharm,用的里面的插件,如图所示。
插件名字:Material Theme UI
主题的名字:Solarized Light
然后字体和图标又设置了一些,需要自己慢慢调整。


#11

好的


#12

尼玛这个色调图片上看着很舒服,安装完后要亮瞎了哈哈哈


#13

哦,可能是显示器的问题吧。我几个显示器都看着比较舒服。