Git Product home page Git Product logo

gae-init's Introduction

gae-init

Slack Status code style: prettier

gae-init is the easiest boilerplate to kick start new applications on Google App Engine using Python, Flask, RESTful, Bootstrap and tons of other cool features.

Read the documentation, where you can find a complete feature list, a detailed tutorial, the how to section and more..

The latest version is always accessible from https://gae-init.appspot.com

Requirements

Make sure you have all of the above or refer to the docs on how to install the requirements.

Initializing the project

cd /path/to/project-name
yarn

To install Gulp as a global package:

yarn global add gulp-cli

Running the Development Environment

cd /path/to/project-name
gulp

To test it visit http://localhost:3000 in your browser.


For a complete list of commands:

gulp help

Local testing

If you wish to run an automated test script, there is an additional dependency which can be installed with:

pip install -r test-requirements.txt

A simple test script framework, following the approach from the Google App Engine docs, can be run:

python main/runner.py --test-path tests ${HOME}/google-cloud-sdk/

This simply tests that the site can start up; that the index page exists (and returns an http response code of 200), and that a non-existent page returns an http response code of 404.

The test framework is easily extensible.

Deploying on Google App Engine

gulp deploy
gulp deploy --project=foo
gulp deploy --project=foo --version=bar
gulp deploy --project=foo --version=bar --no-promote

Resetting the project

If something goes wrong you can always do:

gulp reset
yarn
gulp

Tech Stack

gae-init's People

Contributors

asmith26 avatar davidstackio avatar dependabot-preview[bot] avatar dependabot-support avatar dependabot[bot] avatar georstef avatar gmist avatar greenkeeper[bot] avatar jakedotio avatar jasminegrewal avatar joernhees avatar lepture avatar lipis avatar mdxs avatar pgrimaud avatar pigeonflight avatar rbubley avatar sadovnychyi avatar topless avatar wilfriede avatar xcash avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gae-init's Issues

Problem with my windows stuff #2

New python executable in temp\venv\Scripts\python.exe
Installing setuptools, pip...done.
pip install -q -r requirements.txt
Traceback (most recent call last):
  File "C:\Developer\Projects\WebDevelopement\temp\venv\lib\site.py", line 703, in <module>
    main()
  File "C:\Developer\Projects\WebDevelopement\temp\venv\lib\site.py", line 683, in main
    paths_in_sys = addsitepackages(paths_in_sys)
  File "C:\Developer\Projects\WebDevelopement\temp\venv\lib\site.py", line 282, in addsitepackages
    addsitedir(sitedir, known_paths)
  File "C:\Developer\Projects\WebDevelopement\temp\venv\lib\site.py", line 204, in addsitedir
    addpackage(sitedir, name, known_paths)
  File "C:\Developer\Projects\WebDevelopement\temp\venv\lib\site.py", line 173, in addpackage
    exec(line)
  File "<string>", line 1, in <module>
  File "C:\google-cloud-sdk\bin\dev_appserver.py", line 10, in <module>
    import bootstrapping.bootstrapping as bootstrapping
  File "C:\google-cloud-sdk\bin\bootstrapping\bootstrapping.py", line 21, in <module>
    from googlecloudsdk.core.credentials import store as c_store
  File "C:\google-cloud-sdk\bin\bootstrapping\..\..\lib\googlecloudsdk\core\credentials\store.py", line 18, in <module>
    from googlecloudsdk.core.credentials import flow
  File "C:\google-cloud-sdk\bin\bootstrapping\..\..\lib\googlecloudsdk\core\credentials\flow.py", line 13, in <module>
    from oauth2client import tools
  File "C:\google-cloud-sdk\bin\bootstrapping\..\..\lib\oauth2client\tools.py", line 58, in <module>
    argparser = argparse.ArgumentParser(add_help=False)
  File "C:\google-cloud-sdk\bin\bootstrapping\..\..\lib\argparse\__init__.py", line 1585, in __init__
    prog = _os.path.basename(_sys.argv[0])
AttributeError: 'module' object has no attribute 'argv'

Issue with minor version of CURRENT_VERSION_ID

According to https://developers.google.com/appengine/docs/python/#Python_The_environment the minor version of CURRENT_VERSION_ID is always "1" on the development web server.

However, I'm seeing stuff like 423594672088649939 using version 1.8.9 of the SDK (on a Xubuntu virtual machine), which I'm afraid sometimes triggers an exception in config.py when converting to long in the CURRENT_VERSION_TIMESTAMP; and/or resulting in CURRENT_VERSION_DATE being way out in the past or the future (that is: on the development web server).

Is this something in my development VM, or are others also seeing the CURRENT_VERSION_ID.split('.')[1] unequal to "1" on their local development web server testing (using SDK 1.8.9)?

Could not guess mimetype warnings for .ttf files

When updating a gae-init based project to appspot.com, using for example:

appcfg.py update main --oauth2

Then four warnings (or at least notifications) are shown in the log:

...
Could not guess mimetype for static/font/fontawesome-webfont.ttf.  Using application/octet-stream.
Could not guess mimetype for static/font/glyphicons-halflings-regular.ttf.  Using application/octet-stream.
Could not guess mimetype for static/font/fontawesome-webfont.ttf.  Using application/octet-stream.
Could not guess mimetype for static/font/glyphicons-halflings-regular.ttf.  Using application/octet-stream.
...

Note that these 4 lines are about 2 files, namely the two .ttf files found in main/static/font/ and apparently defaulting to assume the "application/octet-stream" mime type for them when serving.

Whether right or wrong... I lack the knowledge; so Google to the rescue and I found: https://code.google.com/p/googleappengine/issues/detail?id=6183 in which the "Jul 17, 2013" comment provides some interesting clue. There might be some value in trying to tell GAE they are of the "font/ttf" mime type. It hints at a possible gzip or deflate compression and notes that "TTF fonts are great candidates for gzip compression, which saves about 20% on the size of my fonts. This results in decreased load times for users and reduced bandwidth for app owners."

Thus I tried in app.yaml the following:

...
- url: /p/font/(.*\.(ttf))
  static_files: static/font/\1
  upload: static/font/(.*\.(ttf))
  mime_type: font/ttf
  expiration: 1000d

- url: /p/font/(.*\.(ttf))
  static_dir: static/font/\1
  expiration: 1000d
...

And that made the warnings go away, while still only "Cloning 13 static files" (I was afraid that there might be a duplication on the upload... but there isn't?) and in testing the site I didn't spot a difference in behaviour / look-and-feel.

However, I'm not sure whether the above is better or not... I like the cleaner log when updating to appspot.com and would assume that removing guesswork is better; but whether the compression is really better (as hinted)?

Any gi with an opinion on this (and/or can we measure / see the possible gain)?

Problem with my windows stuff

[18:29:31] ---CLEAN ALL ----------------------------------------------
Traceback (most recent call last):
  File ".\run.py", line 624, in <module>
    run()
  File ".\run.py", line 599, in run
    run_clean_all()
  File ".\run.py", line 511, in run_clean_all
    remove_file_dir(DIR_NODE_MODULES)
  File ".\run.py", line 134, in remove_file_dir
    shutil.rmtree(file_dir)
  File "C:\Python27\lib\shutil.py", line 244, in rmtree
    rmtree(fullname, ignore_errors, onerror)
  File "C:\Python27\lib\shutil.py", line 244, in rmtree
    rmtree(fullname, ignore_errors, onerror)
  File "C:\Python27\lib\shutil.py", line 244, in rmtree
    rmtree(fullname, ignore_errors, onerror)
  File "C:\Python27\lib\shutil.py", line 244, in rmtree
    rmtree(fullname, ignore_errors, onerror)
  File "C:\Python27\lib\shutil.py", line 244, in rmtree
    rmtree(fullname, ignore_errors, onerror)
  File "C:\Python27\lib\shutil.py", line 244, in rmtree
    rmtree(fullname, ignore_errors, onerror)
  File "C:\Python27\lib\shutil.py", line 244, in rmtree
    rmtree(fullname, ignore_errors, onerror)
  File "C:\Python27\lib\shutil.py", line 244, in rmtree
    rmtree(fullname, ignore_errors, onerror)
  File "C:\Python27\lib\shutil.py", line 244, in rmtree
    rmtree(fullname, ignore_errors, onerror)
  File "C:\Python27\lib\shutil.py", line 244, in rmtree
    rmtree(fullname, ignore_errors, onerror)
  File "C:\Python27\lib\shutil.py", line 244, in rmtree
    rmtree(fullname, ignore_errors, onerror)
  File "C:\Python27\lib\shutil.py", line 244, in rmtree
    rmtree(fullname, ignore_errors, onerror)
  File "C:\Python27\lib\shutil.py", line 244, in rmtree
    rmtree(fullname, ignore_errors, onerror)
  File "C:\Python27\lib\shutil.py", line 244, in rmtree
    rmtree(fullname, ignore_errors, onerror)
  File "C:\Python27\lib\shutil.py", line 249, in rmtree
    onerror(os.remove, fullname, sys.exc_info())
  File "C:\Python27\lib\shutil.py", line 247, in rmtree
    os.remove(fullname)
WindowsError: [Error 3] The system cannot find the path specified: 'node_modules\\less\\node_modules\\request\\node_modu
les\\lodash.merge\\node_modules\\lodash._basecreatecallback\\node_modules\\lodash.bind\\node_modules\\lodash._createwrap
per\\node_modules\\lodash._basebind\\node_modules\\lodash._basecreate'
PS C:\Developer\Projects\WebDevelopement>

help me to understand the source code

hi, I've been learning flask on gae development these days, and I found this repo is amazing, but I got confused by these codes below:

_PROPERITES={
    key,
    id,
    version
}

and all like above.
what's these mean? any reference on flask docs?

tks a lot

golang support

appengine now supports golang (in addition to python, java and php)
would be nice if gae-init would support that runtime
since it is a good lunguage and its at very mature state right now

How to add a front end library?

This question from StackOverflow needs one more vote to be opened, but until then here is the answer.


There are usually 3 things that you need to do in order to add a 3rd party library into gae-init project.

As an example I will use the Selectize library since I believe is a bit better choice than the requested Bootstrap Tags Input.

In the bower.json file add the name of the library (or the direct link to the git repo) in the dependencies section and depending on the library you will have to write which files you need from it described in the exportsOverride section.

Here is how the bower.json will look like:

{
  "dependencies": {
    ...
    "selectize": "~0"
  },
  "exportsOverride": {
    ...
    "selectize": {
      "js": "dist/js/*",
      "less": "dist/less/*.less",
      "less/plugins": "dist/less/plugins/*"
    }
  }
}

Because Selectize libriary has JavaScript and Less files we will have to make sure that they will be included in the build process and used by gae-init.

The JavaScript files are defined in the config.py:

SCRIPTS = [
    ('libs', [
        ...
        'ext/js/selectize/selectize.js',
      ]),
    ...

To merge the Less files into one single CSS in the end import them in the style.less like this:

...
@import "../../ext/less/selectize/selectize";
@import "../../ext/less/selectize/selectize.bootstrap3";
@import "../../ext/less/selectize/plugins/remove_button";
...

Finally you will have to execute the ./run.py -s. Since there were changes in the bower.json the 3rd party library will be downloaded and copied into the right place.


Just to see it in action you could add a simple input field somewhere in your template:

<input class="form-control" type="text" value="foo bar">

and run the following code from the console of your browser (as taken from their official examples):

$('.form-control').selectize({
  plugins: ['remove_button'],
  delimiter: ' ',
  persist: false,
  create: function(input) {
    return {
      value: input,
      text: input
    }
  }
});

Here is the final result in action: Selectize gae-init example.

Python kwgs convension

Switch to standard **kwargs or **kws, where I am in favour of the first one since its widely used.

feature request: @login_required and @admin_required methods argument

would anyone else find it convenient to have the possibility to specify which methods the standard auth decorators become active for?

I often have the case where it's ok to view (GET) a page for everyone but modification (POST) requires login or admin...

If someone else finds this interesting i'd rewrite the decorators similarly to django's view function decorators in a backwards compatible way, so you can still use @login_required without args, but you could also use @login_required(methods=['POST']) to only require a login for POST requests.

security considerations: email & pw auth

our email & pw auth is pretty much HTTP / HTML form based auth. It's a very common technique, but also very very very insecure when used via http as it sends plain text credentials around.

I think we should tighten this up in a couple of ways:

  • for now we should quickly de-activate email & pw login if we're not on https (https-only decorator?)
  • redirect relevant auth pages to https (causes problems for "https://version.app.appspot.com", so those URIs need to be rewritten to "https://version-dot-app.appspot.com", but probably still the way to go in general)
  • preferably in general serve everything via https only (as otherwise those redirects could easily be circumvented by a man in the middle attack as without https the client won't be able to tell if the http was modified during transport), HSTS comes to mind... flask-sslify?

Throughs 500 error when Facebook users doesn't have a primary email

/_s/callback/facebook/oauth-authorized/?code=AQCuUVQb_....


'email'
Traceback (most recent call last):
  File "lib.zip/flask/app.py", line 1475, in full_dispatch_request
    rv = self.dispatch_request()
  File "lib.zip/flask/app.py", line 1461, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "lib.zip/flask_oauth.py", line 434, in decorated
    return f(*((data,) + args), **kwargs)
  File "/base/data/home/apps/s~lim-life-line/date.377588946281106576/auth.py", line 380, in facebook_authorized
    user_db = retrieve_user_from_facebook(me.data)
  File "/base/data/home/apps/s~lim-life-line/date.377588946281106576/auth.py", line 406, in retrieve_user_from_facebook
    response['email'],
KeyError: 'email'

Node dependency check fails on linux

After an accidental format, I had to re-setup my linux machine. Everything worked out of the box except node. I fixed it by replacing node with nodejs in run.py.

:486 of run.py

def check_nodejs():
    return bool(spawn.find_executable('nodejs')), 'Node.js', '#nodejs'

Include all 3rd party OAuth from gae-init-auth here

Since the whole thing is broken down now in separate files and even in the admin console there is separate link for OAuth maybe it makes sense to include all of them here and not maintaining both files as it's not actually adding any overhead AFAIK...

What do you think?!

Da list!

  • Google
  • Facebook
  • Twitter
  • Bitbucket
  • Dropbox
  • GitHub
  • Instagram
  • Linkedin
  • Microsoft
  • Reddit
  • StackOverflow
  • VK
  • Yahoo!

Everything should be sorted by name except for the oauth.html template where the providers Google, Facebook and Twitter always should be first and the rest in alphabetical order.

Importing model from nested structure.

Well, I have a bit more complicated structure for my work project and I am facing some trouble with the imports of the new model.

My major difference is that I keep controllers, lib and models under a dir called server so my models can be found under main/server/model instead of main/model.

In config.py I manage to do successfully from server import model but when I go for example to main/server/model/user.py and I try to do from server import model I get an error model cannot be found, instead if I do from server.model import Base everything works normal. Like this though I have to define everytime all the classes I want imported. Any ideas anyone? I have struggled a bit with paths in appengine_config.py but no luck :(

Function auth in auth.py

I believe that def auth serves more than one purposes. Would it make more sense if it was separate, like def auth_signin, def auth_signup ?

npm install step is very slow

This is more a discussion than a bug, maybe i'm doing it wrong: after a gae-init release and a lot of merging things into projects i like to upgrade things in a clean way.

Usually i would do ./run.py -C but i notice that the npm step is very slow. We're talking about > 10 minutes on a very fast internet connection.
If i run npm update it seems to be even slower.

As i'm not a node guru: is there a way to speed this up?

output here: https://gist.github.com/joernhees/ce47441e0c76337ea6db

Log in with a different user

Consider the case where I sign in at gae-init with my Google account. I changed my mind and I want to sign in with my corporate account.

I hit the sign out button and trying to sign in again, but the service logs me in with my existing running session.

The expected behavior would be to give you the option if you want to change the account you want to sign in.

admin usermanager shows outdated info on update

If you update the status of a user to be an admin and hit "Update" you're sent back to the user list, where it still shows the user not to be an admin.
Once you reload the page the display is correct.

Maybe could be solved with an ancestor query?

HTML validation

HTML validator requires maximum 3 decimal digits for the seconds. moement.js with python isoformat() produce more.

XSS vulnerability in Admin Config

Not a major problem, as the Admin should now better... but there is an XSS vulnerability in the current Announcement HTML field on the Admin Config form.

To reproduce: run ./run.py -ms and browse to http://localhost:8080/admin/config/ (if needed login as an administrator). Then provide <script>alert(document.cookie);</script> in the Announcement HTML field and hit Update Config ... start enjoying the cookies-in-your-face.

What I would like to know is whether we already have precautions against XSS (see https://www.owasp.org/index.php/Testing_for_Cross_site_scripting for details), for example in support libraries, and how we could turn them on/off as needed on fields. Perhaps we simply need to set a flag somewhere?

ImportError: No module named flask.ext

there are always appear the error by follow tutorial

[22:43:36] --------DONE ----------------------------------------------
INFO 2014-09-18 14:43:38,541 devappserver2.py:725] Skipping SDK update check.
WARNING 2014-09-18 14:43:38,546 api_server.py:383] Could not initialize images API; you are likely missing the Python "PIL" module.
INFO 2014-09-18 14:43:38,580 api_server.py:171] Starting API server at: http://localhost:49195
INFO 2014-09-18 14:43:38,609 dispatcher.py:183] Starting module "default" running at: http://127.0.0.1:8080
INFO 2014-09-18 14:43:38,639 admin_server.py:117] Starting admin server at: http://localhost:8081
ERROR 2014-09-18 14:43:40,766 wsgi.py:262]
Traceback (most recent call last):
File "/Users/Alpha/google-cloud-sdk/platform/google_appengine/google/appengine/runtime/wsgi.py", line 239, in Handle
handler = _config_handle.add_wsgi_middleware(self._LoadHandler())
File "/Users/Alpha/google-cloud-sdk/platform/google_appengine/google/appengine/runtime/wsgi.py", line 298, in _LoadHandler
handler, path, err = LoadObject(self._handler)
File "/Users/Alpha/google-cloud-sdk/platform/google_appengine/google/appengine/runtime/wsgi.py", line 84, in LoadObject
obj = import(path[0])
File "/Users/Alpha/Downloads/phonebook/main/main.py", line 5, in
from flask.ext import wtf
ImportError: No module named flask.ext
INFO 2014-09-18 14:43:40,776 module.py:652] default: "GET /_ah/warmup HTTP/1.1" 500 -

