Commit f29d3893 authored by PJ Janse van Rensburg's avatar PJ Janse van Rensburg

Merge branch 'prs-to-merge'

parents d1191c27 dc12800a
#!/bin/sh
pybabel extract -F babel.ini -k _gettext -k _ngettext -k lazy_gettext -o admin.pot --project Flask-Admin ../flask_admin
pybabel compile -f -D admin -d ../flask_admin/translations/
# docs
cd ..
make gettext
cp build/locale/*.pot babel/
sphinx-intl update -p build/locale/ -d flask_admin/translations/
......@@ -148,22 +148,11 @@ classes as follows::
widget = CKTextAreaWidget()
class MessageAdmin(ModelView):
extra_js = ['//cdn.ckeditor.com/4.6.0/standard/ckeditor.js']
form_overrides = {
'body': CKTextAreaField
}
create_template = 'ckeditor.html'
edit_template = 'ckeditor.html'
For this to work, you would also need to create a template that extends the default
functionality by including the necessary CKEditor javascript on the `create` and
`edit` pages. Save this in `templates/ckeditor.html`::
{% extends 'admin/model/edit.html' %}
{% block tail %}
{{ super() }}
<script src="//cdn.ckeditor.com/4.5.1/standard/ckeditor.js"></script>
{% endblock %}
File & Image Fields
*******************
......
......@@ -17,7 +17,7 @@
form_widget_args, form_extra_fields,
form_ajax_refs, form_create_rules,
form_edit_rules,
page_size
page_size, can_set_page_size
.. autoattribute:: can_create
.. autoattribute:: can_edit
......@@ -58,3 +58,4 @@
.. autoattribute:: action_disallowed_list
.. autoattribute:: page_size
.. autoattribute:: can_set_page_size
......@@ -57,6 +57,7 @@ release = version
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
locale_dirs = ['../flask_admin/translations/']
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
......
......@@ -267,6 +267,13 @@ When your forms contain foreign keys, have those **related models loaded via aja
}
}
To filter the results that are loaded via ajax, you can use::
form_ajax_refs = {
'active_user': QueryAjaxModelLoader('user', db.session, User,
filters=["is_active=True", "id>1000"])
}
To **manage related models inline**::
inline_models = ['post', ]
......
This example shows how you can change bootswatch themes
To run this example:
1. Clone the repository::
git clone https://github.com/flask-admin/flask-admin.git
cd flask-admin
2. Create and activate a virtual environment::
virtualenv env
source env/bin/activate
3. Install requirements::
pip install -r 'examples/forms/requirements.txt'
4. Run the application::
python examples/forms/app.py
The first time you run this example, a sample sqlite database gets populated automatically. To suppress this behaviour,
comment the following lines in app.py:::
if not os.path.exists(database_path):
build_sample_db()
__author__ = 'rochacbruno'
import os
import os.path as op
from flask import Flask, url_for
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.event import listens_for
from jinja2 import Markup
from flask_admin import Admin, form
from flask_admin.form import rules
from flask_admin.contrib import sqla
# Create application
app = Flask(__name__, static_folder='files')
# set flask admin swatch
app.config['FLASK_ADMIN_SWATCH'] = 'cerulean'
# Create dummy secrey key so we can use sessions
app.config['SECRET_KEY'] = '123456790'
# Create in-memory database
app.config['DATABASE_FILE'] = 'sample_db.sqlite'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + app.config['DATABASE_FILE']
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)
# Create directory for file fields to use
file_path = op.join(op.dirname(__file__), 'files')
try:
os.mkdir(file_path)
except OSError:
pass
# Create models
class File(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.Unicode(64))
path = db.Column(db.Unicode(128))
def __unicode__(self):
return self.name
class Image(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.Unicode(64))
path = db.Column(db.Unicode(128))
def __unicode__(self):
return self.name
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.Unicode(64))
last_name = db.Column(db.Unicode(64))
email = db.Column(db.Unicode(128))
phone = db.Column(db.Unicode(32))
city = db.Column(db.Unicode(128))
country = db.Column(db.Unicode(128))
notes = db.Column(db.UnicodeText)
# Delete hooks for models, delete files if models are getting deleted
@listens_for(File, 'after_delete')
def del_file(mapper, connection, target):
if target.path:
try:
os.remove(op.join(file_path, target.path))
except OSError:
# Don't care if was not deleted because it does not exist
pass
@listens_for(Image, 'after_delete')
def del_image(mapper, connection, target):
if target.path:
# Delete image
try:
os.remove(op.join(file_path, target.path))
except OSError:
pass
# Delete thumbnail
try:
os.remove(op.join(file_path,
form.thumbgen_filename(target.path)))
except OSError:
pass
# Administrative views
class FileView(sqla.ModelView):
# Override form field to use Flask-Admin FileUploadField
form_overrides = {
'path': form.FileUploadField
}
# Pass additional parameters to 'path' to FileUploadField constructor
form_args = {
'path': {
'label': 'File',
'base_path': file_path,
'allow_overwrite': False
}
}
class ImageView(sqla.ModelView):
def _list_thumbnail(view, context, model, name):
if not model.path:
return ''
return Markup('<img src="%s">' % url_for('static',
filename=form.thumbgen_filename(model.path)))
column_formatters = {
'path': _list_thumbnail
}
# Alternative way to contribute field is to override it completely.
# In this case, Flask-Admin won't attempt to merge various parameters for the field.
form_extra_fields = {
'path': form.ImageUploadField('Image',
base_path=file_path,
thumbnail_size=(100, 100, True))
}
class UserView(sqla.ModelView):
"""
This class demonstrates the use of 'rules' for controlling the rendering of forms.
"""
form_create_rules = [
# Header and four fields. Email field will go above phone field.
rules.FieldSet(('first_name', 'last_name', 'email', 'phone'), 'Personal'),
# Separate header and few fields
rules.Header('Location'),
rules.Field('city'),
# String is resolved to form field, so there's no need to explicitly use `rules.Field`
'country',
# Show macro from Flask-Admin lib.html (it is included with 'lib' prefix)
rules.Container('rule_demo.wrap', rules.Field('notes'))
]
# Use same rule set for edit page
form_edit_rules = form_create_rules
create_template = 'rule_create.html'
edit_template = 'rule_edit.html'
# Flask views
@app.route('/')
def index():
return '<a href="/admin/">Click me to get to Admin!</a>'
# Create admin
admin = Admin(app, 'Example: Bootswatch', template_mode='bootstrap2')
# Add views
admin.add_view(FileView(File, db.session))
admin.add_view(ImageView(Image, db.session))
admin.add_view(UserView(User, db.session, name='User'))
def build_sample_db():
"""
Populate a small db with some example entries.
"""
import random
import string
db.drop_all()
db.create_all()
first_names = [
'Harry', 'Amelia', 'Oliver', 'Jack', 'Isabella', 'Charlie','Sophie', 'Mia',
'Jacob', 'Thomas', 'Emily', 'Lily', 'Ava', 'Isla', 'Alfie', 'Olivia', 'Jessica',
'Riley', 'William', 'James', 'Geoffrey', 'Lisa', 'Benjamin', 'Stacey', 'Lucy'
]
last_names = [
'Brown', 'Smith', 'Patel', 'Jones', 'Williams', 'Johnson', 'Taylor', 'Thomas',
'Roberts', 'Khan', 'Lewis', 'Jackson', 'Clarke', 'James', 'Phillips', 'Wilson',
'Ali', 'Mason', 'Mitchell', 'Rose', 'Davis', 'Davies', 'Rodriguez', 'Cox', 'Alexander'
]
locations = [
("Shanghai", "China"),
("Istanbul", "Turkey"),
("Karachi", "Pakistan"),
("Mumbai", "India"),
("Moscow", "Russia"),
("Sao Paulo", "Brazil"),
("Beijing", "China"),
("Tianjin", "China"),
("Guangzhou", "China"),
("Delhi", "India"),
("Seoul", "South Korea"),
("Shenzhen", "China"),
("Jakarta", "Indonesia"),
("Tokyo", "Japan"),
("Mexico City", "Mexico"),
("Kinshasa", "Democratic Republic of the Congo"),
("Bangalore", "India"),
("New York City", "United States"),
("London", "United Kingdom"),
("Bangkok", "Thailand"),
("Tehran", "Iran"),
("Dongguan", "China"),
("Lagos", "Nigeria"),
("Lima", "Peru"),
("Ho Chi Minh City", "Vietnam"),
]
for i in range(len(first_names)):
user = User()
user.first_name = first_names[i]
user.last_name = last_names[i]
user.email = user.first_name.lower() + "@example.com"
tmp = ''.join(random.choice(string.digits) for i in range(10))
user.phone = "(" + tmp[0:3] + ") " + tmp[3:6] + " " + tmp[6::]
user.city = locations[i][0]
user.country = locations[i][1]
db.session.add(user)
images = ["Buffalo", "Elephant", "Leopard", "Lion", "Rhino"]
for name in images:
image = Image()
image.name = name
image.path = name.lower() + ".jpg"
db.session.add(image)
for i in [1, 2, 3]:
file = File()
file.name = "Example " + str(i)
file.path = "example_" + str(i) + ".pdf"
db.session.add(file)
db.session.commit()
return
if __name__ == '__main__':
# Build a sample db on the fly, if one does not exist yet.
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()
# Start app
app.run(debug=True, use_reloader=True)
Flask
Flask-Admin
Flask-SQLAlchemy
pillow
\ No newline at end of file
{% extends 'admin/master.html' %}
{% block body %}
{{ super() }}
<div class="container">
<div class="row">
<div class="span12">
<h1>Flask-Admin example</h1>
<p class="lead">
Bootswatch
</p>
<p>
This example shows how you can define a bootstrap swatch theme
</p>
<pre># set flask admin swatch
app.config['FLASK_ADMIN_SWATCH'] = 'cerulean'</pre>
<p>
Available swatches in <a href="http://bootswatch.com/2/">http://bootswatch.com/2/</a>
</p>
<a class="btn btn-primary" href="/"><i class="glyphicon glyphicon-chevron-left"></i> Back</a>
</div>
</div>
</div>
{% endblock body %}
{% extends 'admin/model/create.html' %}
{% import 'rule_demo.html' as rule_demo %}
\ No newline at end of file
{% macro wrap() %}
<div style="border: 1px solid gray; background-color: #f0f0f0; padding-top: 8px; margin-bottom: 8px">
{{ caller() }}
</div>
{% endmacro %}
\ No newline at end of file
{% extends 'admin/model/edit.html' %}
{% import 'rule_demo.html' as rule_demo %}
This example shows how you can change bootswatch themes
To run this example:
1. Clone the repository::
git clone https://github.com/flask-admin/flask-admin.git
cd flask-admin
2. Create and activate a virtual environment::
virtualenv env
source env/bin/activate
3. Install requirements::
pip install -r 'examples/forms/requirements.txt'
4. Run the application::
python examples/forms/app.py
The first time you run this example, a sample sqlite database gets populated automatically. To suppress this behaviour,
comment the following lines in app.py:::
if not os.path.exists(database_path):
build_sample_db()
__author__ = 'rochacbruno'
import os
import os.path as op
from flask import Flask, url_for
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.event import listens_for
from jinja2 import Markup
from flask_admin import Admin, form
from flask_admin.form import rules
from flask_admin.contrib import sqla
# Create application
app = Flask(__name__, static_folder='files')
# set flask admin swatch
app.config['FLASK_ADMIN_SWATCH'] = 'cerulean'
# Create dummy secrey key so we can use sessions
app.config['SECRET_KEY'] = '123456790'
# Create in-memory database
app.config['DATABASE_FILE'] = 'sample_db.sqlite'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + app.config['DATABASE_FILE']
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)
# Create directory for file fields to use
file_path = op.join(op.dirname(__file__), 'files')
try:
os.mkdir(file_path)
except OSError:
pass
# Create models
class File(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.Unicode(64))
path = db.Column(db.Unicode(128))
def __unicode__(self):
return self.name
class Image(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.Unicode(64))
path = db.Column(db.Unicode(128))
def __unicode__(self):
return self.name
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.Unicode(64))
last_name = db.Column(db.Unicode(64))
email = db.Column(db.Unicode(128))
phone = db.Column(db.Unicode(32))
city = db.Column(db.Unicode(128))
country = db.Column(db.Unicode(128))
notes = db.Column(db.UnicodeText)
# Delete hooks for models, delete files if models are getting deleted
@listens_for(File, 'after_delete')
def del_file(mapper, connection, target):
if target.path:
try:
os.remove(op.join(file_path, target.path))
except OSError:
# Don't care if was not deleted because it does not exist
pass
@listens_for(Image, 'after_delete')
def del_image(mapper, connection, target):
if target.path:
# Delete image
try:
os.remove(op.join(file_path, target.path))
except OSError:
pass
# Delete thumbnail
try:
os.remove(op.join(file_path,
form.thumbgen_filename(target.path)))
except OSError:
pass
# Administrative views
class FileView(sqla.ModelView):
# Override form field to use Flask-Admin FileUploadField
form_overrides = {
'path': form.FileUploadField
}
# Pass additional parameters to 'path' to FileUploadField constructor
form_args = {
'path': {
'label': 'File',
'base_path': file_path,
'allow_overwrite': False
}
}
class ImageView(sqla.ModelView):
def _list_thumbnail(view, context, model, name):
if not model.path:
return ''
return Markup('<img src="%s">' % url_for('static',
filename=form.thumbgen_filename(model.path)))
column_formatters = {
'path': _list_thumbnail
}
# Alternative way to contribute field is to override it completely.
# In this case, Flask-Admin won't attempt to merge various parameters for the field.
form_extra_fields = {
'path': form.ImageUploadField('Image',
base_path=file_path,
thumbnail_size=(100, 100, True))
}
class UserView(sqla.ModelView):
"""
This class demonstrates the use of 'rules' for controlling the rendering of forms.
"""
form_create_rules = [
# Header and four fields. Email field will go above phone field.
rules.FieldSet(('first_name', 'last_name', 'email', 'phone'), 'Personal'),
# Separate header and few fields
rules.Header('Location'),
rules.Field('city'),
# String is resolved to form field, so there's no need to explicitly use `rules.Field`
'country',
# Show macro from Flask-Admin lib.html (it is included with 'lib' prefix)
rules.Container('rule_demo.wrap', rules.Field('notes'))
]
# Use same rule set for edit page
form_edit_rules = form_create_rules
create_template = 'rule_create.html'
edit_template = 'rule_edit.html'
# Flask views
@app.route('/')
def index():
return '<a href="/admin/">Click me to get to Admin!</a>'
# Create admin
admin = Admin(app, 'Example: Bootswatch', template_mode='bootstrap3')
# Add views
admin.add_view(FileView(File, db.session))
admin.add_view(ImageView(Image, db.session))
admin.add_view(UserView(User, db.session, name='User'))
def build_sample_db():
"""
Populate a small db with some example entries.
"""
import random
import string
db.drop_all()
db.create_all()
first_names = [
'Harry', 'Amelia', 'Oliver', 'Jack', 'Isabella', 'Charlie','Sophie', 'Mia',
'Jacob', 'Thomas', 'Emily', 'Lily', 'Ava', 'Isla', 'Alfie', 'Olivia', 'Jessica',
'Riley', 'William', 'James', 'Geoffrey', 'Lisa', 'Benjamin', 'Stacey', 'Lucy'
]
last_names = [
'Brown', 'Smith', 'Patel', 'Jones', 'Williams', 'Johnson', 'Taylor', 'Thomas',
'Roberts', 'Khan', 'Lewis', 'Jackson', 'Clarke', 'James', 'Phillips', 'Wilson',
'Ali', 'Mason', 'Mitchell', 'Rose', 'Davis', 'Davies', 'Rodriguez', 'Cox', 'Alexander'
]
locations = [
("Shanghai", "China"),
("Istanbul", "Turkey"),
("Karachi", "Pakistan"),
("Mumbai", "India"),
("Moscow", "Russia"),
("Sao Paulo", "Brazil"),
("Beijing", "China"),
("Tianjin", "China"),
("Guangzhou", "China"),
("Delhi", "India"),
("Seoul", "South Korea"),
("Shenzhen", "China"),
("Jakarta", "Indonesia"),
("Tokyo", "Japan"),
("Mexico City", "Mexico"),
("Kinshasa", "Democratic Republic of the Congo"),
("Bangalore", "India"),
("New York City", "United States"),
("London", "United Kingdom"),
("Bangkok", "Thailand"),
("Tehran", "Iran"),
("Dongguan", "China"),
("Lagos", "Nigeria"),
("Lima", "Peru"),
("Ho Chi Minh City", "Vietnam"),
]
for i in range(len(first_names)):
user = User()
user.first_name = first_names[i]
user.last_name = last_names[i]
user.email = user.first_name.lower() + "@example.com"
tmp = ''.join(random.choice(string.digits) for i in range(10))
user.phone = "(" + tmp[0:3] + ") " + tmp[3:6] + " " + tmp[6::]
user.city = locations[i][0]
user.country = locations[i][1]
db.session.add(user)
images = ["Buffalo", "Elephant", "Leopard", "Lion", "Rhino"]
for name in images:
image = Image()
image.name = name
image.path = name.lower() + ".jpg"
db.session.add(image)
for i in [1, 2, 3]:
file = File()
file.name = "Example " + str(i)
file.path = "example_" + str(i) + ".pdf"
db.session.add(file)
db.session.commit()
return
if __name__ == '__main__':
# Build a sample db on the fly, if one does not exist yet.
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()
# Start app
app.run(debug=True, use_reloader=True)
Flask
Flask-Admin
Flask-SQLAlchemy
pillow
\ No newline at end of file
{% extends 'admin/master.html' %}
{% block body %}
{{ super() }}
<div class="container">
<div class="row">
<div class="col-sm-10 col-sm-offset-1">
<h1>Flask-Admin example</h1>
<p class="lead">
Bootswatch
</p>
<p>
This example shows how you can define a bootstrap swatch theme
</p>
<pre># set flask admin swatch
app.config['FLASK_ADMIN_SWATCH'] = 'cerulean'</pre>
<p>
Available swatches in <a href="http://bootswatch.com">http://bootswatch.com</a>
</p>
<a class="btn btn-primary" href="/"><i class="glyphicon glyphicon-chevron-left"></i> Back</a>
</div>
</div>
</div>
{% endblock body %}
{% extends 'admin/model/create.html' %}
{% import 'rule_demo.html' as rule_demo %}
\ No newline at end of file
{% macro wrap() %}
<div style="border: 1px solid gray; background-color: #f0f0f0; padding-top: 8px; margin-bottom: 8px">
{{ caller() }}
</div>
{% endmacro %}
\ No newline at end of file
{% extends 'admin/model/edit.html' %}
{% import 'rule_demo.html' as rule_demo %}
......@@ -518,8 +518,8 @@ class Admin(object):
self.template_mode = template_mode or 'bootstrap2'
self.category_icon_classes = category_icon_classes or dict()
# Add predefined index view
self.add_view(self.index_view)
# Add index view
self._set_admin_index_view(index_view=index_view, endpoint=endpoint, url=url)
# Register with application
if app is not None:
......@@ -541,6 +541,30 @@ class Admin(object):
self._add_view_to_menu(view)
def _set_admin_index_view(self, index_view=None,
endpoint=None, url=None):
"""
Add the admin index view.
:param index_view:
Home page view to use. Defaults to `AdminIndexView`.
:param url:
Base URL
:param endpoint:
Base endpoint name for index view. If you use multiple instances of the `Admin` class with
a single Flask application, you have to set a unique endpoint name for each instance.
"""
self.index_view = index_view or AdminIndexView(endpoint=endpoint, url=url)
self.endpoint = endpoint or self.index_view.endpoint
self.url = url or self.index_view.url
# Add predefined index view
# assume index view is always the first element of views.
if len(self._views) > 0:
self._views[0] = self.index_view
else:
self.add_view(self.index_view)
def add_views(self, *args):
"""
Add one or more views to the collection.
......@@ -627,7 +651,8 @@ class Admin(object):
def get_category_menu_item(self, name):
return self._menu_categories.get(name)
def init_app(self, app):
def init_app(self, app, index_view=None,
endpoint=None, url=None):
"""
Register all views with the Flask application.
......@@ -638,10 +663,14 @@ class Admin(object):
self._init_extension()
# Register Index view
self._set_admin_index_view(index_view=index_view, endpoint=endpoint, url=url)
# Register views
for view in self._views:
app.register_blueprint(view.create_blueprint(self))
def _init_extension(self):
if not hasattr(self.app, 'extensions'):
self.app.extensions = dict()
......@@ -670,4 +699,4 @@ class Admin(object):
"""
Return menu links.
"""
return self._menu_links
return self._menu_links
\ No newline at end of file
from sqlalchemy import or_
from sqlalchemy import or_, and_
from flask_admin._compat import as_unicode, string_types
from flask_admin.model.ajax import AjaxModelLoader, DEFAULT_PAGE_SIZE
......@@ -13,6 +13,8 @@ class QueryAjaxModelLoader(AjaxModelLoader):
:param fields:
Fields to run query against
:param filters:
Additional filters to apply to the loader
"""
super(QueryAjaxModelLoader, self).__init__(name, options)
......@@ -20,6 +22,7 @@ class QueryAjaxModelLoader(AjaxModelLoader):
self.model = model
self.fields = options.get('fields')
self.order_by = options.get('order_by')
self.filters = options.get('filters')
if not self.fields:
raise ValueError('AJAX loading requires `fields` to be specified for %s.%s' % (model, self.name))
......@@ -65,6 +68,10 @@ class QueryAjaxModelLoader(AjaxModelLoader):
filters = (field.ilike(u'%%%s%%' % term) for field in self._cached_fields)
query = query.filter(or_(*filters))
if self.filters:
filters = ["%s.%s" % (self.model.__name__.lower(), value) for value in self.filters]
query = query.filter(and_(*filters))
if self.order_by:
query = query.order_by(self.order_by)
......
......@@ -105,16 +105,16 @@ class AdminModelConverter(ModelConverterBase):
# determine optional/required, or respect existing
requirement_options = (validators.Optional, validators.InputRequired)
if not any(isinstance(v, requirement_options) for v in kwargs['validators']):
if property_is_association_proxy or column.nullable or prop.direction.name != 'MANYTOONE':
requirement_validator_specified = any(isinstance(v, requirement_options) for v in kwargs['validators'])
if property_is_association_proxy or column.nullable or prop.direction.name != 'MANYTOONE':
kwargs['allow_blank'] = True
if not requirement_validator_specified:
kwargs['validators'].append(validators.Optional())
else:
else:
kwargs['allow_blank'] = False
if not requirement_validator_specified:
kwargs['validators'].append(validators.InputRequired())
# Contribute model-related parameters
if 'allow_blank' not in kwargs:
kwargs['allow_blank'] = column.nullable
# Override field type if necessary
override = self._get_field_override(prop.key)
if override:
......
......@@ -628,13 +628,26 @@ class ModelView(BaseModelView):
column = columns[0]
# If filter related to relation column (represented by
# relation_name.target_column) we collect here relation name
joined_column_name = None
if '.' in name:
joined_column_name = name.split('.')[0]
# Join not needed for hybrid properties
if (not is_hybrid_property and tools.need_join(self.model, column.table) and
name not in self.column_labels):
visible_name = '%s / %s' % (
self.get_column_name(column.table.name),
self.get_column_name(column.name)
)
if joined_column_name:
visible_name = '%s / %s / %s' % (
joined_column_name,
self.get_column_name(column.table.name),
self.get_column_name(column.name)
)
else:
visible_name = '%s / %s' % (
self.get_column_name(column.table.name),
self.get_column_name(column.name)
)
else:
if not isinstance(name, string_types):
visible_name = self.get_column_name(name.property.key)
......@@ -657,10 +670,19 @@ class ModelView(BaseModelView):
options=self.column_choices.get(name),
)
key_name = column
# In case of filter related to relation column filter key
# must be named with relation name (to prevent following same
# target column to replace previous)
if joined_column_name:
key_name = "{0}.{1}".format(joined_column_name, column)
for f in flt:
f.key_name = key_name
if joins:
self._filter_joins[column] = joins
self._filter_joins[key_name] = joins
elif not is_hybrid_property and tools.need_join(self.model, column.table):
self._filter_joins[column] = [column.table]
self._filter_joins[key_name] = [column.table]
return flt
......@@ -900,7 +922,9 @@ class ModelView(BaseModelView):
# Figure out joins
if isinstance(flt, sqla_filters.BaseSQLAFilter):
path = self._filter_joins.get(flt.column, [])
# If no key_name is specified, use filter column as filter key
filter_key = flt.key_name or flt.column
path = self._filter_joins.get(filter_key, [])
query, joins, alias = self._apply_path_joins(query, joins, path, inner_join=False)
......
......@@ -42,8 +42,9 @@ class ViewArgs(object):
"""
List view arguments.
"""
def __init__(self, page=None, sort=None, sort_desc=None, search=None, filters=None, extra_args=None):
def __init__(self, page=None, page_size=None, sort=None, sort_desc=None, search=None, filters=None, extra_args=None):
self.page = page
self.page_size = page_size
self.sort = sort
self.sort_desc = bool(sort_desc)
self.search = search
......@@ -61,6 +62,7 @@ class ViewArgs(object):
flt = None
kwargs.setdefault('page', self.page)
kwargs.setdefault('page_size', self.page_size)
kwargs.setdefault('sort', self.sort)
kwargs.setdefault('sort_desc', self.sort_desc)
kwargs.setdefault('search', self.search)
......@@ -719,12 +721,17 @@ class BaseModelView(BaseView, ActionsMixin):
for supported types.
"""
# Various settings
# Pagination settings
page_size = 20
"""
Default page size for pagination.
"""
can_set_page_size = False
"""
Allows to select page size via dropdown list
"""
def __init__(self, model,
name=None, category=None, endpoint=None, url=None, static_folder=None,
menu_class_name=None, menu_icon_type=None, menu_icon_value=None):
......@@ -1646,6 +1653,7 @@ class BaseModelView(BaseView, ActionsMixin):
Return arguments from query string.
"""
return ViewArgs(page=request.args.get('page', 0, type=int),
page_size=request.args.get('page_size', 0, type=int),
sort=request.args.get('sort', None, type=int),
sort_desc=request.args.get('desc', None, type=int),
search=request.args.get('search', None),
......@@ -1668,6 +1676,9 @@ class BaseModelView(BaseView, ActionsMixin):
kwargs = dict(page=page, sort=view_args.sort, desc=desc, search=view_args.search)
kwargs.update(view_args.extra_args)
if view_args.page_size:
kwargs['page_size'] = view_args.page_size
if view_args.filters:
for i, pair in enumerate(view_args.filters):
idx, flt_name, value = pair
......@@ -1821,9 +1832,12 @@ class BaseModelView(BaseView, ActionsMixin):
if sort_column is not None:
sort_column = sort_column[0]
# Get page size
page_size = view_args.page_size or self.page_size
# Get count and data
count, data = self.get_list(view_args.page, sort_column, view_args.sort_desc,
view_args.search, view_args.filters)
view_args.search, view_args.filters, page_size=page_size)
list_forms = {}
if self.column_editable_list:
......@@ -1831,9 +1845,9 @@ class BaseModelView(BaseView, ActionsMixin):
list_forms[self.get_pk_value(row)] = self.list_form(obj=row)
# Calculate number of pages
if count is not None and self.page_size:
num_pages = int(ceil(count / float(self.page_size)))
elif not self.page_size:
if count is not None and page_size:
num_pages = int(ceil(count / float(page_size)))
elif not page_size:
num_pages = 0 # hide pager for unlimited page_size
else:
num_pages = None # use simple pager
......@@ -1852,6 +1866,12 @@ class BaseModelView(BaseView, ActionsMixin):
return self._get_list_url(view_args.clone(sort=column, sort_desc=desc))
def page_size_url(s):
if not s:
s = self.page_size
return self._get_list_url(view_args.clone(page_size=s))
# Actions
actions, actions_confirmation = self.get_actions_list()
......@@ -1877,8 +1897,10 @@ class BaseModelView(BaseView, ActionsMixin):
count=count,
pager_url=pager_url,
num_pages=num_pages,
can_set_page_size=self.can_set_page_size,
page_size_url=page_size_url,
page=view_args.page,
page_size=self.page_size,
page_size=page_size,
# Sorting
sort_column=view_args.sort,
......
......@@ -8,7 +8,7 @@ class BaseFilter(object):
"""
Base filter class.
"""
def __init__(self, name, options=None, data_type=None):
def __init__(self, name, options=None, data_type=None, key_name=None):
"""
Constructor.
......@@ -18,10 +18,13 @@ class BaseFilter(object):
List of fixed options. If provided, will use drop down instead of textbox.
:param data_type:
Client-side widget type to use.
:param key_name:
Optional name who represent this filter.
"""
self.name = name
self.options = options
self.data_type = data_type
self.key_name = key_name
def get_options(self, view):
"""
......
......@@ -89,3 +89,53 @@ table.filters tr td {
.admin-form .controls {
margin-left: 110px;
}
@media only screen and (max-width: 800px) {
/* Force table to not be like tables anymore */
#no-more-tables table,
#no-more-tables thead,
#no-more-tables tbody,
#no-more-tables th,
#no-more-tables td,
#no-more-tables tr {
display: block;
}
/* Hide table headers (but not display: none;, for accessibility) */
#no-more-tables thead tr {
position: absolute;
top: -9999px;
left: -9999px;
}
#no-more-tables tr { border: 1px solid #ccc; }
#no-more-tables td {
/* Behave like a "row" */
border: none;
border-bottom: 1px solid #eee;
position: relative;
padding-left: 50%;
white-space: normal;
text-align:left;
}
#no-more-tables td:before {
/* Now like a table header */
position: absolute;
/* Top/left values mimic padding */
top: 6px;
left: 6px;
width: 45%;
padding-right: 10px;
white-space: nowrap;
text-align:left;
font-weight: bold;
}
/*
Label the data
*/
#no-more-tables td:before { content: attr(data-title); }
}
......@@ -103,3 +103,8 @@ body.modal-open {
margin-top: 20px;
margin-bottom: 10px;
}
.table-responsive
{
overflow-x: auto;
}
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -12,9 +12,14 @@
<meta name="author" content="">
{% endblock %}
{% block head_css %}
<link href="{{ admin_static.url(filename='bootstrap/bootstrap2/css/bootstrap.css', v='2.3.2') }}" rel="stylesheet">
<link href="{{ admin_static.url(filename='bootstrap/bootstrap2/swatch/{swatch}/bootstrap.min.css'.format(swatch=config.get('FLASK_ADMIN_SWATCH', 'default')), v='2.3.2') }}" rel="stylesheet">
<link href="{{ admin_static.url(filename='bootstrap/bootstrap2/css/bootstrap-responsive.css', v='2.3.2') }}" rel="stylesheet">
<link href="{{ admin_static.url(filename='admin/css/bootstrap2/admin.css', v='1.1.1') }}" rel="stylesheet">
{% if admin_view.extra_css %}
{% for css_url in admin_view.extra_css %}
<link href="{{ css_url }}" rel="stylesheet">
{% endfor %}
{% endif %}
<style>
body {
padding-top: 4px;
......@@ -65,6 +70,11 @@
<script src="{{ admin_static.url(filename='bootstrap/bootstrap2/js/bootstrap.min.js', v='2.3.2') }}" type="text/javascript"></script>
<script src="{{ admin_static.url(filename='vendor/moment.min.js', v='2.9.0') }}" type="text/javascript"></script>
<script src="{{ admin_static.url(filename='vendor/select2/select2.min.js', v='3.5.2') }}" type="text/javascript"></script>
{% if admin_view.extra_js %}
{% for js_url in admin_view.extra_js %}
<script src="{{ js_url }}" type="text/javascript"></script>
{% endfor %}
{% endif %}
{% endblock %}
{% block tail %}
......
......@@ -22,6 +22,7 @@
{% endblock %}
{% block file_list_table %}
<div id="no-more-tables">
<table class="table table-striped table-bordered model-list">
<thead>
<tr>
......@@ -102,13 +103,13 @@
{% endblock %}
</td>
{% if is_dir %}
<td colspan="2">
<td colspan="2" data-title="{{ _gettext('Name') }}">
<a href="{{ get_dir_url('.index_view', path)|safe }}">
<i class="fa fa-folder-o icon-folder-close"></i> <span>{{ name }}</span>
</a>
</td>
{% else %}
<td>
<td data-title="{{ _gettext('Name') }}">
{% if admin_view.can_download %}
{%- if admin_view.edit_modal and admin_view.is_file_editable(path) -%}
{{ lib.add_modal_button(url=get_file_url(path, modal=True)|safe,
......@@ -121,7 +122,7 @@
{% endif %}
</td>
{% if admin_view.is_column_visible('size') %}
<td>
<td data-title="{{ _gettext('Size') }}">
{{ size|filesizeformat }}
</td>
{% endif %}
......@@ -135,6 +136,7 @@
</tr>
{% endfor %}
</table>
</div>
{% endblock %}
{% block toolbar %}
<div class="btn-toolbar">
......
......@@ -68,3 +68,14 @@
{% endif %}
</form>
{% endmacro %}
{% macro page_size_form(generator, btn_class='dropdown-toggle') %}
<a class="{{ btn_class }}" data-toggle="dropdown" href="javascript:void(0)">
{{ page_size }} {{ _gettext('items') }}<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="{{ generator(20) }}">20 {{ _gettext('items') }}</a></li>
<li><a href="{{ generator(50) }}">50 {{ _gettext('items') }}</a></li>
<li><a href="{{ generator(100) }}">100 {{ _gettext('items') }}</a></li>
</ul>
{% endmacro %}
......@@ -39,6 +39,12 @@
</li>
{% endif %}
{% if can_set_page_size %}
<li class="dropdown">
{{ model_layout.page_size_form(page_size_url) }}
</li>
{% endif %}
{% if actions %}
<li class="dropdown">
{{ actionlib.dropdown(actions) }}
......@@ -61,8 +67,9 @@
{% endif %}
{% block model_list_table %}
<table class="table table-striped table-bordered table-hover model-list">
<thead>
<div id="no-more-tables">
<table class="table table-striped table-bordered table-hover model-list cf">
<thead class="cf">
<tr>
{% block list_header scoped %}
{% if actions %}
......@@ -127,7 +134,7 @@
{% endblock %}
{% for c, name in list_columns %}
<td class="col-{{c}}">
<td class="col-{{c}}" data-title="{{ name }}">
{% if admin_view.is_editable(c) %}
{% set form = list_forms[get_pk_value(row)] %}
{% if form.csrf_token %}
......@@ -154,6 +161,7 @@
</tr>
{% endfor %}
</table>
</div>
{% block list_pager %}
{% if num_pages is not none %}
{{ lib.pager(page, num_pages, pager_url) }}
......
......@@ -12,9 +12,16 @@
<meta name="author" content="">
{% endblock %}
{% block head_css %}
<link href="{{ admin_static.url(filename='bootstrap/bootstrap3/css/bootstrap.min.css', v='3.3.5') }}" rel="stylesheet">
<link href="{{ admin_static.url(filename='bootstrap/bootstrap3/swatch/{swatch}/bootstrap.min.css'.format(swatch=config.get('FLASK_ADMIN_SWATCH', 'default')), v='3.3.5') }}" rel="stylesheet">
{%if config.get('FLASK_ADMIN_SWATCH', 'default') == 'default' %}
<link href="{{ admin_static.url(filename='bootstrap/bootstrap3/css/bootstrap-theme.min.css', v='3.3.5') }}" rel="stylesheet">
{%endif%}
<link href="{{ admin_static.url(filename='admin/css/bootstrap3/admin.css', v='1.1.1') }}" rel="stylesheet">
{% if admin_view.extra_css %}
{% for css_url in admin_view.extra_css %}
<link href="{{ css_url }}" rel="stylesheet">
{% endfor %}
{% endif %}
<style>
body {
padding-top: 4px;
......@@ -76,6 +83,11 @@
<script src="{{ admin_static.url(filename='bootstrap/bootstrap3/js/bootstrap.min.js', v='3.3.5') }}" type="text/javascript"></script>
<script src="{{ admin_static.url(filename='vendor/moment.min.js', v='2.9.0') }}" type="text/javascript"></script>
<script src="{{ admin_static.url(filename='vendor/select2/select2.min.js', v='3.5.2') }}" type="text/javascript"></script>
{% if admin_view.extra_js %}
{% for js_url in admin_view.extra_js %}
<script src="{{ js_url }}" type="text/javascript"></script>
{% endfor %}
{% endif %}
{% endblock %}
{% block tail %}
......
......@@ -22,6 +22,7 @@
{% endblock %}
{% block file_list_table %}
<div class="table-responsive">
<table class="table table-striped table-bordered model-list">
<thead>
<tr>
......@@ -135,6 +136,7 @@
</tr>
{% endfor %}
</table>
</div>
{% endblock %}
{% block toolbar %}
<div class="btn-toolbar">
......
......@@ -66,3 +66,14 @@
{% endif %}
</form>
{% endmacro %}
{% macro page_size_form(generator, btn_class='dropdown-toggle') %}
<a class="{{ btn_class }}" data-toggle="dropdown" href="javascript:void(0)">
{{ page_size }} {{ _gettext('items') }}<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="{{ generator(20) }}">20 {{ _gettext('items') }}</a></li>
<li><a href="{{ generator(50) }}">50 {{ _gettext('items') }}</a></li>
<li><a href="{{ generator(100) }}">100 {{ _gettext('items') }}</a></li>
</ul>
{% endmacro %}
......@@ -39,6 +39,12 @@
</li>
{% endif %}
{% if can_set_page_size %}
<li class="dropdown">
{{ model_layout.page_size_form(page_size_url) }}
</li>
{% endif %}
{% if actions %}
<li class="dropdown">
{{ actionlib.dropdown(actions) }}
......@@ -60,6 +66,7 @@
{% endif %}
{% block model_list_table %}
<div class="table-responsive">
<table class="table table-striped table-bordered table-hover model-list">
<thead>
<tr>
......@@ -153,6 +160,7 @@
</tr>
{% endfor %}
</table>
</div>
{% block list_pager %}
{% if num_pages is not none %}
{{ lib.pager(page, num_pages, pager_url) }}
......
......@@ -640,7 +640,7 @@ def test_column_filters():
view = CustomModelView(Model2, db.session,
column_filters=['model1.bool_field'])
eq_([(f['index'], f['operation']) for f in view._filter_groups[u'Model1 / Bool Field']],
eq_([(f['index'], f['operation']) for f in view._filter_groups[u'model1 / Model1 / Bool Field']],
[
(0, 'equals'),
(1, 'not equal'),
......
......@@ -116,6 +116,25 @@ def test_custom_index_view():
eq_(admin._views[0], view)
def test_custom_index_view_in_init_app():
view = base.AdminIndexView(name='a', category='b', endpoint='c',
url='/d', template='e')
app = Flask(__name__)
admin = base.Admin()
admin.init_app(app, index_view=view)
eq_(admin.endpoint, 'c')
eq_(admin.url, '/d')
ok_(admin.index_view is view)
eq_(view.name, 'a')
eq_(view.category, 'b')
eq_(view._template, 'e')
# Check if view was added
eq_(len(admin._views), 1)
eq_(admin._views[0], view)
def test_base_registration():
app = Flask(__name__)
admin = base.Admin(app)
......
# Adding A Model Backend
# http://flask-admin.readthedocs.io/en/latest/adding_a_new_model_backend/
#
# Copyright (C) 2012-2015, Serge S. Koval
# This file is distributed under the same license as the flask-admin
# package.
# 1dot75cm <sensor.wen@gmail.com>, 2016.
#
msgid ""
msgstr ""
"Project-Id-Version: flask-admin 1.4.2\n"
"Report-Msgid-Bugs-To: https://github.com/sixu05202004/Flask-extensions-docs\n"
"POT-Creation-Date: 2016-11-25 03:00+0800\n"
"PO-Revision-Date: 2016-11-27 03:00+0800\n"
"Last-Translator: 1dot75cm <sensor.wen@gmail.com>\n"
"Language-Team: zh_CN <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.3.4\n"
#: ../../adding_a_new_model_backend.rst:4
msgid "Adding A Model Backend"
msgstr "添加一个模型后端"
#: ../../adding_a_new_model_backend.rst:6
msgid ""
"Flask-Admin makes a few assumptions about the database models that it "
"works with. If you want to implement your own database backend, and still"
" have Flask-Admin's model views work as expected, then you should take "
"note of the following:"
msgstr ""
"Flask-Admin 对它使用的数据库模型做了一些假设。如果你想实现你自己的数据库后端,"
"并且保证 Flask-Admin 的模型视图按预期工作,那么应该注意以下几点:"
#: ../../adding_a_new_model_backend.rst:9
msgid ""
"Each model must have one field which acts as a `primary key` to uniquely "
"identify instances of that model. However, there are no restriction on "
"the data type or the field name of the `primary key` field."
msgstr ""
"每个模型必须有一个字段作为主键,以唯一标识该模型的实例。对主键字段的数据类型或字段名没有限制。"
#: ../../adding_a_new_model_backend.rst:11
msgid "Models must make their data accessible as python properties."
msgstr "模型的数据必须为可访问的 python 属性。"
#: ../../adding_a_new_model_backend.rst:13
msgid ""
"If that is the case, then you can implement your own database backend by "
"extending the `BaseModelView` class, and implementing the set of "
"scaffolding methods listed below."
msgstr ""
"如果是这样,您可以通过扩展 `BaseModelView` 类并实现以下列出的一组方法"
"来实现您自己的数据库后端。"
#: ../../adding_a_new_model_backend.rst:17
msgid "Extending BaseModelView"
msgstr "扩展 BaseModelView"
#: ../../adding_a_new_model_backend.rst:19
msgid ""
"Start off by defining a new class, which derives from from "
":class:`~flask_admin.model.BaseModelView`::"
msgstr ""
"定义一个新类,继承自 :class:`~flask_admin.model.BaseModelView`::"
#: ../../adding_a_new_model_backend.rst:24
msgid ""
"This class inherits BaseModelView's `__init__` method, which accepts a "
"model class as first argument. The model class is stored as the attribute"
" ``self.model`` so that other methods may access it."
msgstr ""
"这个类继承了 BaseModelView 的 `__init__` 方法,它接受一个模型类作为第一个参数。"
"模型类被存储为属性 ``self.model``,以便其他方法可以访问它。"
#: ../../adding_a_new_model_backend.rst:27
msgid "Now, implement the following scaffolding methods for the new class:"
msgstr "现在,为新类实现以下脚手架方法:"
#: ../../adding_a_new_model_backend.rst:29
msgid ":meth:`~flask_admin.model.BaseModelView.get_pk_value`"
msgstr ":meth:`~flask_admin.model.BaseModelView.get_pk_value`"
#: ../../adding_a_new_model_backend.rst:31
msgid ""
"This method returns a primary key value from the model instance. In the "
"SQLAlchemy backend, it gets the primary key from the model using "
":meth:`~flask_admin.contrib.sqla.ModelView.scaffold_pk`, caches it and "
"then returns the value from the model whenever requested."
msgstr ""
"此方法从模型实例返回主键值。在 SQLAlchemy 后端,它使用 "
":meth:`~flask_admin.contrib.sqla.ModelView.scaffold_pk` 从模型中获取主键,"
"将其缓存,然后在请求时从模型返回值。"
#: ../../adding_a_new_model_backend.rst:36
#: ../../adding_a_new_model_backend.rst:85
#: ../../adding_a_new_model_backend.rst:155
#: ../../adding_a_new_model_backend.rst:191
msgid "For example::"
msgstr "例如::"
#: ../../adding_a_new_model_backend.rst:42
msgid ":meth:`~flask_admin.model.BaseModelView.scaffold_list_columns`"
msgstr ":meth:`~flask_admin.model.BaseModelView.scaffold_list_columns`"
#: ../../adding_a_new_model_backend.rst:44
msgid "Returns a list of columns to be displayed in a list view. For example::"
msgstr "返回 list 视图需要显示的字段列表。例如::"
#: ../../adding_a_new_model_backend.rst:57
msgid ":meth:`~flask_admin.model.BaseModelView.scaffold_sortable_columns`"
msgstr ":meth:`~flask_admin.model.BaseModelView.scaffold_sortable_columns`"
#: ../../adding_a_new_model_backend.rst:59
msgid ""
"Returns a dictionary of sortable columns. The keys in the dictionary "
"should correspond to the model's field names. The values should be those "
"variables that will be used for sorting."
msgstr ""
"返回可排序字典。字典的键对应模型的字段名称。这些值将用于排序。"
#: ../../adding_a_new_model_backend.rst:62
msgid ""
"For example, in the SQLAlchemy backend it is possible to sort by a "
"foreign key field. So, if there is a field named `user`, which is a "
"foreign key for the `Users` table, and the `Users` table also has a name "
"field, then the key will be `user` and value will be `Users.name`."
msgstr ""
"例如,在 SQLAlchemy 后端,可以按外键字段排序。因此,如果有一个名为 `user` 的字段,"
"它是 `Users` 表的外键,并且 `Users` 表也有一个 name 字段,那么键将是 `user`,"
"值将是 `Users.name`。"
#: ../../adding_a_new_model_backend.rst:66
msgid ""
"If your backend does not support sorting, return `None` or an empty "
"dictionary."
msgstr ""
"如果您的后端不支持排序,则返回 `None` 或空字典。"
#: ../../adding_a_new_model_backend.rst:69
msgid ":meth:`~flask_admin.model.BaseModelView.init_search`"
msgstr ":meth:`~flask_admin.model.BaseModelView.init_search`"
#: ../../adding_a_new_model_backend.rst:71
msgid ""
"Initialize search functionality. If your backend supports full-text "
"search, do initializations and return `True`. If your backend does not "
"support full-text search, return `False`."
msgstr ""
"初始化搜索功能。如果您的后端支持全文搜索,请进行初始化并返回 `True`。"
"如果您的后端不支持全文搜索,请返回 `False`。"
#: ../../adding_a_new_model_backend.rst:76
msgid ""
"For example, SQLAlchemy backend reads value of the "
"`self.searchable_columns` and verifies if all fields are of text type, if"
" they're local to the current model (if not, it will add a join, etc) and"
" caches this information for future use."
msgstr ""
"例如,SQLAlchemy 后端读取 `self.searchable_columns` 的值,并验证所有字段是否为"
"文本类型,是否为当前模块的本地字段 (如果不是,则添加 join 等),并缓存此信息以供将来使用。"
#: ../../adding_a_new_model_backend.rst:81
msgid ":meth:`~flask_admin.model.BaseModelView.scaffold_form`"
msgstr ":meth:`~flask_admin.model.BaseModelView.scaffold_form`"
#: ../../adding_a_new_model_backend.rst:83
msgid "Generate `WTForms` form class from the model."
msgstr "从模型生成 `WTForms` 表单类。"
#: ../../adding_a_new_model_backend.rst:95
msgid ":meth:`~flask_admin.model.BaseModelView.get_list`"
msgstr ":meth:`~flask_admin.model.BaseModelView.get_list`"
#: ../../adding_a_new_model_backend.rst:97
msgid ""
"This method should return list of model instances with paging, sorting, "
"etc applied."
msgstr ""
"此方法应返回用于分页,排序等操作的模型实例的列表。"
#: ../../adding_a_new_model_backend.rst:100
msgid "For SQLAlchemy backend it looks like:"
msgstr "对于 SQLAlchemy 后端的示例如下:"
#: ../../adding_a_new_model_backend.rst:102
msgid ""
"If search was enabled and provided search value is not empty, generate "
"LIKE statements for each field from `self.searchable_columns`"
msgstr ""
"如果启用搜索并且提供的搜索值不为空,请从 `self.searchable_columns` 中"
"为每个字段生成 LIKE 语句。"
#: ../../adding_a_new_model_backend.rst:105
msgid "If filter values were passed, call `apply` method with values::"
msgstr "如果已向过滤器传值,请调用具有该值的 `apply` 方法::"
#: ../../adding_a_new_model_backend.rst:111
msgid "Execute query to get total number of rows in the database (count)"
msgstr "执行查询以获取数据库中的总行数 (count)"
#: ../../adding_a_new_model_backend.rst:114
msgid ""
"If `sort_column` was passed, will do something like (with some extra FK "
"logic which is omitted in this example)::"
msgstr ""
"如果 `sort_column` 被传递,将做类似的事情 (在这个例子中省略一些额外的 FK 逻辑)::"
#: ../../adding_a_new_model_backend.rst:121
msgid "Apply paging"
msgstr "应用分页"
#: ../../adding_a_new_model_backend.rst:123
msgid "Return count, list as a tuple"
msgstr "返回 count, list 作为一个元组"
#: ../../adding_a_new_model_backend.rst:125
msgid ":meth:`~flask_admin.model.BaseModelView.get_one`"
msgstr ":meth:`~flask_admin.model.BaseModelView.get_one`"
#: ../../adding_a_new_model_backend.rst:127
msgid "Return a model instance by its primary key."
msgstr "通过其主键返回模型实例。"
#: ../../adding_a_new_model_backend.rst:129
msgid ":meth:`~flask_admin.model.BaseModelView.create_model`"
msgstr ":meth:`~flask_admin.model.BaseModelView.create_model`"
#: ../../adding_a_new_model_backend.rst:131
msgid "Create a new instance of the model from the `Form` object."
msgstr "从 `Form` 对象创建新的模型实例。"
#: ../../adding_a_new_model_backend.rst:133
msgid ":meth:`~flask_admin.model.BaseModelView.update_model`"
msgstr ":meth:`~flask_admin.model.BaseModelView.update_model`"
#: ../../adding_a_new_model_backend.rst:135
msgid "Update the model instance with data from the form."
msgstr "用表单数据更新模型实例。"
#: ../../adding_a_new_model_backend.rst:137
msgid ":meth:`~flask_admin.model.BaseModelView.delete_model`"
msgstr ":meth:`~flask_admin.model.BaseModelView.delete_model`"
#: ../../adding_a_new_model_backend.rst:139
msgid "Delete the specified model instance from the data store."
msgstr "从数据存储中删除指定的模型实例。"
#: ../../adding_a_new_model_backend.rst:141
msgid ":meth:`~flask_admin.model.BaseModelView.is_valid_filter`"
msgstr ":meth:`~flask_admin.model.BaseModelView.is_valid_filter`"
#: ../../adding_a_new_model_backend.rst:143
msgid "Verify whether the given object is a valid filter."
msgstr "验证给定对象是否是有效的过滤器。"
#: ../../adding_a_new_model_backend.rst:145
msgid ":meth:`~flask_admin.model.BaseModelView.scaffold_filters`"
msgstr ":meth:`~flask_admin.model.BaseModelView.scaffold_filters`"
#: ../../adding_a_new_model_backend.rst:147
msgid "Return a list of filter objects for one model field."
msgstr "返回一个模型字段的过滤器对象列表。"
#: ../../adding_a_new_model_backend.rst:149
msgid ""
"This method will be called once for each entry in the "
"`self.column_filters` setting."
msgstr ""
"对于 `self.column_filters` 设置中的每个条目,都将调用一次该方法。"
#: ../../adding_a_new_model_backend.rst:152
msgid ""
"If your backend does not know how to generate filters for the provided "
"field, it should return `None`."
msgstr ""
"如果您的后端不知道如何为提供的字段生成过滤器,则它应该返回 `None`。"
#: ../../adding_a_new_model_backend.rst:165
msgid "Implementing filters"
msgstr "实现过滤器"
#: ../../adding_a_new_model_backend.rst:167
msgid ""
"Each model backend should have its own set of filter implementations. It "
"is not possible to use the filters from SQLAlchemy models in a non-"
"SQLAlchemy backend. This also means that different backends might have "
"different set of available filters."
msgstr ""
"每个模型后端应该有自己的一组过滤器实现。不能在非 SQLAlchemy 后端中使用 SQLAlchemy "
"模型的过滤器。这意味着不同的后端可能具有不同的可用过滤器集。"
#: ../../adding_a_new_model_backend.rst:171
msgid ""
"The filter is a class derived from "
":class:`~flask_admin.model.filters.BaseFilter` which implements at least "
"two methods:"
msgstr ""
"过滤器继承 :class:`~flask_admin.model.filters.BaseFilter` 类,"
"至少需要实现以下两个方法:"
#: ../../adding_a_new_model_backend.rst:173
msgid ":meth:`~flask_admin.model.filters.BaseFilter.apply`"
msgstr ":meth:`~flask_admin.model.filters.BaseFilter.apply`"
#: ../../adding_a_new_model_backend.rst:174
msgid ":meth:`~flask_admin.model.filters.BaseFilter.operation`"
msgstr ":meth:`~flask_admin.model.filters.BaseFilter.operation`"
#: ../../adding_a_new_model_backend.rst:176
msgid ""
"`apply` method accepts two parameters: `query` object and a value from "
"the client. Here you can add filtering logic for the filter type."
msgstr ""
"`apply` 方法允许两个参数:`query` 对象和来自客户端的值。"
"在这里,您可以为该过滤器类型添加过滤逻辑。"
#: ../../adding_a_new_model_backend.rst:179
msgid "Lets take SQLAlchemy model backend as an example:"
msgstr "让我们以 SQLAlchemy 模型后端为例:"
#: ../../adding_a_new_model_backend.rst:181
msgid ""
"All SQLAlchemy filters derive from "
":class:`~flask_admin.contrib.sqla.filters.BaseSQLAFilter` class."
msgstr ""
"所有 SQLAlchemy 过滤器都继承自 "
":class:`~flask_admin.contrib.sqla.filters.BaseSQLAFilter` 类。"
#: ../../adding_a_new_model_backend.rst:183
msgid ""
"Each filter implements one simple filter SQL operation (like, not like, "
"greater, etc) and accepts a column as input parameter."
msgstr ""
"每个过滤器实现一个简单的 SQL 过滤器操作 (like, not like, greater 等),"
"并接受列作为输入参数。"
#: ../../adding_a_new_model_backend.rst:186
msgid ""
"Whenever model view wants to apply a filter to a query object, it will "
"call `apply` method in a filter class with a query and value. Filter will"
" then apply real filter operation."
msgstr ""
"每当模型视图想要对 query 对象应用过滤器时,它将调用已传入 query 和值的过滤器类的 `apply` "
"方法。然后过滤器将进行实际的 SQL 过滤器操作。"
#: ../../adding_a_new_model_backend.rst:217
msgid ""
"Feel free ask questions if you have problems adding a new model backend. "
"Also, if you get stuck, try taking a look at the SQLAlchemy model backend"
" and use it as a reference."
msgstr ""
"如果您在添加新模型后端时遇到问题,请随时提出问题。此外,如果您遇到困难,"
"建议将 SQLAlchemy 模型后端的实现作为参考。"
# Advanced Functionality
# http://flask-admin.readthedocs.io/en/latest/advanced/
#
# Copyright (C) 2012-2015, Serge S. Koval
# This file is distributed under the same license as the flask-admin
# package.
# 1dot75cm <sensor.wen@gmail.com>, 2016.
#
msgid ""
msgstr ""
"Project-Id-Version: flask-admin 1.4.2\n"
"Report-Msgid-Bugs-To: https://github.com/sixu05202004/Flask-extensions-docs\n"
"POT-Creation-Date: 2016-11-25 03:00+0800\n"
"PO-Revision-Date: 2016-11-27 03:00+0800\n"
"Last-Translator: 1dot75cm <sensor.wen@gmail.com>\n"
"Language-Team: zh_CN <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.3.4\n"
#: ../../advanced.rst:4
msgid "Advanced Functionality"
msgstr "高级功能"
#: ../../advanced.rst:7
msgid "Enabling CSRF Protection"
msgstr "启用 CSRF 保护"
#: ../../advanced.rst:9
msgid ""
"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::"
msgstr ""
"要向 *ModelView* 实例生成的表单添加 CSRF 保护,请在 *ModelView* 子类中将 "
"*form_base_class* 参数值设为 SecureForm 类::"
#: ../../advanced.rst:18
msgid ""
"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."
msgstr ""
"SecureForm 需要 WTForms 2+。当表单提交时,它使用 WTForms SessionCSRF "
"类来生成和验证令牌。"
#: ../../advanced.rst:22
msgid "Localization With Flask-Babelex"
msgstr "使用 Flask-Babelex 本地化"
#: ../../advanced.rst:26
msgid ""
"Flask-Admin comes with translations for several languages. Enabling "
"localization is simple:"
msgstr ""
"Flask-Admin 提供多种语言的翻译。启用本地化非常简单:"
#: ../../advanced.rst:29
msgid ""
"Install `Flask-BabelEx <http://github.com/mrjoes/flask-babelex/>`_ to do "
"the heavy lifting. It's a fork of the `Flask-Babel "
"<http://github.com/mitshuhiko/flask-babel/>`_ package::"
msgstr ""
"安装 `Flask-BabelEx <http://github.com/mrjoes/flask-babelex/>`_ 扩展,"
"它是 `Flask-Babel <http://github.com/mitshuhiko/flask-babel/>`_ 的分支::"
#: ../../advanced.rst:35
msgid "Initialize Flask-BabelEx by creating instance of `Babel` class::"
msgstr "通过创建 `Babel` 类实例,初始化 Flask-BabelEx 扩展::"
#: ../../advanced.rst:43
msgid "Create a locale selector function::"
msgstr "创建区域选择器函数::"
#: ../../advanced.rst:51
msgid ""
"Now, you could try a French version of the application at: "
"`http://localhost:5000/admin/?lang=fr "
"<http://localhost:5000/admin/?lang=fr>`_."
msgstr ""
"现在,您能够访问法语版本的管理界面: "
"`http://localhost:5000/admin/?lang=fr "
"<http://localhost:5000/admin/?lang=fr>`_。"
#: ../../advanced.rst:53
msgid ""
"Go ahead and add your own logic to the locale selector function. The "
"application can store locale in a user profile, cookie, session, etc. It "
"can also use the `Accept-Language` header to make the selection "
"automatically."
msgstr ""
"继续,添加您的区域设置到语言选择器函数。应用程序可以将区域设置存储在"
"用户 profile, cookie, session 中。它还可以使用 `Accept-Language` 头"
"来自动选择语言。"
#: ../../advanced.rst:57
msgid ""
"If the built-in translations are not enough, look at the `Flask-BabelEx "
"documentation <https://pythonhosted.org/Flask-BabelEx/>`_ to see how you "
"can add your own."
msgstr ""
"如果内置的翻译不够,请查看 `Flask-BabelEx 文档 "
"<https://pythonhosted.org/Flask-BabelEx/>`_ 了解如何添加翻译。"
#: ../../advanced.rst:63
msgid "Managing Files & Folders"
msgstr "管理文件 & 目录"
#: ../../advanced.rst:67
msgid ""
"To manage static files instead of database records, Flask-Admin comes "
"with the FileAdmin plug-in. It gives you the ability to upload, delete, "
"rename, etc. You can use it by adding a FileAdmin view to your app::"
msgstr ""
"为了管理静态文件而不是数据库记录,Flask-Admin 附带了 FileAdmin 插件。"
"它使您能够上传,删除,重命名文件。您可以通过向应用程序添加 FileAdmin 视图来使用该功能::"
#: ../../advanced.rst:83
msgid ""
"FileAdmin also has out-of-the-box support for managing files located on a"
" Amazon Simple Storage Service bucket. To add it to your app::"
msgstr ""
"FileAdmin 还具有管理 Amazon Simple Storage 服务的文件的开箱支持。"
"将该功能添加到应用程序::"
#: ../../advanced.rst:93
msgid ""
"You can disable uploads, disable file deletion, restrict file uploads to "
"certain types, etc. Check :mod:`flask_admin.contrib.fileadmin` in the API"
" documentation for more details."
msgstr ""
"您可以配置禁用上传,禁用文件删除,限制上传文件的类型等功能。详细信息,请参阅 "
":mod:`flask_admin.contrib.fileadmin` API 文档。"
#: ../../advanced.rst:97
msgid "Adding new file backends"
msgstr "添加新文件后端"
#: ../../advanced.rst:99
msgid ""
"You can also implement your own storage backend by creating a class that "
"implements the same methods defined in the `LocalFileStorage` class. "
"Check :mod:`flask_admin.contrib.fileadmin` in the API documentation for "
"details on the methods."
msgstr ""
"您还可以通过继承 `LocalFileStorage` 类并重写其中的方法来实现自己的存储后端。"
"有关方法的详细信息,请参阅 :mod:`flask_admin.contrib.fileadmin` API 文档。"
#: ../../advanced.rst:104
msgid "Adding A Redis Console"
msgstr "添加 Redis 控制台"
#: ../../advanced.rst:108
msgid ""
"Another plug-in that's available is the Redis Console. If you have a "
"Redis instance running on the same machine as your app, you can::"
msgstr ""
"另一个可用的插件是 Redis 控制台。如果您的 Redis 实例与应用程序"
"在同一个节点上运行,您可以::"
#: ../../advanced.rst:122
msgid "Replacing Individual Form Fields"
msgstr "替换单个表单域"
#: ../../advanced.rst:126
msgid ""
"The `form_overrides` attribute allows you to replace individual fields "
"within a form. A common use-case for this would be to add a *What-You-"
"See-Is-What-You-Get* (WYSIWIG) editor, or to handle file / image uploads "
"that need to be tied to a field in your model."
msgstr ""
"`form_overrides` 属性允许您替换表单中的单个字段。一个常见的用例是添加一个 "
"What-You-See-Is-What-You-Get (WYSIWIG, 所见即所得) 编辑器,"
"或处理需要绑定到模型中的文件/图像上传字段。"
#: ../../advanced.rst:131
msgid "WYSIWIG Text Fields"
msgstr "WYSIWIG 文本字段"
#: ../../advanced.rst:132
msgid ""
"To handle complicated text content, you can use `CKEditor "
"<http://ckeditor.com/>`_ by subclassing some of the built-in WTForms "
"classes as follows::"
msgstr ""
"要处理复杂的文本内容,可以通过子类化一些内置的 WTForms 类来集成 "
"`CKEditor <http://ckeditor.com/>`_ 编辑器,示例如下::"
#: ../../advanced.rst:157
msgid ""
"For this to work, you would also need to create a template that extends "
"the default functionality by including the necessary CKEditor javascript "
"on the `create` and `edit` pages. Save this in "
"`templates/ckeditor.html`::"
msgstr ""
"为了使其工作,还需要创建一个模板,通过在 `create` 和 `edit` 页面包含必要的 "
"CKEditor javascript 来扩展默认功能。将其保存在 `templates/ckeditor.html` 中::"
#: ../../advanced.rst:169
msgid "File & Image Fields"
msgstr "文件 & 图片字段"
#: ../../advanced.rst:171
msgid ""
"Flask-Admin comes with a built-in "
":meth:`~flask_admin.form.upload.FileUploadField` and "
":meth:`~flask_admin.form.upload.ImageUploadField`. To make use of them, "
"you'll need to specify an upload directory and add them to the forms in "
"question. Image handling also requires you to have `Pillow "
"<https://pypi.python.org/pypi/Pillow/2.8.2>`_ installed if you need to do"
" any processing on the image files."
msgstr ""
"Flask-Admin 内置有 "
":meth:`~flask_admin.form.upload.FileUploadField` 和 "
":meth:`~flask_admin.form.upload.ImageUploadField`。"
"要使用它们,您需要指定一个上传目录,并将它们添加到表单中。"
"如果您需要对图像文件进行处理,则需要安装 `Pillow "
"<https://pypi.python.org/pypi/Pillow/>`_。"
#: ../../advanced.rst:177
msgid ""
"Have a look at the example at https://github.com/flask-admin/Flask-"
"Admin/tree/master/examples/forms."
msgstr ""
"请查看 https://github.com/flask-admin/Flask-Admin/"
"tree/master/examples/forms 示例。"
#: ../../advanced.rst:180
msgid ""
"If you are using the MongoEngine backend, Flask-Admin supports GridFS-"
"backed image and file uploads through WTForms fields. Documentation can "
"be found at :mod:`flask_admin.contrib.mongoengine.fields`."
msgstr ""
"如果您使用 MongoEngine 后端,Flask-Admin 支持通过 WTForms 字段上传的文件/图片,"
"保存在 GridFS 后端中。详细信息,请参阅 :mod:`flask_admin.contrib.mongoengine."
"fields` 文档。"
#: ../../advanced.rst:182
msgid ""
"If you just want to manage static files in a directory, without tying "
"them to a database model, then use the :ref:`File-Admin<file-admin>` "
"plug-in."
msgstr ""
"如果您只想管理目录中的静态文件,而不是将其绑定到数据库模型,"
"则使用 :ref:`File-Admin<file-admin>` 插件。"
#: ../../advanced.rst:186
msgid "Managing Geographical Models"
msgstr "管理地理模型"
#: ../../advanced.rst:190
msgid ""
"If you want to store spatial information in a GIS database, Flask-Admin "
"has you covered. The GeoAlchemy backend extends the SQLAlchemy backend "
"(just as `GeoAlchemy <https://geoalchemy-2.readthedocs.io/>`_ extends "
"SQLAlchemy) to give you a pretty and functional map-based editor for your"
" admin pages."
msgstr ""
"如果你想在 GIS 数据库中存储空间信息,Flask-Admin 同样支持。GeoAlchemy 后端扩展了 "
"SQLAlchemy 后端 (类似 `GeoAlchemy <https://geoalchemy-2.readthedocs.io/>`_ "
"扩展了 SQLAlchemy ),为您的管理页面提供一个漂亮且功能强大的基于地图的编辑器。"
#: ../../advanced.rst:195
msgid "Some notable features include:"
msgstr "一些显著的功能包括:"
#: ../../advanced.rst:197
msgid ""
"Maps are displayed using the amazing `Leaflet <http://leafletjs.com/>`_ "
"Javascript library, with map data from `Mapbox "
"<https://www.mapbox.com/>`_."
msgstr ""
"使用惊人的 `Leaflet <http://leafletjs.com/>`_ Javascript 库显示地图,"
"地图数据来自 `Mapbox <https://www.mapbox.com/>`_。"
#: ../../advanced.rst:199
msgid ""
"Geographic information, including points, lines and polygons, can be "
"edited interactively using `Leaflet.Draw "
"<https://github.com/Leaflet/Leaflet.draw>`_."
msgstr ""
"地理信息,包括点,线和多边形,可以使用 `Leaflet.Draw "
"<https://github.com/Leaflet/Leaflet.draw>`_ 交互式编辑。"
#: ../../advanced.rst:201
msgid ""
"Graceful fallback: `GeoJSON <http://geojson.org/>`_ data can be edited in"
" a ``<textarea>``, if the user has turned off Javascript."
msgstr ""
"后备支持:如果用户已关闭 Javascript,则可以在 ``<textarea>`` 中编辑 "
"`GeoJSON <http://geojson.org/>`_ 数据。"
#: ../../advanced.rst:203
msgid ""
"Works with a `Geometry "
"<https://geoalchemy-2.readthedocs.io/en/latest/types.html#geoalchemy2.types.Geometry>`_"
" SQL field that is integrated with `Shapely "
"<http://toblerity.org/shapely/>`_ objects."
msgstr ""
"使用与 `Shapely <http://toblerity.org/shapely/>`_ 对象集成的 `Geometry "
"<https://geoalchemy-2.readthedocs.io/en/latest/types.html#geoalchemy2.types.Geometry>`_"
" SQL 字段。"
#: ../../advanced.rst:205
msgid ""
"To get started, define some fields on your model using GeoAlchemy's "
"*Geometry* field. Next, add model views to your interface using the "
"ModelView class from the GeoAlchemy backend, rather than the usual "
"SQLAlchemy backend::"
msgstr ""
"要开始使用,请使用 GeoAlchemy 的 *Geometry* 字段在模型上定义一些字段。"
"接下来,使用来自 GeoAlchemy 后端的 ModelView 类,而不是通常的 SQLAlchemy "
"后端,将模型视图添加到您的接口::"
#: ../../advanced.rst:220
msgid ""
"Some of the Geometry field types that are available include: \"POINT\", "
"\"MULTIPOINT\", \"POLYGON\", \"MULTIPOLYGON\", \"LINESTRING\" and "
"\"MULTILINESTRING\"."
msgstr ""
"可用的 Geometry 字段类型包括: \"POINT\", \"MULTIPOINT\", \"POLYGON\", "
"\"MULTIPOLYGON\", \"LINESTRING\" 和 \"MULTILINESTRING\"。"
#: ../../advanced.rst:223
msgid ""
"Have a look at https://github.com/flask-admin/flask-"
"admin/tree/master/examples/geo_alchemy to get started."
msgstr ""
"请查看 https://github.com/flask-admin/flask-admin/"
"tree/master/examples/geo_alchemy 示例以开始使用。"
#: ../../advanced.rst:227
msgid "Loading Tiles From Mapbox"
msgstr "从 Mapbox 加载地图"
#: ../../advanced.rst:229
msgid ""
"To have map data display correctly, you'll have to sign up for an account"
" at https://www.mapbox.com/ and include some credentials in your "
"application's config::"
msgstr ""
"要正确显示地图数据,您必须在 https://www.mapbox.com/ 注册帐户,"
"并在应用程序的配置中包含一些凭据::"
#: ../../advanced.rst:237
msgid ""
"Leaflet supports loading map tiles from any arbitrary map tile provider, "
"but at the moment, Flask-Admin only supports Mapbox. If you want to use "
"other providers, make a pull request!"
msgstr ""
"Leaflet 支持从任意地图图块 provider 程序加载地图图块,但目前 Flask-Admin 仅支持 "
"Mapbox。如果你想使用其他地图源,请提交 pull request!"
#: ../../advanced.rst:242
msgid "Limitations"
msgstr "限制"
#: ../../advanced.rst:244
msgid ""
"There's currently no way to sort, filter, or search on geometric fields "
"in the admin. It's not clear that there's a good way to do so. If you "
"have any ideas or suggestions, make a pull request!"
msgstr ""
"目前没有办法对 admin 中的 geometric 字段进行排序,过滤或搜索。不知道"
"有没有好方法解决该问题。如果您有任何想法或建议,请提出 pull request!"
#: ../../advanced.rst:249
msgid "Customising Builtin Forms Via Rendering Rules"
msgstr "通过渲染规则定制内置表单"
#: ../../advanced.rst:253
msgid ""
"Before version 1.0.7, all model backends were rendering the *create* and "
"*edit* forms using a special Jinja2 macro, which was looping over the "
"fields of a WTForms form object and displaying them one by one. This "
"works well, but it is difficult to customize."
msgstr ""
"在 1.0.7 版本前,所有模型后端都使用特殊的 Jinja2 宏来渲染 `create` 和 `edit` 表单,"
"该宏在 WTForms 表单对象的字段上循环,并逐个显示它们。这很好,但是很难定制。"
#: ../../advanced.rst:257
msgid ""
"Starting from version 1.0.7, Flask-Admin supports form rendering rules, "
"to give you fine grained control of how the forms for your modules should"
" be displayed."
msgstr ""
"从 1.0.7 版本开始,Flask-Admin 支持表单渲染规则,以便您对模块中的表单如何显示"
"进行细粒度的控制。"
#: ../../advanced.rst:260
msgid ""
"The basic idea is pretty simple: the customizable rendering rules replace"
" a static macro, so you can tell Flask-Admin how each form should be "
"rendered. As an extension, however, the rendering rules also let you do a"
" bit more: You can use them to output HTML, call Jinja2 macros, render "
"fields, and so on."
msgstr ""
"基本思想很简单:可自定义的渲染规则替换了静态宏,所以你可以告诉 "
"Flask-Admin 如何渲染每个表单。作为一个扩展,渲染规则还可以做更多事:"
"你可以使用它们来输出 HTML,调用 Jinja2 宏,渲染字段等。"
#: ../../advanced.rst:264
msgid ""
"Essentially, form rendering rules separate the form rendering from the "
"form definition. For example, it no longer matters in which sequence your"
" form fields are defined."
msgstr ""
"基本上,表单渲染规则将表单渲染与表单定义分开。"
"明显的改善是,您的表单字段定义的顺序不再重要。"
#: ../../advanced.rst:267
msgid ""
"To start using the form rendering rules, put a list of form field names "
"into the `form_create_rules` property one of your admin views::"
msgstr ""
"要开始使用表单渲染规则,请在管理视图中,"
"将表单字段名列表放入 `form_create_rules` 属性中::"
#: ../../advanced.rst:273
msgid ""
"In this example, only three fields will be rendered and `email` field "
"will be above other two fields."
msgstr ""
"在此示例中,将仅渲染三个字段,并且 `email` 字段将高于其他两个字段。"
#: ../../advanced.rst:275
msgid ""
"Whenever Flask-Admin sees a string value in `form_create_rules`, it "
"automatically assumes that it is a form field reference and creates a "
":class:`flask_admin.form.rules.Field` class instance for that field."
msgstr ""
"每当 Flask-Admin 在 `form_create_rules` 中查看字符串值时,"
"它会假定值是一个表单字段引用,并为该字段创建一个 "
":class:`flask_admin.form.rules.Field` 类实例。"
#: ../../advanced.rst:278
msgid ""
"Let's say we want to display some text between the `email` and "
"`first_name` fields. This can be accomplished by using the "
":class:`flask_admin.form.rules.Text` class::"
msgstr ""
"假设我们要在 `email` 和 `first_name` 字段之间显示一些文本。"
"可以通过使用 :class:`flask_admin.form.rules.Text` 类来实现::"
#: ../../advanced.rst:287
msgid "Built-in Rules"
msgstr "内置规则"
#: ../../advanced.rst:289
msgid ""
"Flask-Admin comes with few built-in rules that can be found in the "
":mod:`flask_admin.form.rules` module:"
msgstr ""
"Flask-Admin 有一些内置规则,可以在 :mod:`flask_admin.form.rules` 模块中找到:"
#: ../../advanced.rst:292
msgid "Form Rendering Rule"
msgstr "表单渲染规则"
#: ../../advanced.rst:292
msgid "Description"
msgstr "描述"
#: ../../advanced.rst:294
msgid ":class:`flask_admin.form.rules.BaseRule`"
msgstr ":class:`flask_admin.form.rules.BaseRule`"
#: ../../advanced.rst:294
msgid "All rules derive from this class"
msgstr "所有规则都派生自该类"
#: ../../advanced.rst:295
msgid ":class:`flask_admin.form.rules.NestedRule`"
msgstr ":class:`flask_admin.form.rules.NestedRule`"
#: ../../advanced.rst:295
msgid "Allows rule nesting, useful for HTML containers"
msgstr "允许规则嵌套,适用于 HTML 容器"
#: ../../advanced.rst:296
msgid ":class:`flask_admin.form.rules.Text`"
msgstr ":class:`flask_admin.form.rules.Text`"
#: ../../advanced.rst:296
msgid "Simple text rendering rule"
msgstr "简单的文本渲染规则"
#: ../../advanced.rst:297
msgid ":class:`flask_admin.form.rules.HTML`"
msgstr ":class:`flask_admin.form.rules.HTML`"
#: ../../advanced.rst:297
msgid "Same as `Text` rule, but does not escape the text"
msgstr "与 `Text` 规则相同,但不转义文本"
#: ../../advanced.rst:298
msgid ":class:`flask_admin.form.rules.Macro`"
msgstr ":class:`flask_admin.form.rules.Macro`"
#: ../../advanced.rst:298
msgid "Calls macro from current Jinja2 context"
msgstr "从当前 Jinja2 上下文调用宏"
#: ../../advanced.rst:299
msgid ":class:`flask_admin.form.rules.Container`"
msgstr ":class:`flask_admin.form.rules.Container`"
#: ../../advanced.rst:299
msgid "Wraps child rules into container rendered by macro"
msgstr "将子规则包含到由宏渲染的容器中"
#: ../../advanced.rst:300
msgid ":class:`flask_admin.form.rules.Field`"
msgstr ":class:`flask_admin.form.rules.Field`"
#: ../../advanced.rst:300
msgid "Renders single form field"
msgstr "渲染单个表单字段"
#: ../../advanced.rst:301
msgid ":class:`flask_admin.form.rules.Header`"
msgstr ":class:`flask_admin.form.rules.Header`"
#: ../../advanced.rst:301
msgid "Renders form header"
msgstr "渲染表单标头"
#: ../../advanced.rst:302
msgid ":class:`flask_admin.form.rules.FieldSet`"
msgstr ":class:`flask_admin.form.rules.FieldSet`"
#: ../../advanced.rst:302
msgid "Renders form header and child rules"
msgstr "渲染表单标头和主体规则"
#: ../../advanced.rst:308
msgid "Using Different Database Backends"
msgstr "使用不同的数据库后端"
#: ../../advanced.rst:312
msgid ""
"Other than SQLAlchemy... There are five different backends for you to "
"choose from, depending on which database you would like to use for your "
"application. If, however, you need to implement your own database "
"backend, have a look at :ref:`adding-model-backend`."
msgstr ""
"除了 SQLAlchemy... 有五个不同的后端供您选择,具体取决于您的应用程序使用的数据库。"
"如果您需要实现自己的数据库后端,请查看 :ref:`adding-model-backend`。"
#: ../../advanced.rst:316
msgid ""
"If you don't know where to start, but you're familiar with relational "
"databases, then you should probably look at using `SQLAlchemy`_. It is a "
"full-featured toolkit, with support for SQLite, PostgreSQL, MySQL, Oracle"
" and MS-SQL amongst others. It really comes into its own once you have "
"lots of data, and a fair amount of relations between your data models. If"
" you want to track spatial data like latitude/longitude points, you "
"should look into `GeoAlchemy`_, as well."
msgstr ""
"如果您熟悉关系型数据库,那么应该使用 `SQLAlchemy`_。它是一个全功能的工具包,"
"支持 SQLite, PostgreSQL, MySQL, Oracle 和 MS-SQL 等数据库。如果您有很多"
"数据,并且数据模型之间有很多关系,应该使用 SQLAlchemy。如果要跟踪空间数据 "
"(如纬度/经度点),则应使用 `GeoAlchemy`_。"
#: ../../advanced.rst:323
msgid "SQLAlchemy"
msgstr "SQLAlchemy"
#: ../../advanced.rst:325
msgid "Notable features:"
msgstr "特点:"
#: ../../advanced.rst:327
msgid "SQLAlchemy 0.6+ support"
msgstr "SQLAlchemy 0.6+ 支持"
#: ../../advanced.rst:328
msgid "Paging, sorting, filters"
msgstr "分页, 排序, 过滤"
#: ../../advanced.rst:329
msgid "Proper model relationship handling"
msgstr "正确的模型关系处理"
#: ../../advanced.rst:330
msgid "Inline editing of related models"
msgstr "相关模型的行内编辑"
#: ../../advanced.rst:332
msgid "**Multiple Primary Keys**"
msgstr "**多主键**"
#: ../../advanced.rst:334
msgid ""
"Flask-Admin has limited support for models with multiple primary keys. It"
" only covers specific case when all but one primary keys are foreign keys"
" to another model. For example, model inheritance following this "
"convention."
msgstr ""
"Flask-Admin 对多主键模型的支持有限。它只支持一个主键"
"是另一个模型的外键的特殊情况。例如,遵循此惯例的模型继承。"
#: ../../advanced.rst:338
msgid "Let's Model a car with its tyres::"
msgstr "让我们看看汽车及其轮胎的模型::"
#: ../../advanced.rst:355
msgid ""
"A specific tyre is identified by using the two primary key columns of the"
" ``Tyre`` class, of which the ``car_id`` key is itself a foreign key to "
"the class ``Car``."
msgstr ""
"通过使用 ``Tire`` 类的两个主键列来识别特定轮胎,"
"其中 ``car_id`` 键本身是 ``Car`` 类的外键。"
#: ../../advanced.rst:358
msgid ""
"To be able to CRUD the ``Tyre`` class, you need to enumerate columns when"
" defining the AdminView::"
msgstr ""
"为了能够对 ``Tire`` 类执行 CRUD,你需要在定义 AdminView 时枚举列::"
#: ../../advanced.rst:363
msgid ""
"The ``form_columns`` needs to be explicit, as per default only one "
"primary key is displayed."
msgstr ""
"``form_columns`` 需要显式指定,默认情况下只显示一个主键。"
#: ../../advanced.rst:365
msgid ""
"When having multiple primary keys, **no** validation for uniqueness "
"*prior* to saving of the object will be done. Saving a model that "
"violates a unique-constraint leads to an Sqlalchemy-Integrity-Error. In "
"this case, ``Flask-Admin`` displays a proper error message and you can "
"change the data in the form. When the application has been started with "
"``debug=True`` the ``werkzeug`` debugger will catch the exception and "
"will display the stacktrace."
msgstr ""
"当有多个主键时,在保存对象之前 **不会** 进行唯一性验证。保存违反唯一约束的模型"
"会导致 Sqlalchemy-Integrity-Error。在这种情况下,``Flask-Admin`` 显示正"
"确的错误消息,您可以更改表单中的数据。当应用程序以 ``debug=True`` 启动时, "
"``werkzeug`` 调试器将捕获异常并显示栈跟踪信息。"
#: ../../advanced.rst:371
msgid "MongoEngine"
msgstr "MongoEngine"
#: ../../advanced.rst:373
msgid ""
"If you're looking for something simpler than SQLAlchemy, and your data "
"models are reasonably self-contained, then `MongoDB "
"<https://www.mongodb.org/>`_, a popular *NoSQL* database, could be a "
"better option."
msgstr ""
"如果你需要比 SQLAlchemy 更简单的东西,你的数据模型是合理的自包含类型,"
"那么 `MongoDB <https://www.mongodb.org/>`_ 这个流行的 *NoSQL* 数"
"据库,或许是一个更好的选择。"
#: ../../advanced.rst:377
msgid ""
"`MongoEngine <http://mongoengine.org/>`_ is a python wrapper for MongoDB."
" For an example of using MongoEngine with Flask-Admin, see "
"https://github.com/flask-admin/flask-"
"admin/tree/master/examples/mongoengine."
msgstr ""
"`MongoEngine <http://mongoengine.org/>`_ 是 MongoDB 的 Python 封装。"
"在 Flask-Admin 中使用 MongoEngine 的示例,请参阅 https://github.com/"
"flask-admin/flask-admin/tree/master/examples/mongoengine。"
#: ../../advanced.rst:382 ../../advanced.rst:403
msgid "Features:"
msgstr "特性:"
#: ../../advanced.rst:384
msgid "MongoEngine 0.7+ support"
msgstr "MongoEngine 0.7+ 支持"
#: ../../advanced.rst:385
msgid "Paging, sorting, filters, etc"
msgstr "分页,排序,过滤等"
#: ../../advanced.rst:386
msgid "Supports complex document structure (lists, subdocuments and so on)"
msgstr "支持复杂的文档结构 (列表,子文档等等)"
#: ../../advanced.rst:387
msgid "GridFS support for file and image uploads"
msgstr "GridFS 支持存储上传的文件/图片"
#: ../../advanced.rst:389
msgid ""
"In order to use MongoEngine integration, install the `Flask-MongoEngine "
"<https://flask-mongoengine.readthedocs.io>`_ package. Flask-Admin uses "
"form scaffolding from it."
msgstr ""
"为了集成 MongoEngine,需要安装 `Flask-MongoEngine "
"<https://flask-mongoengine.readthedocs.io>`_ 包。"
"Flask-Admin 使用其中的表单脚手架。"
#: ../../advanced.rst:393 ../../advanced.rst:412
msgid "Known issues:"
msgstr "已知问题:"
#: ../../advanced.rst:395
msgid ""
"Search functionality can't split query into multiple terms due to "
"MongoEngine query language limitations"
msgstr ""
"由于 MongoEngine 查询语言的限制,搜索功能不能将查询拆分为多个条件"
#: ../../advanced.rst:398
msgid ""
"For more, check the :class:`~flask_admin.contrib.mongoengine` API "
"documentation."
msgstr ""
"更多信息,请参阅 :class:`~flask_admin.contrib.mongoengine` API 文档。"
#: ../../advanced.rst:401
msgid "Peewee"
msgstr "Peewee"
#: ../../advanced.rst:405
msgid "Peewee 2.x+ support;"
msgstr "Peewee 2.x+ 支持"
#: ../../advanced.rst:406
msgid "Paging, sorting, filters, etc;"
msgstr "分页,排序,过滤等"
#: ../../advanced.rst:407
msgid "Inline editing of related models;"
msgstr "相关模型的行内编辑"
#: ../../advanced.rst:409
msgid ""
"In order to use peewee integration, you need to install two additional "
"Python packages: `peewee <http://docs.peewee-orm.com/>`_ and `wtf-peewee "
"<https://github.com/coleifer/wtf-peewee/>`_."
msgstr ""
"为了使用 peewee,您需要安装 2 个 Python 包:`peewee "
"<http://docs.peewee-orm.com/>`_ 和 `wtf-peewee "
"<https://github.com/coleifer/wtf-peewee/>`_。"
#: ../../advanced.rst:414
msgid ""
"Many-to-Many model relations are not supported: there's no built-in way "
"to express M2M relation in Peewee"
msgstr ""
"不支持多对多模型关系:在 Peewee 中没有内置的方式来表达 M2M 关系"
#: ../../advanced.rst:416
msgid ""
"For more, check the :class:`~flask_admin.contrib.peewee` API "
"documentation. Or look at the Peewee example at https://github.com/flask-"
"admin/flask-admin/tree/master/examples/peewee."
msgstr ""
"更多信息,请参阅 :class:`~flask_admin.contrib.peewee` API 文档。"
"或查看 Peewee 使用示例 https://github.com/flask-admin/flask-admin/"
"tree/master/examples/peewee。"
#: ../../advanced.rst:420
msgid "PyMongo"
msgstr "PyMongo"
#: ../../advanced.rst:422
msgid "The bare minimum you have to provide for Flask-Admin to work with PyMongo:"
msgstr "Flask-Admin 使用 PyMongo 的最小要求:"
#: ../../advanced.rst:424
msgid "A list of columns by setting `column_list` property"
msgstr "设置 `column_list` 属性,值为字段列表"
#: ../../advanced.rst:425
msgid "Provide form to use by setting `form` property"
msgstr "设置 `form` 属性,值为要使用的表单"
#: ../../advanced.rst:426
msgid ""
"When instantiating :class:`flask_admin.contrib.pymongo.ModelView` class, "
"you have to provide PyMongo collection object"
msgstr ""
"当实例化 :class:`flask_admin.contrib.pymongo.ModelView` 类时,"
"你必须提供 PyMongo 集合对象"
#: ../../advanced.rst:428
msgid "This is minimal PyMongo view::"
msgstr "最简单的 PyMongo 视图:"
#: ../../advanced.rst:444
msgid "On top of that you can add sortable columns, filters, text search, etc."
msgstr "除此之外,您还可以添加可排序的列,过滤器,文本搜索等。"
#: ../../advanced.rst:446
msgid ""
"For more, check the :class:`~flask_admin.contrib.pymongoe` API "
"documentation. Or look at the Peewee example at https://github.com/flask-"
"admin/flask-admin/tree/master/examples/pymongo."
msgstr ""
"更多信息,请参阅 :class:`~flask_admin.contrib.pymongoe` API 文档。"
"或查看 PyMongo 使用示例 https://github.com/flask-admin/flask-admin/"
"tree/master/examples/pymongo。"
#: ../../advanced.rst:450
msgid "Migrating From Django"
msgstr "从 Django 迁移"
#: ../../advanced.rst:454
msgid ""
"If you are used to `Django <https://www.djangoproject.com/>`_ and the "
"*django-admin* package, you will find Flask-Admin to work slightly "
"different from what you would expect."
msgstr ""
"如果你习惯了 `Django <https://www.djangoproject.com/>`_ "
"和 *django-admin* 包,你会发现 Flask-Admin 的工作方式"
"与你期望的略有不同。"
#: ../../advanced.rst:458
msgid "Design Philosophy"
msgstr "设计哲学"
#: ../../advanced.rst:460
msgid ""
"In general, Django and *django-admin* strives to make life easier by "
"implementing sensible defaults. So a developer will be able to get an "
"application up in no time, but it will have to conform to most of the "
"defaults. Of course it is possible to customize things, but this often "
"requires a good understanding of what's going on behind the scenes, and "
"it can be rather tricky and time-consuming."
msgstr ""
"一般来说,Django 和 *django-admin* 有合理的默认值。因此,开发人员"
"能够立即获得应用程序,但它必须符合大多数默认值。如果需要定制,需要深刻的"
"理解后端的处理逻辑,这会相当耗时。"
#: ../../advanced.rst:465
msgid ""
"The design philosophy behind Flask is slightly different. It embraces the"
" diversity that one tends to find in web applications by not forcing "
"design decisions onto the developer. Rather than making it very easy to "
"build an application that *almost* solves your whole problem, and then "
"letting you figure out the last bit, Flask aims to make it possible for "
"you to build the *whole* application. It might take a little more effort "
"to get started, but once you've got the hang of it, the sky is the "
"limit... Even when your application is a little different from most other"
" applications out there on the web."
msgstr ""
"Flask 背后的设计理念略有不同。它倾向于使 web 应用程序更灵活,而不是"
"强制设计所有方面。Django 使您可以很容易构建应用程序,几乎替您解决了"
"所有问题;Flask 旨在使您控制构建整个应用程序。它需要学习更多内容,"
"一旦您了解了 Flask,您就可以开发任何类型的 Web 应用程序。"
#: ../../advanced.rst:472
msgid ""
"Flask-Admin follows this same design philosophy. So even though it "
"provides you with several tools for getting up & running quickly, it will"
" be up to you, as a developer, to tell Flask-Admin what should be "
"displayed and how. Even though it is easy to get started with a simple "
"`CRUD <http://en.wikipedia.org/wiki/Create,_read,_update_and_delete>`_ "
"interface for each model in your application, Flask-Admin doesn't fix you"
" to this approach, and you are free to define other ways of interacting "
"with some, or all, of your models."
msgstr ""
"Flask-Admin 遵循同样的设计理念。因此,即使它为您提供了几种快速启动和"
"运行的工具,作为开发人员,还是应该由您告诉 Flask-Admin 应该显示什么"
"以及如何显示。即使可以很容易的为应用程序的每个模型构建一个简单的 "
"`CRUD <http://en.wikipedia.org/wiki/Create,_read,_update_and_delete>`_ "
"接口,Flask-Admin 也不能完全解决所有问题,您可以灵活的定义与模块的交互方法,"
"来实现所有功能。"
#: ../../advanced.rst:478
msgid ""
"Due to Flask-Admin supporting more than one ORM (SQLAlchemy, MongoEngine,"
" Peewee, raw pymongo), the developer is even free to mix different model "
"types into one application by instantiating appropriate CRUD classes."
msgstr ""
"由于 Flask-Admin 支持多种 ORM (SQLAlchemy, MongoEngine, Peewee, raw pymongo),"
"开发人员甚至可以通过实例化相应的 CRUD 类,将不同的模型类型混合到一个应用程序中。"
#: ../../advanced.rst:481
msgid ""
"Here is a list of some of the configuration properties that are made "
"available by Flask-Admin and the SQLAlchemy backend. You can also see "
"which *django-admin* properties they correspond to:"
msgstr ""
"以下是 Flask-Admin 和 SQLAlchemy 后端提供的一些配置属性的列表。"
"您还可以查看它们对应的 *django-admin* 属性:"
#: ../../advanced.rst:485
msgid "Django"
msgstr "Django"
#: ../../advanced.rst:485
msgid "Flask-Admin"
msgstr "Flask-Admin"
#: ../../advanced.rst:487
msgid "actions"
msgstr "actions"
#: ../../advanced.rst:487
msgid ":attr:`~flask_admin.actions`"
msgstr ":attr:`~flask_admin.actions`"
#: ../../advanced.rst:488
msgid "exclude"
msgstr "exclude"
#: ../../advanced.rst:488
msgid ":attr:`~flask_admin.model.BaseModelView.form_excluded_columns`"
msgstr ":attr:`~flask_admin.model.BaseModelView.form_excluded_columns`"
#: ../../advanced.rst:489
msgid "fields"
msgstr "fields"
#: ../../advanced.rst:489
msgid ":attr:`~flask_admin.model.BaseModelView.form_columns`"
msgstr ":attr:`~flask_admin.model.BaseModelView.form_columns`"
#: ../../advanced.rst:490
msgid "form"
msgstr "form"
#: ../../advanced.rst:490
msgid ":attr:`~flask_admin.model.BaseModelView.form`"
msgstr ":attr:`~flask_admin.model.BaseModelView.form`"
#: ../../advanced.rst:491
msgid "formfield_overrides"
msgstr "formfield_overrides"
#: ../../advanced.rst:491
msgid ":attr:`~flask_admin.model.BaseModelView.form_args`"
msgstr ":attr:`~flask_admin.model.BaseModelView.form_args`"
#: ../../advanced.rst:492
msgid "inlines"
msgstr "inlines"
#: ../../advanced.rst:492
msgid ":attr:`~flask_admin.contrib.sqla.ModelView.inline_models`"
msgstr ":attr:`~flask_admin.contrib.sqla.ModelView.inline_models`"
#: ../../advanced.rst:493
msgid "list_display"
msgstr "list_display"
#: ../../advanced.rst:493
msgid ":attr:`~flask_admin.model.BaseModelView.column_list`"
msgstr ":attr:`~flask_admin.model.BaseModelView.column_list`"
#: ../../advanced.rst:494
msgid "list_filter"
msgstr "list_filter"
#: ../../advanced.rst:494
msgid ":attr:`~flask_admin.contrib.sqla.ModelView.column_filters`"
msgstr ":attr:`~flask_admin.contrib.sqla.ModelView.column_filters`"
#: ../../advanced.rst:495
msgid "list_per_page"
msgstr "list_per_page"
#: ../../advanced.rst:495
msgid ":attr:`~flask_admin.model.BaseModelView.page_size`"
msgstr ":attr:`~flask_admin.model.BaseModelView.page_size`"
#: ../../advanced.rst:496
msgid "search_fields"
msgstr "search_fields"
#: ../../advanced.rst:496
msgid ":attr:`~flask_admin.model.BaseModelView.column_searchable_list`"
msgstr ":attr:`~flask_admin.model.BaseModelView.column_searchable_list`"
#: ../../advanced.rst:497
msgid "add_form_template"
msgstr "add_form_template"
#: ../../advanced.rst:497
msgid ":attr:`~flask_admin.model.BaseModelView.create_template`"
msgstr ":attr:`~flask_admin.model.BaseModelView.create_template`"
#: ../../advanced.rst:498
msgid "change_form_template"
msgstr "change_form_template"
#: ../../advanced.rst:498
msgid ":attr:`~flask_admin.model.BaseModelView.change_form_template`"
msgstr ":attr:`~flask_admin.model.BaseModelView.change_form_template`"
#: ../../advanced.rst:501
msgid ""
"You might want to check :class:`~flask_admin.model.BaseModelView` for "
"basic model configuration options (reused by all model backends) and "
"specific backend documentation, for example "
":class:`~flask_admin.contrib.sqla.ModelView`. There's much more than what"
" is displayed in this table."
msgstr ""
"您可能需要查看 :class:`~flask_admin.model.BaseModelView` "
"的基本模型配置选项 (由所有模型后端重用) 和特定的后端文档,例如 "
":class:`~flask_admin.contrib.sqla.ModelView`。了解更多的"
"模型配置选项。"
#: ../../advanced.rst:507
msgid "Overriding the Form Scaffolding"
msgstr "覆盖表单脚手架"
#: ../../advanced.rst:511
msgid ""
"If you don't want to the use the built-in Flask-Admin form scaffolding "
"logic, you are free to roll your own by simply overriding "
":meth:`~flask_admin.model.base.scaffold_form`. For example, if you use "
"`WTForms-Alchemy <https://github.com/kvesteri/wtforms-alchemy>`_, you "
"could put your form generation code into a `scaffold_form` method in your"
" `ModelView` class."
msgstr ""
"如果你不想使用 Flask-Admin 内置的表单框架逻辑,你可以通过简单覆盖 "
":meth:`~flask_admin.model.base.scaffold_form` 来自由滚动。例如,如果使用 "
"`WTForms-Alchemy <https://github.com/kvesteri/wtforms-alchemy>`_,您"
"可以将您的表单生成代码放入您的 `ModelView` 类中的 `scaffold_form` 方法。"
#: ../../advanced.rst:516
msgid ""
"For SQLAlchemy, if the `synonym_property` does not return a SQLAlchemy "
"field, then Flask-Admin won't be able to figure out what to do with it, "
"so it won't generate a form field. In this case, you would need to "
"manually contribute your own field::"
msgstr ""
"对于 SQLAlchemy,如果 `synonym_property` 不返回 SQLAlchemy 字段,那么 "
"Flask-Admin 将不知道该如何生成表单字段。在这种情况下,您需要手动提供自己的字段::"
#: ../../advanced.rst:526
msgid "Customizing Batch Actions"
msgstr "自定义批处理操作"
#: ../../advanced.rst:530
msgid ""
"If you want to add other batch actions to the list view, besides the "
"default delete action, then you can define a function that implements the"
" desired logic and wrap it with the `@action` decorator."
msgstr ""
"如果要向列表视图添加其他批处理操作,除了默认的删除操作,您可以"
"定义一个实现所需逻辑的函数,并使用 `@action` 装饰器将其包装。"
#: ../../advanced.rst:533
msgid ""
"The `action` decorator takes three parameters: `name`, `text` and "
"`confirmation`. While the wrapped function should accept only one "
"parameter - `ids`::"
msgstr ""
"`action` 装饰器需要三个参数: `name`, `text` 和 `confirmation`。"
"而被包装的函数只接受一个 `ids` 参数::"
This source diff could not be displayed because it is too large. You can view the blob instead.
# Changelog
# http://flask-admin.readthedocs.io/en/latest/changelog/
#
# Copyright (C) 2012-2015, Serge S. Koval
# This file is distributed under the same license as the flask-admin
# package.
# 1dot75cm <sensor.wen@gmail.com>, 2016.
#
msgid ""
msgstr ""
"Project-Id-Version: flask-admin 1.4.2\n"
"Report-Msgid-Bugs-To: https://github.com/sixu05202004/Flask-extensions-docs\n"
"POT-Creation-Date: 2016-11-25 03:00+0800\n"
"PO-Revision-Date: 2016-11-25 03:00+0800\n"
"Last-Translator: 1dot75cm <sensor.wen@gmail.com>\n"
"Language-Team: zh_CN <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.3.4\n"
#: ../../changelog.rst:2
msgid "Changelog"
msgstr "变更日志"
#: ../../changelog.rst:5
msgid "1.4.2"
msgstr "1.4.2"
#: ../../changelog.rst:7
msgid ""
"Small bug fix release. Fixes regression that prevented usage of "
"\"virtual\" columns with a custom formatter."
msgstr ""
"修复小错误。修复阻止使用自定义格式的 \"虚拟\" 列的用法。"
#: ../../changelog.rst:10
msgid "1.4.1"
msgstr "1.4.1"
#: ../../changelog.rst:12
msgid "Official Python 3.5 support"
msgstr "官方 Python 3.5 支持"
#: ../../changelog.rst:13
msgid "Customizable row actions"
msgstr "可自定义的行操作"
#: ../../changelog.rst:14
msgid "Tablib support (exporting to XLS, XLSX, CSV, etc)"
msgstr "Tablib 支持 (导出到 XLS, XLSX, CSV 等)"
#: ../../changelog.rst:15
msgid "Updated external dependencies (jQuery, x-editable, etc)"
msgstr "更新外部依赖 (jQuery, x-editable 等)"
#: ../../changelog.rst:16
msgid "Added settings that allows exceptions to be raised on view errors"
msgstr "添加了允许在视图错误时引发异常的设置"
#: ../../changelog.rst:17 ../../changelog.rst:30 ../../changelog.rst:43
msgid "Bug fixes"
msgstr "Bug 修复"
#: ../../changelog.rst:20
msgid "1.4.0"
msgstr "1.4.0"
#: ../../changelog.rst:22
msgid "Updated and reworked documentation"
msgstr "更新和重做文档"
#: ../../changelog.rst:23
msgid ""
"FileAdmin went through minor refactoring and now supports remote file "
"systems. Comes with the new, optional, AWS S3 file management interface"
msgstr ""
"重构 FileAdmin,现在支持远程文件系统。提供新的,可选的 AWS S3 文件管理界面"
#: ../../changelog.rst:24
msgid "Configurable CSV export for model views"
msgstr "可配置 CSV 导出模型视图"
#: ../../changelog.rst:25
msgid ""
"Added overridable URL generation logic. Allows using custom URLs with "
"parameters for administrative views"
msgstr ""
"添加了可覆盖的网址生成逻辑。允许使用包含管理视图参数的自定义网址"
#: ../../changelog.rst:26
msgid ""
"Added column_display_actions to ModelView control visibility of the "
"action column without overriding the template"
msgstr ""
"将 column_display_actions 添加到 ModelView 控制操作列的可见性,而不覆盖模板"
#: ../../changelog.rst:27
msgid "Added support for the latest MongoEngine"
msgstr "增加了对最新 MongoEngine 的支持"
#: ../../changelog.rst:28
msgid "New SecureForm base class for easier CSRF validation"
msgstr "新的 SecureForm 基类,更容易进行 CSRF 验证"
#: ../../changelog.rst:29
msgid "Lots of translation-related fixes and updated translations"
msgstr "许多与翻译相关的修复,并更新翻译"
#: ../../changelog.rst:33
msgid "1.3.0"
msgstr "1.3.0"
#: ../../changelog.rst:35
msgid "New feature: Edit models in the list view in a popup"
msgstr "新功能:在弹出式窗口中的列表视图中编辑模型"
#: ../../changelog.rst:36
msgid "New feature: Read-only model details view"
msgstr "新功能:只读模型详细信息视图"
#: ../../changelog.rst:37
msgid "Fixed XSS in column_editable_list values"
msgstr "修正了 column_editable_list 值中的 XSS"
#: ../../changelog.rst:38
msgid "Improved navigation consistency in model create and edit views"
msgstr "改进模型创建和编辑视图中的导航一致性"
#: ../../changelog.rst:39
msgid "Ability to choose page size in model list view"
msgstr "能够在模型列表视图中选择页面大小"
#: ../../changelog.rst:40
msgid "Updated client-side dependencies (jQuery, Select2, etc)"
msgstr "更新客户端依赖关系 (jQuery, Select2 等)"
#: ../../changelog.rst:41
msgid "Updated documentation and examples"
msgstr "更新文档和示例"
#: ../../changelog.rst:42
msgid "Updated translations"
msgstr "更新翻译"
# Flask-Admin
# http://flask-admin.readthedocs.io/en/latest/
#
# Copyright (C) 2012-2015, Serge S. Koval
# This file is distributed under the same license as the flask-admin
# package.
# 1dot75cm <sensor.wen@gmail.com>, 2016.
#
msgid ""
msgstr ""
"Project-Id-Version: flask-admin 1.4.2\n"
"Report-Msgid-Bugs-To: https://github.com/sixu05202004/Flask-extensions-docs\n"
"POT-Creation-Date: 2016-11-25 03:00+0800\n"
"PO-Revision-Date: 2016-11-25 03:00+0800\n"
"Last-Translator: 1dot75cm <sensor.wen@gmail.com>\n"
"Language-Team: zh_CN <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.3.4\n"
#: ../../index.rst:4
msgid "Flask-Admin"
msgstr "Flask-Admin"
#: ../../index.rst:6
msgid ""
"**Why Flask?** As a micro-framework, `Flask <http://flask.pocoo.org/>`_ "
"lets you build web services with very little overhead. It offers freedom "
"for you, the designer, to implement your project in a way that suits your"
" particular application."
msgstr ""
"**为什么选择 Flask?** 作为一个微框架,`Flask <http://flask.pocoo.org/>`_ "
"允许您以非常少的开销构建 Web 服务。它为您的设计提供了自由,使您能够以适合特定应用程序"
"的方式实现您的项目。"
#: ../../index.rst:10
msgid ""
"**Why Flask-Admin?** In a world of micro-services and APIs, Flask-Admin "
"solves the boring problem of building an admin interface on top of an "
"existing data model. With little effort, it lets you manage your web "
"service's data through a user-friendly interface."
msgstr ""
"**为什么选择 Flask-Admin?** 在微服务和 API 的世界中,Flask-Admin 解决了"
"在现有数据模型之上构建管理界面的无聊问题。通过很少的努力,它允许您通过用户友好的"
"界面管理您的 Web 服务的数据。"
#: ../../index.rst:15
msgid ""
"**How does it work?** The basic concept behind Flask-Admin, is that it "
"lets you build complicated interfaces by grouping individual views "
"together in classes: Each web page you see on the frontend, represents a "
"method on a class that has explicitly been added to the interface."
msgstr ""
"**它是如何工作的?** Flask-Admin 背后的基本概念是,它允许你通过将各个视图在类中组合"
"来构建复杂的接口:你在前端看到的每个页面,都代表一个已明确添加到接口中的类方法。"
#: ../../index.rst:20
msgid ""
"These view classes are especially helpful when they are tied to "
"particular database models, because they let you group together all of "
"the usual *Create, Read, Update, Delete* (CRUD) view logic into a single,"
" self-contained class for each of your models."
msgstr ""
"这些视图类在绑定到特定数据库模型时特别有用,因为它们允许您将所有常用的 "
"*Create, Read, Update, Delete* (CRUD) 视图逻辑分组到每个模型的单独类中。"
#: ../../index.rst:26
msgid ""
"**What does it look like?** At http://examples.flask-admin.org/ you can "
"see some examples of Flask-Admin in action, or browse through the "
"`examples/` directory in the `GitHub repository <https://github.com"
"/flask-admin/flask-admin>`_."
msgstr ""
"**它是什么样子的?** 在 http://examples.flask-admin.org/,你可以看到 "
"Flask-Admin 的一些示例,也可以直接浏览 `GitHub 存储库 <https://github.com"
"/flask-admin/flask-admin>`_ 中的 `examples/` 目录。"
#: ../../index.rst:40
msgid "Support"
msgstr "支持"
#: ../../index.rst:44
msgid "Python 2.6 - 2.7 and 3.3 - 3.4."
msgstr "Python 2.6 - 2.7 和 3.3 - 3.4。"
#: ../../index.rst:47
msgid "Indices And Tables"
msgstr "索引和表格"
#: ../../index.rst:51
msgid ":ref:`genindex`"
msgstr ":ref:`genindex`"
#: ../../index.rst:52
msgid ":ref:`modindex`"
msgstr ":ref:`modindex`"
#: ../../index.rst:53
msgid ":ref:`search`"
msgstr ":ref:`search`"
# Introduction To Flask-Admin
# http://flask-admin.readthedocs.io/en/latest/introduction/
#
# Copyright (C) 2012-2015, Serge S. Koval
# This file is distributed under the same license as the flask-admin
# package.
# 1dot75cm <sensor.wen@gmail.com>, 2016.
#
msgid ""
msgstr ""
"Project-Id-Version: flask-admin 1.4.2\n"
"Report-Msgid-Bugs-To: https://github.com/sixu05202004/Flask-extensions-docs\n"
"POT-Creation-Date: 2016-11-25 03:00+0800\n"
"PO-Revision-Date: 2016-11-25 03:00+0800\n"
"Last-Translator: 1dot75cm <sensor.wen@gmail.com>\n"
"Language-Team: zh_CN <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.3.4\n"
#: ../../introduction.rst:4
msgid "Introduction To Flask-Admin"
msgstr "介绍 Flask-Admin"
#: ../../introduction.rst:7
msgid "Getting Started"
msgstr "快速入门"
#: ../../introduction.rst:12
msgid "Initialization"
msgstr "初始化"
#: ../../introduction.rst:14
msgid ""
"The first step is to initialize an empty admin interface for your Flask "
"app::"
msgstr ""
"首先为 Flask app 初始化空的 admin 接口::"
#: ../../introduction.rst:26
msgid ""
"Here, both the *name* and *template_mode* parameters are optional. "
"Alternatively, you could use the :meth:`~flask_admin.base.Admin.init_app`"
" method."
msgstr ""
"这里的 *name* 和 *template_mode* 参数可选。"
"另外,可以用 :meth:`~flask_admin.base.Admin.init_app` 方法初始化。"
#: ../../introduction.rst:29
msgid ""
"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."
msgstr ""
"如果启动应用并导航至 "
"`http://localhost:5000/admin/ <http://localhost:5000/admin/>`_, 你"
"会看到一个包含导航栏的空页面。"
#: ../../introduction.rst:33
msgid "Adding Model Views"
msgstr "添加模型视图"
#: ../../introduction.rst:35
msgid ""
"Model views allow you to add a dedicated set of admin pages for managing "
"any model in your database. Do this by creating instances of the "
"*ModelView* class, which you can import from one of Flask-Admin's built-"
"in ORM backends. An example is the SQLAlchemy backend, which you can use "
"as follows::"
msgstr ""
"模型视图允许您添加一组专用的管理页面来管理数据库中的任何模型。"
"通过创建 *ModelView* 类的实例来执行此操作,您可以从 Flask-Admin "
"的内置 ORM 后端导入。SQLAlchemy 后端示例如下::"
#: ../../introduction.rst:47
msgid ""
"Straight out of the box, this gives you a set of fully featured *CRUD* "
"views for your model:"
msgstr ""
"直接开箱即用,这为您的模型提供了一组全功能的 *CRUD* 视图:"
#: ../../introduction.rst:49
msgid ""
"A `list` view, with support for searching, sorting, filtering, and "
"deleting records."
msgstr ""
"`list` view:支持搜索,排序,过滤,删除记录。"
#: ../../introduction.rst:50
msgid "A `create` view for adding new records."
msgstr "`create` view:添加新记录。"
#: ../../introduction.rst:51
msgid "An `edit` view for updating existing records."
msgstr "`edit` view:更新已存在的记录。"
#: ../../introduction.rst:52
msgid "An optional, read-only `details` view."
msgstr "可选的,只读 `details` view。"
#: ../../introduction.rst:54
msgid ""
"There are many options available for customizing the display and "
"functionality of these built-in views. For more details on that, see :ref"
":`customizing-builtin-views`. For more details on the other ORM backends "
"that are available, see :ref:`database-backends`."
msgstr ""
"内置视图有许多选项可用于定制外观和功能。更多信息,请参考 "
":ref:`customizing-builtin-views`。更多其他 ORM 后端"
"的详细信息,请参考 :ref:`database-backends`。"
#: ../../introduction.rst:59
msgid "Adding Content to the Index Page"
msgstr "添加内容至索引页"
#: ../../introduction.rst:60
msgid ""
"The first thing you'll notice when you visit "
"`http://localhost:5000/admin/ <http://localhost:5000/admin/>`_ is that "
"it's just an empty page with a navigation menu. To add some content to "
"this page, save the following text as `admin/index.html` in your "
"project's `templates` directory::"
msgstr ""
"当您访问 `http://localhost:5000/admin/ <http://localhost:5000/admin/>`_ "
"页面时,你会看到一个仅有导航条的空页面。添加内容至该页面,请将以下内容保存至"
"您项目 `templates` 目录下的 `admin/index.html` 文件::"
#: ../../introduction.rst:69
msgid ""
"This will override the default index template, but still give you the "
"built-in navigation menu. So, now you can add any content to the index "
"page, while maintaining a consistent user experience."
msgstr ""
"这将覆盖默认 index 模板,但仍给您内置的导航菜单。"
"因此,现在您可以向 index 页面添加任何内容,同时保持一致的用户体验。"
#: ../../introduction.rst:73
msgid "Authorization & Permissions"
msgstr "认证 & 权限"
#: ../../introduction.rst:77
msgid ""
"When setting up an admin interface for your application, one of the first"
" problems you'll want to solve is how to keep unwanted users out. With "
"Flask-Admin there are a few different ways of approaching this."
msgstr ""
"当为您的应用设置管理接口时,首先考虑的问题是,如何对用户进行访问控制。"
"Flask-Admin 有以下几种方式对用户进行访问控制。"
#: ../../introduction.rst:82
msgid "HTTP Basic Auth"
msgstr "HTTP Basic Auth"
#: ../../introduction.rst:83
msgid ""
"The simplest form of authentication is HTTP Basic Auth. It doesn't "
"interfere with your database models, and it doesn't require you to write "
"any new view logic or template code. So it's great for when you're "
"deploying something that's still under development, before you want the "
"whole world to see it."
msgstr ""
"最简单的身份验证形式是 HTTP 基本认证。它不干扰您的数据库模型,"
"它不需要您写任何新的视图逻辑或模板代码。所以当你在部署一些仍在"
"开发中的东西前,使用基本认证是很好的选择。"
#: ../../introduction.rst:88
msgid ""
"Have a look at `Flask-BasicAuth <https://flask-"
"basicauth.readthedocs.io/>`_ to see just how easy it is to put your whole"
" application behind HTTP Basic Auth."
msgstr ""
"`Flask-BasicAuth <https://flask-basicauth.readthedocs.io/>`_ "
"可以轻易的为应用添加 HTTP 基本验证。"
#: ../../introduction.rst:91
msgid ""
"Unfortunately, there is no easy way of applying HTTP Basic Auth just to "
"your admin interface."
msgstr ""
"不幸的是,没有简单的方法将 HTTP 基本认证应用于您的管理界面。"
#: ../../introduction.rst:95
msgid "Rolling Your Own"
msgstr "自定义认证"
#: ../../introduction.rst:96
msgid ""
"For a more flexible solution, Flask-Admin lets you define access control "
"rules on each of your admin view classes by simply overriding the "
"`is_accessible` method. How you implement the logic is up to you, but if "
"you were to use a low-level library like `Flask-Login <https://flask-"
"login.readthedocs.io/>`_, then restricting access could be as simple as::"
msgstr ""
"对于更灵活的解决方案,Flask-Admin 允许您通过覆盖 `is_accessible` 方法"
"来为每个 admin 视图类定义访问控制规则。如何实现逻辑取决于你,如果你正在使用"
"类似 `Flask-Login <https://flask-login.readthedocs.io/>`_ 的低级库,"
"限制访问的规则如下::"
#: ../../introduction.rst:111
msgid ""
"In the navigation menu, components that are not accessible to a "
"particular user will not be displayed for that user. For an example of "
"using Flask-Login with Flask-Admin, have a look at https://github.com"
"/flask-admin/Flask-Admin/tree/master/examples/auth-flask-login."
msgstr ""
"在导航菜单中,不会显示该用户无法访问的组件。有关使用 Flask-Login "
"与 Flask-Admin 的示例,请参考 https://github.com/flask-admin/"
"Flask-Admin/tree/master/examples/auth-flask-login。"
#: ../../introduction.rst:115
msgid ""
"The main drawback is that you still need to implement all of the relevant"
" login, registration, and account management views yourself."
msgstr ""
"主要缺点是你仍然需要自己实现所有的登录,注册和帐户管理视图。"
#: ../../introduction.rst:120
msgid "Using Flask-Security"
msgstr "使用 Flask-Security"
#: ../../introduction.rst:122
msgid ""
"If you want a more polished solution, you could use `Flask-Security "
"<https://pythonhosted.org/Flask-Security/>`_, 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."
msgstr ""
"如果你需要一个更优秀的解决方案,可以使用 `Flask-Security "
"<https://pythonhosted.org/Flask-Security/>`_,这是一个更高级的库。"
"它有很多内置视图,用于完成用户管理相关的常见操作,如用户注册,登录,"
"电子邮件地址确认,密码重置等。"
#: ../../introduction.rst:127
msgid ""
"The only complicated bit is making the built-in Flask-Security views "
"integrate smoothly with the Flask-Admin templates to create a consistent "
"user experience. To do this, you will need to override the built-in "
"Flask-Security templates and have them extend the Flask-Admin base "
"template by adding the following to the top of each file::"
msgstr ""
"唯一复杂的是使内置的 Flask-Security 视图与 Flask-Admin 模板平滑地集成,"
"以创建一致的用户体验。为此,您需要覆盖内置的 Flask-Security 模板,并通过"
"在每个文件的顶部添加以下内容来扩展 Flask-Admin base 模板::"
#: ../../introduction.rst:135
msgid ""
"Now, you'll need to manually pass in some context variables for the "
"Flask-Admin templates to render correctly when they're being called from "
"the Flask-Security views. Defining a `security_context_processor` "
"function will take care of this for you::"
msgstr ""
"现在,当需要从 Flask-Security 视图调用 Flask-Admin 模板时,您需要"
"手动向 Flask-Admin 模板传递一些上下文变量,以便正确显示它们。定义 "
"`security_context_processor` 函数处理模板变量::"
#: ../../introduction.rst:146
msgid ""
"For a working example of using Flask-Security with Flask-Admin, have a "
"look at https://github.com/flask-admin/Flask-"
"Admin/tree/master/examples/auth."
msgstr ""
"有关使用 Flask-Security 和 Flask-Admin 集成的示例,请查看 https://github.com/"
"flask-admin/Flask-Admin/tree/master/examples/auth。"
#: ../../introduction.rst:149
msgid ""
"The example only uses the built-in `register` and `login` views, but you "
"could follow the same approach for including the other views, like "
"`forgot_password`, `send_confirmation`, etc."
msgstr ""
"该示例仅使用内置的 `register` 和 `login` 视图,但您可以按照相同的方法来包括其他视图,"
"如 `forgot_password`, `send_confirmation` 等。"
#: ../../introduction.rst:155
msgid "Customizing Built-in Views"
msgstr "自定义内置视图"
#: ../../introduction.rst:159
msgid ""
"The built-in `ModelView` class is great for getting started quickly. But,"
" you'll want to configure its functionality to suit your particular "
"models. This is done by setting values for the configuration attributes "
"that are made available in the `ModelView` class."
msgstr ""
"内置的 `ModelView` 类非常适合快速入门。另外,您可以通过配置 `ModelView` 类"
"的属性值,来满足您的模型的特殊需求。"
#: ../../introduction.rst:163
msgid ""
"To specify some global configuration parameters, you can subclass "
"`ModelView` and use that subclass when adding your models to the "
"interface::"
msgstr ""
"要指定全局配置参数,可以继承 `ModelView` 类,并在添加模型时使用子类::"
#: ../../introduction.rst:177
msgid ""
"Or, in much the same way, you can specify options for a single model at a"
" time::"
msgstr ""
"或者,您也可以为单个模型指定选项::"
#: ../../introduction.rst:190
msgid "`ModelView` Configuration Attributes"
msgstr "`ModelView` 配置属性"
#: ../../introduction.rst:192
msgid ""
"For a complete list of the attributes that are defined, have a look at "
"the API documentation for :meth:`~flask_admin.model.BaseModelView`. Here "
"are some of the most commonly used attributes:"
msgstr ""
"有关定义属性的完整列表,请查看 :meth:`~flask_admin.model.BaseModelView` API 文档。"
"这里列出了一些最常用的属性:"
#: ../../introduction.rst:196
msgid ""
"To **disable some of the CRUD operations**, set any of these boolean "
"parameters::"
msgstr ""
"要 **禁用某些 CRUD 操作**,请设置以下布尔参数::"
#: ../../introduction.rst:202
msgid ""
"If your model has too much data to display in the list view, you can "
"**add a read-only details view** by setting::"
msgstr ""
"如果您的模型在列表视图中显示的数据过多,可以设置以下内容来 **添加只读的详细视图**::"
#: ../../introduction.rst:207
msgid ""
"**Removing columns** from the list view is easy, just pass a list of "
"column names for the *column_excludes_list* parameter::"
msgstr ""
"从列表视图中 **删除列**,只需要向 *column_excludes_list* 参数传递列名列表即可::"
#: ../../introduction.rst:212
msgid ""
"To **make columns searchable**, or to use them for filtering, specify a "
"list of column names::"
msgstr ""
"要 **使列可搜索** 或用于 **过滤**,请指定列名列表::"
#: ../../introduction.rst:217
msgid ""
"For a faster editing experience, enable **inline editing** in the list "
"view::"
msgstr ""
"要获得更快的编辑体验,请在列表视图中启用 **行内编辑**::"
#: ../../introduction.rst:221
msgid ""
"Or, have the add & edit forms display inside a **modal window** on the "
"list page, instead of the dedicated *create* & *edit* pages::"
msgstr ""
"或者,在列表页面上的 **模态窗口** 内显示 add & edit 表单,代替专门的 "
"*create* & *edit* 页面::"
#: ../../introduction.rst:227
msgid ""
"You can restrict the possible values for a text-field by specifying a "
"list of **select choices**::"
msgstr ""
"您可以通过指定 **选择选项** 的列表,来限制文本字段的可选值::"
#: ../../introduction.rst:239
msgid "To **remove fields** from the create and edit forms::"
msgstr "从创建和编辑表单 **删除字段**::"
#: ../../introduction.rst:243
msgid "To specify **WTForms field arguments**::"
msgstr "指定 **WTForms 字段参数**::"
#: ../../introduction.rst:252
msgid ""
"Or, to specify arguments to the **WTForms widgets** used to render those "
"fields::"
msgstr ""
"或,指定用于渲染这些字段的 **WTForms widgets** 的参数::"
#: ../../introduction.rst:261
msgid ""
"When your forms contain foreign keys, have those **related models loaded "
"via ajax**, using::"
msgstr ""
"当您的表单包含外键时,使用以下参数将 **相关模型通过 ajax 导入**::"
#: ../../introduction.rst:270
msgid "To **manage related models inline**::"
msgstr "**行内管理相关模型**::"
#: ../../introduction.rst:274
msgid ""
"These inline forms can be customized. Have a look at the API "
"documentation for "
":meth:`~flask_admin.contrib.sqla.ModelView.inline_models`."
msgstr ""
"行内表单可以自定义。详情参考 "
":meth:`~flask_admin.contrib.sqla.ModelView.inline_models` API 文档。"
#: ../../introduction.rst:277
msgid "To **enable csv export** of the model view::"
msgstr "启用模型视图的 **CSV 导出功能**::"
#: ../../introduction.rst:281
msgid ""
"This will add a button to the model view that exports records, truncating"
" at :attr:`~flask_admin.model.BaseModelView.export_max_rows`."
msgstr ""
"这将向模型视图添加一个导出记录的按钮,使用 "
":attr:`~flask_admin.model.BaseModelView.export_max_rows` 控制导出行数。"
#: ../../introduction.rst:284
msgid "Adding Your Own Views"
msgstr "添加你自己的视图"
#: ../../introduction.rst:288
msgid ""
"For situations where your requirements are really specific and you "
"struggle to meet them with the built-in "
":class:`~flask_admin.model.ModelView` class, Flask-Admin makes it easy "
"for you to take full control and add your own views to the interface."
msgstr ""
"如果内置的 :class:`~flask_admin.model.ModelView` 类不能满足您的需求, "
"Flask-Admin 可以使您轻松地进行控制并向界面添加自己的视图。"
#: ../../introduction.rst:293
msgid "Standalone Views"
msgstr "独立视图"
#: ../../introduction.rst:294
msgid ""
"A set of standalone views (not tied to any particular model) can be added"
" by extending the :class:`~flask_admin.base.BaseView` class and defining "
"your own view methods. For example, to add a page that displays some "
"analytics data from a 3rd-party API::"
msgstr ""
"可以通过扩展 :class:`~flask_admin.base.BaseView` 类并定义自己的视图方法"
"来添加一组独立视图(不与任何特定模型绑定)。例如,要添加来自第三方 API 的某些"
"分析数据的页面::"
#: ../../introduction.rst:307
msgid ""
"This will add a link to the navbar for your view. Notice that it is "
"served at '/', the root URL. This is a restriction on standalone views: "
"at the very minimum, each view class needs at least one method to serve a"
" view at its root."
msgstr ""
"这将为您的视图添加一个导航栏链接。注意,它在 '/' 根 URL。这是对独立视图的限制:"
"每个视图类需要至少一个方法来在其根目录中提供视图。"
#: ../../introduction.rst:311
msgid ""
"The `analytics_index.html` template for the example above, could look "
"something like::"
msgstr ""
"上述示例的 `analytics_index.html` 模板可能如下所示:"
#: ../../introduction.rst:318
msgid ""
"By extending the *admin/master.html* template, you can maintain a "
"consistent user experience, even while having tight control over your "
"page's content."
msgstr ""
"通过扩展 *admin/master.html* 模板,即使在严格控制页面内容的情况下,"
"您仍然可以保持一致的用户体验。"
#: ../../introduction.rst:322
msgid "Overriding the Built-in Views"
msgstr "覆盖内置视图"
#: ../../introduction.rst:323
msgid ""
"There may be some scenarios where you want most of the built-in ModelView"
" functionality, but you want to replace one of the default `create`, "
"`edit`, or `list` views. For this you could override only the view in "
"question, and all the links to it will still function as you would "
"expect::"
msgstr ""
"在某些情况下,您需要使用大多数内置的 ModelView 功能,但需要替换默认的 `create`, "
"`edit` 或 `list` 视图。为此,您只需要覆盖指定视图,视图的所有链接仍然会正常工作::"
#: ../../introduction.rst:341
msgid "Working With the Built-in Templates"
msgstr "使用内置模板"
#: ../../introduction.rst:345
msgid ""
"Flask-Admin uses the `Jinja2 <http://jinja.pocoo.org/docs/>`_ templating "
"engine."
msgstr ""
"Flask-Admin 使用 `Jinja2 <http://jinja.pocoo.org/docs/>`_ 模板引擎。"
#: ../../introduction.rst:350
msgid "Extending the Built-in Templates"
msgstr "扩展内置模板"
#: ../../introduction.rst:352
msgid ""
"Rather than overriding the built-in templates completely, it's best to "
"extend them. This will make it simpler for you to upgrade to new Flask-"
"Admin versions in future."
msgstr ""
"扩展内置模板,而不是完全覆盖它们。使您可以更容易的升级到新版 Flake-Admin。"
#: ../../introduction.rst:355
msgid ""
"Internally, the Flask-Admin templates are derived from the "
"`admin/master.html` template. The three most interesting templates for "
"you to extend are probably:"
msgstr ""
"在内部,Flask-Admin 模板派生自 `admin/master.html` 模板。你需要扩展的"
"三个有趣的模板可能是:"
#: ../../introduction.rst:358
msgid "`admin/model/list.html`"
msgstr "`admin/model/list.html`"
#: ../../introduction.rst:359
msgid "`admin/model/create.html`"
msgstr "`admin/model/create.html`"
#: ../../introduction.rst:360
msgid "`admin/model/edit.html`"
msgstr "`admin/model/edit.html`"
#: ../../introduction.rst:362
msgid ""
"To extend the default *edit* template with your own functionality, create"
" a template in `templates/microblog_edit.html` to look something like::"
msgstr ""
"要使用自定义功能扩展默认 *edit* 模板,请在 `templates/microblog_edit.html` 中"
"创建模板,如下所示::"
#: ../../introduction.rst:372
msgid ""
"Now, to make your view classes use this template, set the appropriate "
"class property::"
msgstr ""
"现在,确保您的视图类使用该模板,设置相应的类属性::"
#: ../../introduction.rst:379
msgid ""
"If you want to use your own base template, then pass the name of the "
"template to the admin constructor during initialization::"
msgstr ""
"如果要使用自己的 base 模板,则在初始化时将模板名传递给 admin 构造函数::"
#: ../../introduction.rst:385
msgid "Overriding the Built-in Templates"
msgstr "覆盖内置模板"
#: ../../introduction.rst:387
msgid ""
"To take full control over the style and layout of the admin interface, "
"you can override all of the built-in templates. Just keep in mind that "
"the templates will change slightly from one version of Flask-Admin to the"
" next, so once you start overriding them, you need to take care when "
"upgrading your package version."
msgstr ""
"要完全控制管理界面的样式和布局,您可以覆盖所有内置模板。请记住,新版本的 "
"Flask-Admin 模板会稍有变化,所以一旦开始覆盖内置模板,升级软件包时可能会出错。"
#: ../../introduction.rst:392
msgid ""
"To override any of the built-in templates, simply copy them from the "
"Flask-Admin source into your project's `templates/admin/` directory. As "
"long as the filenames stay the same, the templates in your project "
"directory should automatically take precedence over the built-in ones."
msgstr ""
"要覆盖任何内置模板,只需将它们从 Flask-Admin 复制到项目的 `templates/admin/` 目录。"
"只要文件名保持不变,项目目录中的模板将自动优先于内置模板。"
#: ../../introduction.rst:398
msgid "Available Template Blocks"
msgstr "可用模板块"
#: ../../introduction.rst:400
msgid ""
"Flask-Admin defines one *base* template at `admin/master.html` that all "
"other admin templates are derived from. This template is a proxy which "
"points to `admin/base.html`, which defines the following blocks:"
msgstr ""
"Flask-Admin 在 `admin/master.html` 定义了一个 *base* 模板,所有其他管理模板"
"都派生自该模板。此模板是一个指向 `admin/base.html` 的代理,它定义了以下块:"
#: ../../introduction.rst:405 ../../introduction.rst:425
msgid "Block Name"
msgstr "块名称"
#: ../../introduction.rst:405 ../../introduction.rst:425
#: ../../introduction.rst:446
msgid "Description"
msgstr "描述"
#: ../../introduction.rst:407
msgid "head_meta"
msgstr "head_meta"
#: ../../introduction.rst:407
msgid "Page metadata in the header"
msgstr "header 中的页面元数据"
#: ../../introduction.rst:408
msgid "title"
msgstr "title"
#: ../../introduction.rst:408
msgid "Page title"
msgstr "页面标题"
#: ../../introduction.rst:409
msgid "head_css"
msgstr "head_css"
#: ../../introduction.rst:409
msgid "Various CSS includes in the header"
msgstr "header 中的各种 CSS"
#: ../../introduction.rst:410
msgid "head"
msgstr "head"
#: ../../introduction.rst:410
msgid "Empty block in HTML head, in case you want to put something there"
msgstr "空的 HTML head 元素,可自定义信息"
#: ../../introduction.rst:411
msgid "page_body"
msgstr "page_body"
#: ../../introduction.rst:411
msgid "Page layout"
msgstr "页面布局"
#: ../../introduction.rst:412
msgid "brand"
msgstr "brand"
#: ../../introduction.rst:412
msgid "Logo in the menu bar"
msgstr "菜单栏 Logo"
#: ../../introduction.rst:413
msgid "main_menu"
msgstr "main_menu"
#: ../../introduction.rst:413
msgid "Main menu"
msgstr "主菜单"
#: ../../introduction.rst:414
msgid "menu_links"
msgstr "menu_links"
#: ../../introduction.rst:414
msgid "Links menu"
msgstr "菜单链接"
#: ../../introduction.rst:415
msgid "access_control"
msgstr "access_control"
#: ../../introduction.rst:415
msgid "Section to the right of the menu (can be used to add login/logout buttons)"
msgstr "菜单右侧部分 (可用于添加登录/注销按钮)"
#: ../../introduction.rst:416
msgid "messages"
msgstr "messages"
#: ../../introduction.rst:416
msgid "Alerts and various messages"
msgstr "警告和各种消息"
#: ../../introduction.rst:417
msgid "body"
msgstr "body"
#: ../../introduction.rst:417
msgid "Content (that's where your view will be displayed)"
msgstr "内容 (您的视图内容)"
#: ../../introduction.rst:418
msgid "tail"
msgstr "tail"
#: ../../introduction.rst:418
msgid "Empty area below content"
msgstr "空的底部内容"
#: ../../introduction.rst:421
msgid ""
"In addition to all of the blocks that are inherited from "
"`admin/master.html`, the `admin/model/list.html` template also contains "
"the following blocks:"
msgstr ""
"除了从 `admin/master.html` 继承的所有块之外,`admin/model/list.html` 模板"
"还包含以下块:"
#: ../../introduction.rst:427
msgid "model_menu_bar"
msgstr "model_menu_bar"
#: ../../introduction.rst:427
msgid "Menu bar"
msgstr "菜单栏"
#: ../../introduction.rst:428
msgid "model_list_table"
msgstr "model_list_table"
#: ../../introduction.rst:428
msgid "Table container"
msgstr "表格容器"
#: ../../introduction.rst:429
msgid "list_header"
msgstr "list_header"
#: ../../introduction.rst:429
msgid "Table header row"
msgstr "表格头部"
#: ../../introduction.rst:430
msgid "list_row_actions_header"
msgstr "list_row_actions_header"
#: ../../introduction.rst:430
msgid "Actions header"
msgstr "操作表头"
#: ../../introduction.rst:431
msgid "list_row"
msgstr "list_row"
#: ../../introduction.rst:431
msgid "Single row"
msgstr "单行"
#: ../../introduction.rst:432
msgid "list_row_actions"
msgstr "list_row_actions"
#: ../../introduction.rst:432
msgid "Row action cell with edit/remove/etc buttons"
msgstr "单元格的编辑/删除等动作按钮"
#: ../../introduction.rst:433
msgid "empty_list_message"
msgstr "empty_list_message"
#: ../../introduction.rst:433
msgid "Message that will be displayed if there are no models found"
msgstr "如果未找到模型,将显示该消息"
#: ../../introduction.rst:436
msgid ""
"Have a look at the `layout` example at https://github.com/flask-admin"
"/flask-admin/tree/master/examples/layout to see how you can take full "
"stylistic control over the admin interface."
msgstr ""
"请查看 https://github.com/flask-admin/flask-admin/tree/master/examples/"
"layout 上的 *布局* 示例,了解如何对管理界面进行全面的风格控制。"
#: ../../introduction.rst:440
msgid "Environment Variables"
msgstr "环境变量"
#: ../../introduction.rst:442
msgid ""
"While working in any of the templates that extend `admin/master.html`, "
"you have access to a small number of environment variables:"
msgstr ""
"当在任何扩展 `admin/master.html` 的模板中工作时,您可以访问少量的环境变量:"
#: ../../introduction.rst:446
msgid "Variable Name"
msgstr "变量名"
#: ../../introduction.rst:448
msgid "admin_view"
msgstr "admin_view"
#: ../../introduction.rst:448
msgid "Current administrative view"
msgstr "当前管理视图"
#: ../../introduction.rst:449
msgid "admin_base_template"
msgstr "admin_base_template"
#: ../../introduction.rst:449
msgid "Base template name"
msgstr "Base 模板名"
#: ../../introduction.rst:450
msgid "_gettext"
msgstr "_gettext"
#: ../../introduction.rst:450
msgid "Babel gettext"
msgstr "Babel gettext"
#: ../../introduction.rst:451
msgid "_ngettext"
msgstr "_ngettext"
#: ../../introduction.rst:451
msgid "Babel ngettext"
msgstr "Babel ngettext"
#: ../../introduction.rst:452
msgid "h"
msgstr "h"
#: ../../introduction.rst:452
msgid "Helpers from :mod:`~flask_admin.helpers` module"
msgstr ":mod:`~flask_admin.helpers` 模块帮助类"
#: ../../introduction.rst:456
msgid "Generating URLs"
msgstr "生成 URL"
#: ../../introduction.rst:458
msgid "To generate the URL for a specific view, use *url_for* with a dot prefix::"
msgstr "生成指定视图的 URL,请使用带点前缀的 *url_for*::"
#: ../../introduction.rst:469
msgid "A specific record can also be referenced with::"
msgstr "一个指定记录的 URL 可以参考示例::"
#: ../../introduction.rst:474
msgid ""
"When referencing ModelView instances, use the lowercase name of the model"
" as the prefix when calling *url_for*. Other views can be referenced by "
"specifying a unique endpoint for each, and using that as the prefix. So, "
"you could use::"
msgstr ""
"当引用 ModelView 实例时,在调用 *url_for* 时使用模型的小写名称作为前缀。可以通过"
"为每个视图指定唯一的端点,并将其用作前缀来引用其他视图。所以,可以这样引用::"
#: ../../introduction.rst:480
msgid "If your view endpoint was defined like::"
msgstr "您的视图端点定义如下::"
......@@ -3,8 +3,9 @@ wtforms
Flask-SQLAlchemy>=0.15
peewee
wtf-peewee
mongoengine<0.11.0
pymongo==2.8
flask-mongoengine
flask-mongoengine==0.8.2
pillow==2.9.0
Babel<=1.3
flask-babelex
......@@ -13,5 +14,6 @@ geoalchemy2
psycopg2
nose
sphinx
sphinx-intl
coveralls
pylint
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment