博客 页面 31

Flask-User

可定制的用户账号管理扩展

quokka-plugins

扩展

Quokka 尝试使用类似Django-ish的方法去实现quokka-modules,你能通过以下方式去开发modules:

quokka/modules

└── posts
├── admin.py – defines the admin pages
├── commands.py – create management commands here
├── __init__.py – define module and routes
├── models.py – define the Mongo Documents models
├── populate.py – optional example fixtures
├── tasks.py – Tasks is for celery tasks
├── template_filters.py – Jinja filters
├── templates
│      └── posts
│      ├── detail.html
│      └── list.html
└── static
└── views.py – module views

重要:通过阅读开发模块的文档,你能了解到更多内容。模块取名时应该遵照文档规范,避免名称冲突。

安装模块

安装模块不需要改变现有代码或者配置文件。
仅仅将其放入quokka/modules目录下,然后重启服务即可。
Quokka admin也提供了一个web接口让admin用户可以安装、启用、停用模块。

原文:https://github.com/quokkaproject/quokka/wiki/plugins

Flask-Script

The Flask-Script extension provides support for writing external scripts in Flask. This includes running a development server, a customised Python shell, scripts to set up your database, cronjobs, and other command-line tasks that belong outside the web application itself.

Flask-Script works in a similar way to Flask itself. You define and add commands that can be called from the command line to a Manager instance:

# manage.py

from flask.ext.script import Manager

from myapp import app

manager = Manager(app)

@manager.command
def hello():
print “hello”

if __name__ == “__main__”:
manager.run()
Once you define your script commands, you can then run them on the command line:

python manage.py hello
> hello
Source code and issue tracking at GitHub.

Installing Flask-Script
Install with pip and easy_install:

pip install Flask-Script
or download the latest version from version control:

git clone https://github.com/smurfix/flask-script.git
cd flask-script
python setup.py develop
If you are using virtualenv, it is assumed that you are installing Flask-Script in the same virtualenv as your Flask application(s).

Creating and running commands
The first step is to create a Python module to run your script commands in. You can call it anything you like, for our examples we’ll call it manage.py.

You don’t have to place all your commands in the same file; for example, in a larger project with lots of commands you might want to split them into a number of files with related commands.

In your manage.py file you have to create a Manager instance. The Manager class keeps track of all the commands and handles how they are called from the command line:

from flask.ext.script import Manager

app = Flask(__name__)
# configure your app

manager = Manager(app)

if __name__ == “__main__”:
manager.run()
Calling manager.run() prepares your Manager instance to receive input from the command line.

The Manager requires a single argument, a Flask instance. This may also be a function or other callable that returns a Flask instance instead, if you want to use a factory pattern.

The next step is to create and add your commands. There are three methods for creating commands:

subclassing the Command class
using the @command decorator
using the @option decorator
To take a very simple example, we want to create a hello command that just prints out “hello world”. It doesn’t take any arguments so is very straightforward:

from flask.ext.script import Command

class Hello(Command):
“prints hello world”

def run(self):
print “hello world”
Now the command needs to be added to our Manager instance, like the one created above:

manager.add_command(‘hello’, Hello())
This of course needs to be called before manager.run. Now in our command line:

python manage.py hello
> hello world
You can also pass the Command instance in a dict to manager.run():

manager.run({‘hello’ : Hello()})
The Command class must define a run method. The positional and optional arguments depend on the command-line arguments you pass to the Command (see below).

To get a list of available commands and their descriptions, just run with no command:

python manage.py
To get help text for a particular command:

python manage.py runserver -?
This will print usage plus the docstring of the Command.

This first method is probably the most flexible, but it’s also the most verbose. For simpler commands you can use the @command decorator, which belongs to the Manager instance:

@manager.command
def hello():
“Just say hello”
print “hello”
Commands created this way are run in exactly the same way as those created with the Command class:

python manage.py hello
> hello
As with the Command class, the docstring you use for the function will appear when you run with the -? or –help option:

python manage.py -?
> Just say hello
Finally, the @option decorator, again belonging to Manager can be used when you want more sophisticated control over your commands:

@manager.option(‘-n’, ‘–name’, help=’Your name’)
def hello(name):
print “hello”, name
The @option decorator is explained in more detail below.

New in version 2.0

Help was previously available with –help and -h. This had a couple of less-than-ideal consequences, among them the inability to use -h as a shortcut for –host or similar options.

New in version 2.0.2

If you want to restore the original meaning of -h, set your manager’s help_args attribute to a list of argument strings you want to be considered helpful.

manager = Manager() manager.help_args = (‘-h’,’-?’,’–help)
You can override this list in sub-commands and -managers:

def talker(host=’localhost’):
pass
ccmd = ConnectCmd(talker)
ccmd.help_args = (‘-?’,’–help)
manager.add_command(“connect”, ccmd)
manager.run()
so that manager -h prints help, while manager connect -h fubar.example.com connects to a remote host.

Adding arguments to commands
Most commands take a number of named or positional arguments that you pass in the command line.

Taking the above examples, rather than just print “hello world” we would like to be able to print some arbitrary name, like this:

python manage.py hello –name=Joe
hello Joe
or alternatively:

python manage.py hello -n Joe
To facilitate this you use the option_list attribute of the Command class:

from flask.ext.script import Command, Manager, Option

class Hello(Command):

option_list = (
Option(‘–name’, ‘-n’, dest=’name’),
)

def run(self, name):
print “hello %s” % name
Positional and optional arguments are stored as Option instances – see the API below for details.

Alternatively, you can define a get_options method for your Command class. This is useful if you want to be able to return options at runtime based on for example per-instance attributes:

class Hello(Command):

def __init__(self, default_name=’Joe’):
self.default_name=default_name

def get_options(self):
return [
Option(‘-n’, ‘–name’, dest=’name’, default=self.default_name),
]

def run(self, name):
print “hello”, name
If you are using the @command decorator, it’s much easier – the options are extracted automatically from your function arguments. This is an example of a positional argument:

@manager.command
def hello(name):
print “hello”, name
You then invoke this on the command line like so:

> python manage.py hello Joe
hello Joe
Or you can do optional arguments:

@manager.command
def hello(name=”Fred”)
print “hello”, name
These can be called like so:

> python manage.py hello –name=Joe
hello Joe
alternatively:

> python manage.py hello -n Joe
hello Joe
The short form -n is formed from the first letter of the argument, so “name” > “-n”. Therefore it’s a good idea for your optional argument variable names to begin with different letters.

New in version 2.0

Note also that if your optional argument is a boolean, for example:

@manage.command
def verify(verified=False):
“””
Checks if verified
“””
print “VERIFIED?”, “YES” if verified else “NO”
You can just call it like this:

> python manage.py verify
VERIFIED? NO

> python manage.py verify -v
VERIFIED? YES

> python manage.py verify –verified
VERIFIED? YES
The @command decorator is fine for simple operations, but often you need the flexibility. For more sophisticated options it’s better to use the @option decorator:

@manager.option(‘-n’, ‘–name’, dest=’name’, default=’joe’)
def hello(name):
print “hello”, name
You can add as many options as you want:

@manager.option(‘-n’, ‘–name’, dest=’name’, default=’joe’)
@manager.option(‘-u’, ‘–url’, dest=’url’, default=None)
def hello(name, url):
if url is None:
print “hello”, name
else:
print “hello”, name, “from”, url
This can be called like so:

> python manage.py hello -n Joe -u reddit.com
hello Joe from reddit.com
or alternatively:

> python manage.py hello –name=Joe –url=reddit.com
hello Joe from reddit.com
Adding options to the manager
Options can also be passed to the Manager instance. This is allows you to set up options that are passed to the application rather than a single command. For example, you might want to have a flag to set the configuration file for your application. Suppose you create your application with a factory function:

def create_app(config=None):

app = Flask(__name__)
if config is not None:
app.config.from_pyfile(config)
# configure your app…
return app
You want to be able to define the config argument on the command line – for example, if you have a command to set up your database, you most certainly want to use different configuration files for production and development.

In order to pass that config argument, use the add_option() method of your Manager instance. It takes the same arguments as Option:

manager.add_option(‘-c’, ‘–config’, dest=’config’, required=False)
As with any other Flask-Script configuration you can call this anywhere in your script module, but it must be called before your manager.run() call.

Suppose you have this command:

@manager.command
def hello(name):
uppercase = app.config.get(‘USE_UPPERCASE’, False)
if uppercase:
name = name.upper()
print “hello”, name
You can now run the following:

> python manage.py -c dev.cfg hello joe
hello JOE
Assuming the USE_UPPERCASE setting is True in your dev.cfg file.

Notice also that the “config” option is not passed to the command. In fact, this usage

> python manage.py hello joe -c dev.cfg
will show an error message because the -c option does not belong to the hello command.

You can attach same-named options to different levels; this allows you to add an option to your app setup code without checking whether it conflicts with a command:

@manager.option(‘-n’, ‘–name’, dest=’name’, default=’joe’) @manager.option(‘-c’, ‘–clue’, dest=’clue’, default=’clue’) def hello(name,clue):

uppercase = app.config.get(‘USE_UPPERCASE’, False) if uppercase:

name = name.upper() clue = clue.upper()
print “hello {0}, get a {1}!”.format(name,clue)

> python manage.py -c dev.cfg hello -c cookie -n frank hello FRANK, get a COOKIE!

Note that the destination variables (command arguments, corresponding to dest values) must still be different; this is a limitation of Python’s argument parser.

In order for manager options to work you must pass a factory function, rather than a Flask instance, to your Manager constructor. A simple but complete example is available in this gist.

New in version 2.0

Before version 2, options and command names could be interspersed freely. The author decided to discontinue this practice for a number of reasons; the problem with the most impact was that it was not possible to do

> python manage.py connect -d DEST > python manage.py import -d DIR
as these options collided.

Getting user input
Flask-Script comes with a set of helper functions for grabbing user input from the command line. For example:

from flask.ext.script import Manager, prompt_bool

from myapp import app
from myapp.models import db

manager = Manager(app)

@manager.command
def dropdb():
if prompt_bool(
“Are you sure you want to lose all your data”):
db.drop_all()
It then runs like this:

> python manage.py dropdb
Are you sure you want to lose all your data ? [N]
See the API below for details on the various prompt functions.

Default commands
runserver
Flask-Script has a couple of ready commands you can add and customise: Server and Shell.

The Server command runs the Flask development server.:

from flask.ext.script import Server, Manager
from myapp import create_app

manager = Manager(create_app)
manager.add_command(“runserver”, Server())

if __name__ == “__main__”:
manager.run()
and then run the command:

python manage.py runserver
The Server command has a number of command-line arguments – run python manage.py runserver -? for details on these. You can redefine the defaults in the constructor:

server = Server(host=”0.0.0.0″, port=9000)
Needless to say the development server is not intended for production use.

New in version 2.0.5

The most common use-case for runserver is to run a debug server for investigating problems. Therefore the default, if it is not set in the configuration file, is to enable debugging and auto-reloading.

Unfortunately, Flask currently (as of May 2014) defaults to set the DEBUG configuration parameter to False. Until this is changed, you can safely add DEFAULT=None to your Flask configuration. Flask-Script’s runserver will then turn on debugging, but everything else will treat it as being turned off.

To prevent misunderstandings – after all, debug mode is a serious security hole –, a warning is printed when Flask-Script treats a None default value as if it were set to True. You can turn on debugging explicitly to get rid of this warning.

shell
The Shell command starts a Python shell. You can pass in a make_context argument, which must be a callable returning a dict. By default, this is just a dict returning the your Flask application instance:

from flask.ext.script import Shell, Manager

from myapp import app
from myapp import models
from myapp.models import db

def _make_context():
return dict(app=app, db=db, models=models)

manager = Manager(create_app)
manager.add_command(“shell”, Shell(make_context=_make_context))
This is handy if you want to include a bunch of defaults in your shell to save typing lots of import statements.

The Shell command will use IPython if it is installed, otherwise it defaults to the standard Python shell. You can disable this behaviour in two ways: by passing the use_ipython argument to the Shell constructor, or passing the flag –no-ipython in the command line:

shell = Shell(use_ipython=False)
There is also a shell decorator which you can use with a context function:

@manager.shell
def make_shell_context():
return dict(app=app, db=db, models=models)
This enables a shell command with the defaults enabled:

> python manage.py shell
The default commands shell and runserver are included by default, with the default options for these commands. If you wish to replace them with different commands simply override with add_command() or the decorators. If you pass with_default_commands=False to the Manager constructor these commands will not be loaded:

manager = Manager(app, with_default_commands=False)
Sub-Managers
A Sub-Manager is an instance of Manager added as a command to another Manager

To create a submanager:

def sub_opts(app, **kwargs):
pass
sub_manager = Manager(sub_opts)

manager = Manager(self.app)
manager.add_command(“sub_manager”, sub_manager)
If you attach options to the sub_manager, the sub_opts procedure will receive their values. Your application is passed in app for convenience.

If sub_opts returns a value other than None, this value will replace the app value that’s passed on. This way, you can implement a sub-manager which replaces the whole app. One use case is to create a separate administrative application for improved security:

def gen_admin(app, **kwargs):
from myweb.admin import MyAdminApp
## easiest but possibly incomplete way to copy your settings
return MyAdminApp(config=app.config, **kwargs)
sub_manager = Manager(gen_admin)

manager = Manager(MyApp)
manager.add_command(“admin”, sub_manager)

> python manage.py runserver
[ starts your normal server ]
> python manage.py admin runserver
[ starts an administrative server ]
You can cascade sub-managers, i.e. add one sub-manager to another.

A sub-manager does not get default commands added to itself (by default)

New in version 0.5.0.

Note to extension developers
Extension developers can easily create convenient sub-manager instance within their extensions to make it easy for a user to consume all the available commands of an extension.

Here is an example how a database extension could provide (ex. database.py):

manager = Manager(usage=”Perform database operations”)

@manager.command
def drop():
“Drops database tables”
if prompt_bool(“Are you sure you want to lose all your data”):
db.drop_all()

@manager.command
def create(default_data=True, sample_data=False):
“Creates database tables from sqlalchemy models”
db.create_all()
populate(default_data, sample_data)

@manager.command
def recreate(default_data=True, sample_data=False):
“Recreates database tables (same as issuing ‘drop’ and then ‘create’)”
drop()
create(default_data, sample_data)

@manager.command
def populate(default_data=False, sample_data=False):
“Populate database with default data”
from fixtures import dbfixture

if default_data:
from fixtures.default_data import all
default_data = dbfixture.data(*all)
default_data.setup()

if sample_data:
from fixtures.sample_data import all
sample_data = dbfixture.data(*all)
sample_data.setup()
Then the user can register the sub-manager to their primary Manager (within manage.py):

manager = Manager(app)

from flask.ext.database import manager as database_manager
manager.add_command(“database”, database_manager)
The commands will then be available:

> python manage.py database

Please provide a command:

Perform database operations
create Creates database tables from sqlalchemy models
drop Drops database tables
populate Populate database with default data
recreate Recreates database tables (same as issuing ‘drop’ and then ‘create’)
Error handling
Users do not like to see stack traces, but developers want them for bug reports.

Therefore, flask.ext.script.command provides an InvalidCommand error class which is not supposed to print a stack trace when reported.

In your command handler:

from flask.ext.script.commands import InvalidCommand
[… if some command verification fails …] class MyCommand(Command):

def run(self, foo=None,bar=None):
if foo and bar:
raise InvalidCommand(“Options foo and bar are incompatible”)
In your main loop:

try:
MyManager().run()
except InvalidCommand as err:
print(err, file=sys.stderr) sys.exit(1)
This way, you maintain interoperability if some plug-in code supplies Flask-Script hooks you’d like to use, or vice versa.

Accessing local proxies
The Manager runs the command inside a Flask test context. This means that you can access request-local proxies where appropriate, such as current_app, which may be used by extensions.

API
class flask_script.Manager(app=None, with_default_commands=None, usage=None, help=None, description=None, disable_argcomplete=False)
Controller class for handling a set of commands.

Typical usage:

class Print(Command):

def run(self):
print “hello”

app = Flask(__name__)

manager = Manager(app)
manager.add_command(“print”, Print())

if __name__ == “__main__”:
manager.run()
On command line:

python manage.py print
> hello
Parameters:
app – Flask instance, or callable returning a Flask instance.
with_default_commands – load commands runserver and shell by default.
disable_argcomplete – disable automatic loading of argcomplete.
add_command(*args, **kwargs)
Adds command to registry.

Parameters:
command – Command instance
name – Name of the command (optional)
namespace – Namespace of the command (optional; pass as kwarg)
add_option(*args, **kwargs)
Adds a global option. This is useful if you want to set variables applying to the application setup, rather than individual commands.

For this to work, the manager must be initialized with a factory function rather than a Flask instance. Otherwise any options you set will be ignored.

The arguments are then passed to your function, e.g.:

def create_my_app(config=None):
app = Flask(__name__)
if config:
app.config.from_pyfile(config)

return app

manager = Manager(create_my_app)
manager.add_option(“-c”, “–config”, dest=”config”, required=False)
@manager.command
def mycommand(app):
app.do_something()
and are invoked like this:

> python manage.py -c dev.cfg mycommand
Any manager options passed on the command line will not be passed to the command.

Arguments for this function are the same as for the Option class.

command(func)
Decorator to add a command function to the registry.

Parameters: func – command function.Arguments depend on the options.
option(*args, **kwargs)
Decorator to add an option to a function. Automatically registers the function – do not use together with @command. You can add as many @option calls as you like, for example:

@option(‘-n’, ‘–name’, dest=’name’)
@option(‘-u’, ‘–url’, dest=’url’)
def hello(name, url):
print “hello”, name, url
Takes the same arguments as the Option constructor.

run(commands=None, default_command=None)
Prepares manager to receive command line input. Usually run inside “if __name__ == “__main__” block in a Python script.

Parameters:
commands – optional dict of commands. Appended to any commands added using add_command().
default_command – name of default command to run if no arguments passed.
shell(func)
Decorator that wraps function in shell command. This is equivalent to:

def _make_context(app):
return dict(app=app)

manager.add_command(“shell”, Shell(make_context=_make_context))
The decorated function should take a single “app” argument, and return a dict.

For more sophisticated usage use the Shell class.

class flask_script.Command(func=None)
Base class for creating commands.

Parameters: func – Initialize this command by introspecting the function.
get_options()
By default, returns self.option_list. Override if you need to do instance-specific configuration.

run()
Runs a command. This must be implemented by the subclass. Should take arguments as configured by the Command options.

class flask_script.Shell(banner=None, make_context=None, use_ipython=True, use_bpython=True)
Runs a Python shell inside Flask application context.

Parameters:
banner – banner appearing at top of shell when started
make_context – a callable returning a dict of variables used in the shell namespace. By default returns a dict consisting of just the app.
use_bpython – use BPython shell if available, ignore if not. The BPython shell can be turned off in command line by passing the –no-bpython flag.
use_ipython – use IPython shell if available, ignore if not. The IPython shell can be turned off in command line by passing the –no-ipython flag.
class flask_script.Server(host=’127.0.0.1′, port=5000, use_debugger=None, use_reloader=None, threaded=False, processes=1, passthrough_errors=False, **options)
Runs the Flask development server i.e. app.run()

Parameters:
host – server host
port – server port
use_debugger – Flag whether to default to using the Werkzeug debugger. This can be overriden in the command line by passing the -d or -D flag. Defaults to False, for security.
use_reloader – Flag whether to use the auto-reloader. Default to True when debugging. This can be overriden in the command line by passing the -r/-R flag.
threaded – should the process handle each request in a separate thread?
processes – number of processes to spawn
passthrough_errors – disable the error catching. This means that the server will die on errors but it can be useful to hook debuggers in (pdb etc.)
options – werkzeug.run_simple() options.
class flask_script.Option(*args, **kwargs)
Stores positional and optional arguments for ArgumentParser.add_argument.

Parameters:
name_or_flags – Either a name or a list of option strings, e.g. foo or -f, –foo
action – The basic type of action to be taken when this argument is encountered at the command-line.
nargs – The number of command-line arguments that should be consumed.
const – A constant value required by some action and nargs selections.
default – The value produced if the argument is absent from the command-line.
type – The type to which the command-line arg should be converted.
choices – A container of the allowable values for the argument.
required – Whether or not the command-line option may be omitted (optionals only).
help – A brief description of what the argument does.
metavar – A name for the argument in usage messages.
dest – The name of the attribute to be added to the object returned by parse_args().
class flask_script.Group(*options, **kwargs)
Stores argument groups and mutually exclusive groups for ArgumentParser.add_argument_group or ArgumentParser.add_mutually_exclusive_group .

Note: The title and description params cannot be used with the exclusive or required params.

Parameters:
options – A list of Option classes to add to this group
title – A string to use as the title of the argument group
description – A string to use as the description of the argument group
exclusive – A boolean indicating if this is an argument group or a mutually exclusive group
required – A boolean indicating if this mutually exclusive group must have an option selected
flask_script.prompt(name, default=None)
Grab user input from command line.

Parameters:
name – prompt text
default – default value if no input provided.
flask_script.prompt_bool(name, default=False, yes_choices=None, no_choices=None)
Grabs user input from command line and converts to boolean value.

Parameters:
name – prompt text
default – default value if no input provided.
yes_choices – default ‘y’, ‘yes’, ‘1’, ‘on’, ‘true’, ‘t’
no_choices – default ‘n’, ‘no’, ‘0’, ‘off’, ‘false’, ‘f’
flask_script.prompt_pass(name, default=None)
Grabs hidden (password) input from command line.

Parameters:
name – prompt text
default – default value if no input provided.
flask_script.prompt_choices(name, choices, default=None, resolve=, no_choice=(‘none’, ))
Grabs user input from command line from set of provided choices.

Parameters:
name – prompt text
choices – list or tuple of available choices. Choices may be single strings or (key, value) tuples.
default – default value if no input provided.
no_choice – acceptable list of strings for “null choice”

Flask-Mail

给用户发邮件是web应用的基本功能。

Flask-Mail提供了一个简单的接口用于设置SMTP,并发送邮件。

安装Flask-Mail

通过pip和easy_install安扎un个

pip install Flask-Mail

或者你可以下载最新的版本:

git clone https://github.com/mattupstate/flask-mail.git
cd flask-mail
python setup.py install

配置Flask-Mail

Flask-Mail is configured through the standard Flask config API. These are the available options (each is explained later in the documentation):

MAIL_SERVER : default ‘localhost’
MAIL_PORT : default 25
MAIL_USE_TLS : default False
MAIL_USE_SSL : default False
MAIL_DEBUG : default app.debug
MAIL_USERNAME : default None
MAIL_PASSWORD : default None
MAIL_DEFAULT_SENDER : default None
MAIL_MAX_EMAILS : default None
MAIL_SUPPRESS_SEND : default app.testing
MAIL_ASCII_ATTACHMENTS : default False

 
In addition the standard Flask TESTING configuration option is used by Flask-Mail in unit tests (see below).

Emails are managed through a Mail instance:

from flask import Flask
from flask_mail import Mail

app = Flask(__name__)
mail = Mail(app)
In this case all emails are sent using the configuration values of the application that was passed to the Mail class constructor.

Alternatively you can set up your Mail instance later at configuration time, using the init_app method:

mail = Mail()

app = Flask(__name__)
mail.init_app(app)
In this case emails will be sent using the configuration values from Flask’s current_app context global. This is useful if you have multiple applications running in the same process but with different configuration options.

Sending messages
To send a message first create a Message instance:

from flask_mail import Message

@app.route(“/”)
def index():

msg = Message(“Hello”,
sender=”from@example.com”,
recipients=[“to@example.com”])
You can set the recipient emails immediately, or individually:

msg.recipients = [“you@example.com”]
msg.add_recipient(“somebodyelse@example.com”)
If you have set MAIL_DEFAULT_SENDER you don’t need to set the message sender explicity, as it will use this configuration value by default:

msg = Message(“Hello”,
recipients=[“to@example.com”])
If the sender is a two-element tuple, this will be split into name and address:

msg = Message(“Hello”,
sender=(“Me”, “me@example.com”))

assert msg.sender == “Me <me@example.com>”
The message can contain a body and/or HTML:

msg.body = “testing”
msg.html = “<b>testing</b>”
Finally, to send the message, you use the Mail instance configured with your Flask application:

mail.send(msg)
Bulk emails
Usually in a web application you will be sending one or two emails per request. In certain situations you might want to be able to send perhaps dozens or hundreds of emails in a single batch – probably in an external process such as a command-line script or cronjob.

In that case you do things slightly differently:

with mail.connect() as conn:
for user in users:
message = ‘…’
subject = “hello, %s” % user.name
msg = Message(recipients=[user.email],
body=message,
subject=subject)

conn.send(msg)
The connection to your email host is kept alive and closed automatically once all the messages have been sent.

Some mail servers set a limit on the number of emails sent in a single connection. You can set the max amount of emails to send before reconnecting by specifying the MAIL_MAX_EMAILS setting.

Attachments
Adding attachments is straightforward:

with app.open_resource(“image.png”) as fp:
msg.attach(“image.png”, “image/png”, fp.read())
See the API for details.

If MAIL_ASCII_ATTACHMENTS is set to True, filenames will be converted to an ASCII equivalent. This can be useful when using a mail relay that modify mail content and mess up Content-Disposition specification when filenames are UTF-8 encoded. The conversion to ASCII is a basic removal of non-ASCII characters. It should be fine for any unicode character that can be decomposed by NFKD into one or more ASCII characters. If you need romanization/transliteration (i.e ß → ss) then your application should do it and pass a proper ASCII string.

Unit tests and suppressing emails
When you are sending messages inside of unit tests, or in a development environment, it’s useful to be able to suppress email sending.

If the setting TESTING is set to True, emails will be suppressed. Calling send() on your messages will not result in any messages being actually sent.

Alternatively outside a testing environment you can set MAIL_SUPPRESS_SEND to False. This will have the same effect.

However, it’s still useful to keep track of emails that would have been sent when you are writing unit tests.

In order to keep track of dispatched emails, use the record_messages method:

with mail.record_messages() as outbox:

mail.send_message(subject=’testing’,
body=’test’,
recipients=emails)

assert len(outbox) == 1
assert outbox[0].subject == “testing”
The outbox is a list of Message instances sent.

The blinker package must be installed for this method to work.

Note that the older way of doing things, appending the outbox to the g object, is now deprecated.

Header injection
To prevent header injection attempts to send a message with newlines in the subject, sender or recipient addresses will result in a BadHeaderError.

Signalling support
New in version 0.4.

Flask-Mail now provides signalling support through a email_dispatched signal. This is sent whenever an email is dispatched (even if the email is not actually sent, i.e. in a testing environment).

A function connecting to the email_dispatched signal takes a Message instance as a first argument, and the Flask app instance as an optional argument:

def log_message(message, app):
app.logger.debug(message.subject)

email_dispatched.connect(log_message)
API
class flask_mail.Mail(app=None)
Manages email messaging

Parameters: app – Flask instance
send(message)
Sends a single message instance. If TESTING is True the message will not actually be sent.

Parameters: message – a Message instance.
connect()
Opens a connection to the mail host.

send_message(*args, **kwargs)
Shortcut for send(msg).

Takes same arguments as Message constructor.

Versionadded : 0.3.5
class flask_mail.Attachment(filename=None, content_type=None, data=None, disposition=None, headers=None)
Encapsulates file attachment information.

Versionadded :
0.3.5
Parameters:
filename – filename of attachment
content_type – file mimetype
data – the raw file data
disposition – content-disposition (if any)
class flask_mail.Connection(mail)
Handles connection to host.

send(message, envelope_from=None)
Verifies and sends message.

Parameters:
message – Message instance.
envelope_from – Email address to be used in MAIL FROM command.
send_message(*args, **kwargs)
Shortcut for send(msg).

Takes same arguments as Message constructor.

Versionadded : 0.3.5
class flask_mail.Message(subject=”, recipients=None, body=None, html=None, sender=None, cc=None, bcc=None, attachments=None, reply_to=None, date=None, charset=None, extra_headers=None, mail_options=None, rcpt_options=None)
Encapsulates an email message.

Parameters:
subject – email subject header
recipients – list of email addresses
body – plain text message
html – HTML message
sender – email sender address, or MAIL_DEFAULT_SENDER by default
cc – CC list
bcc – BCC list
attachments – list of Attachment instances
reply_to – reply-to address
date – send date
charset – message character set
extra_headers – A dictionary of additional headers for the message
mail_options – A list of ESMTP options to be used in MAIL FROM command
rcpt_options – A list of ESMTP options to be used in RCPT commands
attach(filename=None, content_type=None, data=None, disposition=None, headers=None)
Adds an attachment to the message.

Parameters:
filename – filename of attachment
content_type – file mimetype
data – the raw file data
disposition – content-disposition (if any)
add_recipient(recipient)
Adds another recipient to the message.

Parameters: recipient – email address of recipient.

Flask-Admin

Flask-Admin是一个简单易用的Flask扩展,能让你给应用添加一个管理员接口。它深受Django-admin影响,但开发者能通过它全面控制应用的外观、感觉和功能。