View in JSON returns 404 on homepage

When I click View in JSON on https://gae-init.appspot.com/ then it returns:

{
  "error_class": "NotFound", 
  "error_code": 404, 
  "error_message": "Not Found", 
  "error_name": "not-found", 
  "status": "error"
}

From the framework's perspective of view, it's correct. But as a new user who wants to explore the power of "gae-init", it is a bad user experience.

Minification bug and suggestions.

I used

./run.py -m

in order to create the minified output of JavaScript for the deployed version. I ended up with a file containing only ;

The bug came from my ignorance where I had defined twice a path in my SCRIPT_MODULES in config.py.

You can reproduce

    'scripts': [
        'src/script/common/util.coffee',
        'src/script/common/service.coffee',
        'src/script/common/upload.coffee',

        # Add this duplicate entry below
        'src/script/site/app.coffee',
        'src/script/site/app.coffee',
        ....
    ]

The case is that minifier also didn't spit any message. I know I should have been more careful but when the list gets bigger and things get copy pasted .. mistakes happen.

This might be a good entry point to bring up my <3 for Grunt one more time. Since Grunt is used for monitoring changes in files why not use it for building them also. This is going to save us one terminal window ;). The run script I suggest to be used for starting stopping the App Engine Server and deploying the app.

@lipis, @mdxs, @gmist, Where do you stand on this one? I think I will give it a finger in the weekend :)

