Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
mccarthysean committed Jan 5, 2024
2 parents 4e0802f + 14e24c9 commit 46e6d25
Show file tree
Hide file tree
Showing 69 changed files with 3,059 additions and 2,900 deletions.
29 changes: 17 additions & 12 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
name: Run tests
on:
- pull_request
- push
push:
branches:
- master
pull_request:
branches:
- master

jobs:
test-job:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.6', '3.7', '3.8', '3.9', '3.10']
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
tox-version: [ 'WTForms2' ]
include:
- python-version: 3.6
- python-version: 3.11
tox-version: flake8
- python-version: 3.6
- python-version: 3.11
tox-version: docs-html
services:
# Label used to access the service container
Expand All @@ -33,7 +37,7 @@ jobs:
--health-timeout 5s
--health-retries 5
mongo:
image: mongo:5.0.4-focal
image: mongo:5.0.14-focal
ports:
- 27017:27017
azurite:
Expand All @@ -43,17 +47,18 @@ jobs:
ports:
- 10000:10000
steps:
# Downloads a copy of the code in your repository before running CI tests
- name: Install Ubuntu packages
run: |
sudo apt-get update
sudo apt-get install -y libgeos-c1v5
- name: Check out repository code
uses: actions/checkout@v2
- name: Install postgis
run: sudo apt-get install -y postgis postgresql-12-postgis-3 postgresql-12-postgis-3-scripts
- name: Setup postgis
uses: actions/checkout@v3
- name: Set up PostgreSQL hstore module
env:
PGPASSWORD: postgres
run: psql -U postgres -h localhost -c 'CREATE EXTENSION hstore;' flask_admin_test
- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install tox
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ To run the examples in your local environment::
2. Create and activate a virtual environment::

virtualenv env -p python3
source env/bin/activate
source env/Scripts/activate

3. Install requirements::

Expand Down
20 changes: 17 additions & 3 deletions doc/advanced.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Advanced Functionality
Enabling CSRF Protection
------------------------

****

To add CSRF protection to the forms that are generated by *ModelView* instances, use the
SecureForm class in your *ModelView* subclass by specifying the *form_base_class* parameter::

Expand All @@ -18,6 +20,17 @@ SecureForm class in your *ModelView* subclass by specifying the *form_base_class
SecureForm requires WTForms 2 or greater. It uses the WTForms SessionCSRF class
to generate and validate the tokens for you when the forms are submitted.

Adding Custom Javascript and CSS
--------------------------------

****

To add custom JavaScript or CSS in your *ModelView* use *extra_js* or *extra_css* parameters::

class MyModelView(ModelView):
extra_js = ['https://example.com/custom.js']
extra_css = ['https://example.com/custom.css']

Localization With Flask-Babelex
-------------------------------

Expand Down Expand Up @@ -74,7 +87,7 @@ can use it by adding a FileAdmin view to your app::

# Flask setup here

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

path = op.join(op.dirname(__file__), 'static')
admin.add_view(FileAdmin(path, '/static/', name='Static Files'))
Expand Down Expand Up @@ -113,7 +126,7 @@ instance running on the same machine as your app, you can::

# Flask setup here

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

admin.add_view(rediscli.RedisCli(Redis()))

Expand Down Expand Up @@ -199,7 +212,8 @@ from the GeoAlchemy backend, rather than the usual SQLAlchemy backend::
from flask_admin.contrib.geoa import ModelView

# .. flask initialization
db = SQLAlchemy(app)
db = SQLAlchemy()
db.init_app(app)

class Location(db.Model):
id = db.Column(db.Integer, primary_key=True)
Expand Down
7 changes: 7 additions & 0 deletions doc/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
Changelog
=========

1.6.1
-----

* SQLAlchemy 2.x support
* General updates and bug fixes
* Dropped WTForms 1 support

1.6.0
-----

Expand Down
8 changes: 4 additions & 4 deletions doc/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ The first step is to initialize an empty admin interface for your Flask app::
# set optional bootswatch theme
app.config['FLASK_ADMIN_SWATCH'] = 'cerulean'

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

app.run()
Expand All @@ -31,7 +31,7 @@ you could use the :meth:`~flask_admin.base.Admin.init_app` method.