Quick Start
Introduction
Initialization
Adding views
Authentication
Generating URLs
Model Views
File Admin
Examples
Migrating from Django
Design Philosophy
Getting started
Authentication
Templates
Tips and hints
Working with templates
Inheritance
Building blocks
Power & Flexibility
Jinja2 & Flask Admin
Adding an Index Page
Working with your Models
Environment variables
Customizing templates
Localization
How to enable localization(定位)
Usage Tips
General tips
SQLAlchemy
MongoEngine
Database backends
SQLAlchemy backend
GeoAlchemy backend
MongoEngine backend
Peewee backend
PyMongo backend
Adding a new model backend
Extending BaseModelView
Implementing filters
Form rendering rules
Getting started
Built-in rules
Enabling CSRF Validation
Further reading
API
flask.ext.admin.base
flask.ext.admin.helpers
flask.ext.admin.model
flask.ext.admin.form
flask.ext.admin.form.rules
flask(烧瓶).ext.admin.form.fields
flask.ext.admin.form.upload
flask.ext.admin.tools
flask.ext.admin.actions
flask.ext.admin.contrib.sqla
flask.ext.admin.contrib.mongoengine
flask.ext.admin.contrib.mongoengine.fields
flask.ext.admin.contrib.peewee(小东西)
flask(烧瓶).ext.admin.contrib.pymongo
flask.ext.admin.contrib.fileadmin
flask.ext.admin.model.template(模板)

Flask-Login

Flask-Login 提供了用户会话管理功能。他操控着登录、登出、记住用户等任务。

It will:

Store the active user’s ID in the session, and let you log them in and out easily.
Let you restrict views to logged-in (or logged-out) users.
Handle the normally-tricky “remember me” functionality.
Help protect your users’ sessions from being stolen by cookie thieves.
Possibly integrate with Flask-Principal or other authorization extensions later on.
However, it does not:

Impose a particular database or other storage method on you. You are entirely in charge of how the user is loaded.
Restrict you to using usernames and passwords, OpenIDs, or any other method of authenticating.
Handle permissions beyond “logged in or not.”
Handle user registration or account recovery.

Flask-MongoEngine

这是一个用于整合MongoEngine的Flask扩展。更多的信息,你可以参照MongoEngine文档

安装Flask-MongoEngine

通过pip安装

pip install flask-mongoengine

配置

基础配置是很简单的,仅用于实现扩展:

from flask import Flask
from flask.ext.mongoengine import MongoEngine

app = Flask(__name__)
app.config.from_pyfile('the-config.cfg')
db = MongoEngine(app)

或者,你要在app初始化之前设置你的数据库,那么需要注意应用工厂:

from flask import Flask
from flask.ext.mongoengine import MongoEngine
db = MongoEngine()
...
app = Flask(__name__)
app.config.from_pyfile('the-config.cfg')
db.init_app(app)

 

By default, Flask-MongoEngine assumes(承担) that the mongod instance(实例) is running on localhost on port 27017, and you wish to connect to the database named test.

If MongoDB is running elsewhere(在别处), you should provide the host and port settings in the ‘MONGODB_SETTINGS’ dictionary wih app.config.:

app.config['MONGODB_SETTINGS'] = {
'db': 'project1',
'host': '192.168.1.35',
'port': 12345
 }

If the database requires authentication(证明), the username and password arguments should be provided ‘MONGODB_SETTINGS’ dictionary wih app.config.:

app.config['MONGODB_SETTINGS'] = {
'db': 'project1',
'username':'webapp',
'password':'pwd123'
 }

 

Uri style connections are also supported, just supply the uri as the host in the ‘MONGODB_SETTINGS’ dictionary with app.config. Note that database name from uri has priority(优先) over name.

app.config['MONGODB_SETTINGS'] = {
    'db': 'project1',
    'host': 'mongodb://localhost/database_name'
}

Connection settings may also be provided individually(个别地) by prefixing(加前缀) the setting with ‘MONGODB_’ in the app.config.:

app.config['MONGODB_DB'] = 'project1'
app.config['MONGODB_HOST'] = '192.168.1.35'
app.config['MONGODB_PORT'] = 12345
app.config['MONGODB_USERNAME'] = 'webapp'
app.config['MONGODB_PASSWORD'] = 'pwd123'

 

自定义Queryset
flask-mongoengine attaches(依附) the following methods to Mongoengine’s default QuerySet:

get_or_404: works like .get(), but calls abort(中止计划)(404) if the object DoesNotExist.
first_or_404: same as above, except for .first().
paginate: paginates(为…标页数) the QuerySet. Takes two arguments, page and per_page.
paginate_field: paginates a field from one document in the QuerySet. Arguments: field_name, doc_id, page, per_page.
Examples:

# 404 if object doesn't exist
def view_todo(todo_id):
    todo = Todo.objects.get_or_404(_id=todo_id)
..

# Paginate through todo
def view_todos(page=1):
    paginated_todos = Todo.objects.paginate(page=page, per_page=10)

# Paginate through tags of todo
def view_todo_tags(todo_id, page=1):
    todo = Todo.objects.get_or_404(_id=todo_id)
    paginated_tags = todo.paginate_field('tags', page, per_page=10)

 

