pallets-eco / flask-admin

Simple and extensible administrative interface framework for Flask
https://flask-admin.readthedocs.io
BSD 3-Clause "New" or "Revised" License
5.8k stars 1.58k forks source link

Missing example code in quickstart #2145

Open ryan-williams opened 3 years ago

ryan-williams commented 3 years ago

Wanted to flag something that's confused me a couple of times when reading https://flask-admin.readthedocs.io/en/latest/introduction/#getting-started:

There's 2 code blocks "above the fold":

from flask import Flask
from flask_admin import Admin

app = Flask(__name__)

# set optional bootswatch theme
app.config['FLASK_ADMIN_SWATCH'] = 'cerulean'

admin = Admin(app, name='microblog', template_mode='bootstrap3')
# Add administrative views here

app.run()

followed by:

from flask_admin.contrib.sqla import ModelView

# Flask and Flask-SQLAlchemy initialization here

admin = Admin(app, name='microblog', template_mode='bootstrap3')
admin.add_view(ModelView(User, db.session))
admin.add_view(ModelView(Post, db.session))

Where do db, User, and Post come from? They're not explained or linked in the document, afaict. I see some boilerplate about setting up a db over in the Flask docs, and also some SQL that creates user and post tables, but nothing defining class User / class Post.

I'm guessing this is obvious to people more familiar with the Flask ecosystem, but some explanation, bare-bones code sample defining them, or link to the assumed sample code / boilerplate would be useful in the flask-admin quickstart, I think.

I can try to PR it once I figure out the answer, but thought I'd mention since this has been a point of friction for me picking up flask-admin a couple times.

ryan-williams commented 3 years ago

Looks like the missing code I want is actually over in flask-sqlalchemy https://flask-sqlalchemy.palletsprojects.com/en/2.x/quickstart/

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)

    def __repr__(self):
        return '<User %r>' % self.username

from datetime import datetime

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(80), nullable=False)
    body = db.Column(db.Text, nullable=False)
    pub_date = db.Column(db.DateTime, nullable=False,
        default=datetime.utcnow)

    category_id = db.Column(db.Integer, db.ForeignKey('category.id'),
        nullable=False)
    category = db.relationship('Category',
        backref=db.backref('posts', lazy=True))

    def __repr__(self):
        return '<Post %r>' % self.title
ryan-williams commented 3 years ago

This seems like a minimal / self-contained starter example:

from flask import Flask
from flask_admin import Admin
from flask_admin.contrib.sqla import ModelView
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

# set optional bootswatch theme
app.config['FLASK_ADMIN_SWATCH'] = 'cerulean'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'

admin = Admin(app, name='microblog', template_mode='bootstrap3')

db = SQLAlchemy(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)

    def __repr__(self):
        return '<User %r>' % self.username

db.create_all()

admin.add_view(ModelView(User, db.session))

app.run()
caffeinatedMike commented 3 years ago

Feel free to open a PR updating the docs with this example :)