Using the Flask extensions guidance

In pull request #47, I've moved the Flask-WTF into main/lib/flask_wtf/ and updated imports to use flask.ext.wtf. The gae-init/gae-init-babel#9 PR for gae-init-babel proposes a similar move for Flask-Babel.

In the discussion that followed, https://github.com/lipis mentioned:

I remember playing around with the flask_ext, flaskext and flask.ext and I agree that we have to follow the latest and greatest standards, I'm just too careful with folder structure changes and would prefer to spend some time to check what's best..

To help this assessment, this issue documents my findings.

As I noted in the PRs, http://flask.pocoo.org/docs/extensiondev/#anatomy-of-an-extension shows that the flask.ext.foo notation can be followed to find the extensions (which in recent incarnations of Flask are all moving towards a more maintainable structure).

The same article shows that the extension folder flask_wtf/ (as it is also named in the original source: https://github.com/lepture/flask-wtf/tree/master/flask_wtf) can sit in our main/lib/ while the flask.ext does it's magic to resolve imports from flask.ext.wtf (this seems to be a common pattern for Flask extensions).

Following the code, https://github.com/gae-init/gae-init/blob/master/main/lib/flask/ext/__init__.py explains the flask.ext strategy to transition away from flaskext.foo to flask_foo and in which order the extensions are tried to be imported (when asking for flask.ext.foo it first tries to import from flask_foo and if that fails from flaskext.foo).

Wondering on whether directly importing from flask_foo might be preferred (instead of using the middleware flask.ext.foo ... perhaps performance?), the http://stackoverflow.com/a/19296731/2315612 answer refers to the fine documentation at http://flask.pocoo.org/docs/extensiondev/#extension-import-transition

Inside the extensions they do use import flask_foo, but it seems this is to allow re-use of the packages outside the Flask context. And the changes I propose in the PRs do allow the use of both import flask.ext.foo and import flask_foo when the extension is located in main/lib/flask_foo

Aiming to be "the easiest way to kick start new applications on Google App Engine using Flask, ..."; I think we should be good citizens and follow the latest Flask extension guidance (see article reference above): using flask.ext.foo for imports and having the extension folder flask_foo/ inside main/lib/.

indexes prefilled for default gae-init features

i would like to propose to have the indexes for the default gae-init features prefilled in the index.yaml file.

My rational for this is that it just happened to me that as a dev i didn't test all the default features of gae-init first in the dev server before deploying my app, but just the parts i developed myself. In production the userlist and custom login then didn't work because of missing compound indices...

This is a bit developer unfriendly i think, especially for rather trivial apps. Would it hurt to have them prefilled?

Currently i think these are the places where such indices are currently used by default:

  • userlist
  • custom login (& email checks)

Architecture proposal

Fellow programmers,

I am creating this issue to put down some of my thoughts about the front end solutions of gae-init and hear back your feedback and suggestions.

My suggestion is that everything that has to do with the front end should be moved under /static directory including node_modules, bower_components, bower.json, package.json and Gruntfile.coffee since they affect files from static and below.

Building the front end should be completely taken care of from Gruntfile and run.py should be responsible only to take care of the server.

If we set it up like this we will be able to combine the powehouse back end of gae-init with any front end generator out there. Most of the generators come with their custom Gruntfile so in most cases we don't even have to configure that.

I am aware that its not a small request, since a lot of things need to be tested and some things might break, but providing the flexibility for any front end environment like angular, backbone or even webapp-skeleton without much hassle, will also provide a boost in the user base of gae-init.

As said in the beginning, food for thought.

Cheers.

Should flush also clean the "temp" folder?

When I flush the local datastore with a ./run.py -fit removes the ./temp/datastore/ folder (and all files inside) as expected. It however leaves the ./temp/ folder, which to my knowledge is not used for other purposes. Is this as designed (perhaps used in another derived gae-init-* project), or could we simply add a remove_dir(DIR_TEMP) to run_flush in run.py?

Rename dst -> dist

Proposal for version 1. Observing other implementations like bootstrap and many of yeoman projects they use dist instead of dst. I can feel that both src and dst are 3 characters but I think what most people use is stronger argument.

Phonebook tutorial is out of date with latest release of gae-init from master

Was trying to run through the tutorial and when adding the main/contact.py code there is a dependency on wtf, when in the newest release apparently you have to use wtforms.

class ContactUpdateForm(wtf.Form):
  name = wtf.StringField('Name', [wtf.validators.required()])
  email = wtf.StringField('Email', [wtf.validators.optional(), wtf.validators.email()])
  phone = wtf.StringField('Phone', [wtf.validators.optional()])
  address = wtf.TextAreaField('Address', [wtf.validators.optional()])

should become

import wtforms
class ContactUpdateForm(wtf.Form):
  name = wtforms.StringField('Name', [wtforms.validators.required()])
  email = wtforms.StringField('Email', [wtforms.validators.optional(), wtforms.validators.email()])
  phone = wtforms.StringField('Phone', [wtforms.validators.optional()])
  address = wtforms.TextAreaField('Address', [wtforms.validators.optional()])

Interestingly, we still need to inherit wtf.Form in order to get the validate_on_submit() functionality.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.