Properties of the pagination(标记页数) object include: iter_pages, next, prev, has_next, has_prev, next_num, prev_num.

In the template:

{% macro render_pagination(pagination, endpoint) %}
  <div class=pagination>
  {%- for page in pagination.iter_pages() %}
    {% if page %}
      {% if page != pagination.page %}
        <a href="{{ url_for(endpoint, page=page) }}">{{ page }}</a>
      {% else %}
        <strong>{{ page }}</strong>
      {% endif %}
    {% else %}
      <span class=ellipsis>…</span>
    {% endif %}
  {%- endfor %}
  </div>
{% endmacro %}

MongoEngine and WTForms
You can use MongoEngine and WTForms like so:

from flask.ext.mongoengine.wtf import model_form

class User(db.Document):
email = db.StringField(required=True)
first_name = db.StringField(max_length=50)
last_name = db.StringField(max_length=50)

class Content(db.EmbeddedDocument):
text = db.StringField()
lang = db.StringField(max_length=3)

class Post(db.Document):
title = db.StringField(max_length=120, required=True)
author = db.ReferenceField(User)
tags = db.ListField(db.StringField(max_length=30))
content = db.EmbeddedDocumentField(Content)

PostForm = model_form(Post)

def add_post(request):
form = PostForm(request.POST)
if request.method == ‘POST’ and form.validate():
# do something
redirect(‘done’)
return render_template(‘add_post.html’, form=form)
Supported fields
StringField
BinaryField
URLField
EmailField
IntField
FloatField
DecimalField
BooleanField
DateTimeField
ListField (using wtforms.fields.FieldList )
SortedListField (duplicate(复制) ListField)
EmbeddedDocumentField (using wtforms.fields.FormField and generating(产生的) inline(内联的) Form)
ReferenceField (using wtforms.fields.SelectFieldBase with options loaded from QuerySet or Document)
DictField
Not currently supported field types:
ObjectIdField
GeoLocationField
GenericReferenceField
Session Interface¶
To use MongoEngine as your session(会议) store simple configure(安装) the session interface(界面):

from flask.ext.mongoengine import MongoEngine, MongoEngineSessionInterface

app = Flask(__name__)
db = MongoEngine(app)
app.session_interface = MongoEngineSessionInterface(db)

招聘

寻求小伙伴一起开发中国最牛逼的3D打印机

【机械工程师】

职责
承担主要机械开发工作
制定装配流程
要求
1. 基本的机械制图及自主设计能力,了解基本的加工工艺;
2. 机械装配检修、问题处理能力;
3. 产品原型设计及加工测试能力;
4. 批量生产可行性设计能力;(能力需求较高)
5. 后期维护预估计可维护性设计能力;(能力需求较高)

6. 熟练使用SolidWorks、AutoCAD、UG等软件

 

【助理机械工程师】

职责
协助机械工程师进行开发、测试等工作
编撰设计文档
要求
1. 基本的机械制图及自主设计能力,了解基本的加工工艺;
2. 机械装配检修、问题处理能力;
3. 熟练使用SolidWorks、AutoCAD、UG等软件
【助理电子工程师】

工作地点:成都 or 深圳

职位职责

 

 

职位要求

1.动手能力强

2.

一年以上的sch,pcb layout经验,熟悉模电数电。
stm32  arduino  c51编程开发经验,也要一年以上。
动手能力强。

1熟练掌握各种元器件焊接及电路板生产流程  2熟练操作altium disigner或者pads等pcb设计  3具有单片机至少一到两年开发经验。 4熟悉数电模电,并熟练掌握multisim电路设计软件

 

【嵌入式工程师\软件工程师】

工作地点:成都 or 深圳
职位职责
在嵌入式平台上进行开发工作
方案分析、规划与项目管理
开发文档撰写

职位要求:
熟悉linux、C\C++
熟练使用python、nodejs、lua其中一门脚本语言
能够使用html5、jsp进行前端开发
能够使用git进行项目管理
精通arduino、树莓派、mbed其中一个开源硬件平台
为人和善、沟通协调能力优秀

 

【应用工程师】

 

【web前端】

工作地点:成都 or 深圳

职位职责

 

职位要求

 

【web开发】

工作地点:成都 or 深圳

职位职责

 

职位要求

 

【社区经理】

[工作地点]

成都武侯区

[岗位职责]

创客空间日常管理

线上线下创客活动的策划与运营

[职位要求]

具备活动策划组织能力,熟练使用PPT、PS一类软件

简历可发到邮箱:clz@clz.me

 

 

免费3D建模软件推荐

blender

 

 

wings 3D

 

 

Sculptris

Flask-login的使用

github:https://github.com/maxcountryman/flask-login/blob/master/docs/index.rst
原手册:http://flask-login.readthedocs.org/en/latest/

翻译1:http://docs.jinkan.org/docs/flask-login/

翻译2:http://www.cnblogs.com/bracken/archive/2013/02/25/2932788.html

例程:
http://gouthamanbalaraman.com/blog/minimal-flask-login-example.html
https://github.com/mrjoes/flask-admin/blob/master/examples/auth/app.py