If you start this application and navigate to `http://localhost:5000/admin/ <http://localhost:5000/admin/>`_,
you should see an empty page with a navigation bar on top. Customize the look by
specifying a Bootswatch theme that suits your needs (see http://bootswatch.com/3/ for available swatches).
specifying a Bootswatch theme that suits your needs (see http://bootswatch.com/4/ for available swatches).

Adding Model Views
------------------
Expand All @@ -44,7 +44,7 @@ is the SQLAlchemy backend, which you can use as follows::

# Flask and Flask-SQLAlchemy initialization here

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

Expand Down Expand Up @@ -124,7 +124,7 @@ Using Flask-Security
--------------------

If you want a more polished solution, you could
use `Flask-Security <https://pythonhosted.org/Flask-Security/>`_,
use `Flask-Security <https://flask-security-too.readthedocs.io/>`_,
which is a higher-level library. It comes with lots of built-in views for doing
common things like user registration, login, email address confirmation, password resets, etc.

Expand Down
11 changes: 6 additions & 5 deletions examples/auth-flask-login/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ def __unicode__(self):

# Define login and registration forms (for flask-login)
class LoginForm(form.Form):
login = fields.StringField(validators=[validators.required()])
password = fields.PasswordField(validators=[validators.required()])
login = fields.StringField(validators=[validators.InputRequired()])
password = fields.PasswordField(validators=[validators.InputRequired()])

def validate_login(self, field):
user = self.get_user()
Expand All @@ -76,9 +76,9 @@ def get_user(self):


class RegistrationForm(form.Form):
login = fields.StringField(validators=[validators.required()])
login = fields.StringField(validators=[validators.InputRequired()])
email = fields.StringField()
password = fields.PasswordField(validators=[validators.required()])
password = fields.PasswordField(validators=[validators.InputRequired()])

def validate_login(self, field):
if db.session.query(User).filter_by(login=self.login.data).count() > 0:
Expand Down Expand Up @@ -214,7 +214,8 @@ def build_sample_db():
app_dir = os.path.realpath(os.path.dirname(__file__))
database_path = os.path.join(app_dir, app.config['DATABASE_FILE'])
if not os.path.exists(database_path):
build_sample_db()
with app.app_context():
build_sample_db()

# Start app
app.run(debug=True)
8 changes: 4 additions & 4 deletions examples/auth-mongoengine/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ def __unicode__(self):

# Define login and registration forms (for flask-login)
class LoginForm(form.Form):
login = fields.StringField(validators=[validators.required()])
password = fields.PasswordField(validators=[validators.required()])
login = fields.StringField(validators=[validators.InputRequired()])
password = fields.PasswordField(validators=[validators.InputRequired()])

def validate_login(self, field):
user = self.get_user()
Expand All @@ -68,9 +68,9 @@ def get_user(self):


class RegistrationForm(form.Form):
login = fields.StringField(validators=[validators.required()])
login = fields.StringField(validators=[validators.InputRequired()])
email = fields.StringField()
password = fields.PasswordField(validators=[validators.required()])
password = fields.PasswordField(validators=[validators.InputRequired()])

def validate_login(self, field):
if User.objects(login=self.login.data):
Expand Down
14 changes: 8 additions & 6 deletions examples/auth/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
from flask import Flask, url_for, redirect, render_template, request, abort
from flask_sqlalchemy import SQLAlchemy
from flask_security import Security, SQLAlchemyUserDatastore, \
UserMixin, RoleMixin, login_required, current_user
from flask_security.utils import encrypt_password
UserMixin, RoleMixin, current_user
from flask_security.utils import hash_password
import flask_admin
from flask_admin.contrib import sqla
from flask_admin import helpers as admin_helpers
Expand Down Expand Up @@ -42,6 +42,7 @@ class User(db.Model, UserMixin):
confirmed_at = db.Column(db.DateTime())
roles = db.relationship('Role', secondary=roles_users,
backref=db.backref('users', lazy='dynamic'))
fs_uniquifier = db.Column(db.String(64), unique=True, nullable=False)

def __str__(self):
return self.email
Expand Down Expand Up @@ -121,8 +122,8 @@ def build_sample_db():

test_user = user_datastore.create_user(
first_name='Admin',
email='admin',
password=encrypt_password('admin'),
email='admin@example.com',
password=hash_password('admin'),
roles=[user_role, super_user_role]
)

Expand All @@ -144,7 +145,7 @@ def build_sample_db():
first_name=first_names[i],
last_name=last_names[i],
email=tmp_email,
password=encrypt_password(tmp_pass),
password=hash_password(tmp_pass),
roles=[user_role, ]
)
db.session.commit()
Expand All @@ -156,7 +157,8 @@ def build_sample_db():
app_dir = os.path.realpath(os.path.dirname(__file__))
database_path = os.path.join(app_dir, app.config['DATABASE_FILE'])
if not os.path.exists(database_path):
build_sample_db()
with app.app_context():
build_sample_db()

# Start app
app.run(debug=True)
2 changes: 1 addition & 1 deletion examples/auth/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Flask
Flask-Admin
Flask-SQLAlchemy
Flask-Security>=1.7.5
flask-security-too
email_validator
2 changes: 1 addition & 1 deletion examples/auth/templates/admin/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ <h1>Flask-Admin example</h1>
{% if not current_user.is_authenticated %}
<p>You can register as a regular user, or log in as a superuser with the following credentials:
<ul>
<li>email: <b>admin</b></li>
<li>email: <b>admin@example.com</b></li>
<li>password: <b>admin</b></li>
</ul>
<p>
Expand Down
3 changes: 2 additions & 1 deletion examples/babel/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ def index():
admin.add_view(sqla.ModelView(Post, db.session))

# Create DB
db.create_all()
with app.app_context():
db.create_all()

# Start app
app.run(debug=True)
3 changes: 2 additions & 1 deletion examples/bootstrap4/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ def build_sample_db():
app_dir = op.realpath(os.path.dirname(__file__))
database_path = op.join(app_dir, app.config['DATABASE_FILE'])
if not os.path.exists(database_path):
build_sample_db()
with app.app_context():
build_sample_db()

# Start app
app.run(debug=True)
3 changes: 2 additions & 1 deletion examples/custom-layout/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ def build_sample_db():
app_dir = op.realpath(os.path.dirname(__file__))
database_path = op.join(app_dir, app.config['DATABASE_FILE'])
if not os.path.exists(database_path):
build_sample_db()
with app.app_context():
build_sample_db()

# Start app
app.run(debug=True)
3 changes: 2 additions & 1 deletion examples/forms-files-images/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,8 @@ def build_sample_db():
app_dir = op.realpath(os.path.dirname(__file__))
database_path = op.join(app_dir, app.config['DATABASE_FILE'])
if not os.path.exists(database_path):
build_sample_db()
with app.app_context():
build_sample_db()

# Start app
app.run(debug=False)
8 changes: 4 additions & 4 deletions examples/peewee/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class User(BaseModel):
username = peewee.CharField(max_length=80)
email = peewee.CharField(max_length=120)

def __unicode__(self):
def __str__(self):
return self.username


Expand All @@ -31,8 +31,8 @@ class UserInfo(BaseModel):

user = peewee.ForeignKeyField(User)

def __unicode__(self):
return '%s - %s' % (self.key, self.value)
def __str__(self):
return f'{self.key} - {self.value}'


class Post(BaseModel):
Expand All @@ -43,7 +43,7 @@ class Post(BaseModel):

user = peewee.ForeignKeyField(User)

def __unicode__(self):
def __str__(self):
return self.title


Expand Down
8 changes: 5 additions & 3 deletions examples/sqla-association_proxy/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,17 @@ class KeywordAdmin(sqla.ModelView):
if __name__ == '__main__':

# Create DB
db.create_all()
with app.app_context():
db.create_all()

# Add sample data
user = User('log')
for kw in (Keyword('new_from_blammo'), Keyword('its_big')):
user.keywords.append(kw)

db.session.add(user)
db.session.commit()
with app.app_context():
db.session.add(user)
db.session.commit()

# Start app
app.run(debug=True)
Loading

0 comments on commit 46e6d25

Please sign in to comment.