PK hsC̀ tarbell-0.8/searchindex.jsSearch.setIndex({objects:{},terms:{all:[2,3,1,4],code:[2,4],skeleton:4,skip:2,global:4,runserv:[2,5],follow:[4,3],row:[2,4],whose:0,privat:2,depend:4,flask:[0,5,1],specif:[5,3],"2fwww":2,cdnj:4,under:4,everi:[4,1],string:4,song:2,fals:1,none:1,offlin:2,context_processor:1,facebook:3,fab:[2,3],glyphicon:3,list:4,upload:3,iter:4,item:4,adjust:2,last_upd:3,refer:[0,4,1],create_json:1,pleas:3,tarbel:[0,1,2,3,4,5],depobj:4,pass:4,download:2,bake:[0,1],click:2,index:[2,3,1,4],what:[0,2,4],chicago:5,access_typ:2,advanc:1,access:[2,3,1,4],delet:2,version:[5,1],"new":[2,4],"public":[2,1],told:5,full:2,gener:[2,3],onli:4,here:[2,1],bodi:4,let:[2,4,1],address:1,locat:1,valu:[2,3,1,4],great:2,process_text:4,host:3,credit:4,action:5,chang:2,overrid:1,repositori:5,revok:2,tweak:4,modul:4,filenam:4,api:[2,1],instal:[0,2,5],txt:5,select:2,highli:2,from:[2,1],would:[2,1],visit:[2,5],next:2,websit:3,stylesheet:4,call:[3,1,4],asset:[0,4],recommend:2,scope:2,preview:4,type:[4,1],more:[0,5,1],analytics_path:1,awesome_project:1,flag:3,"_base":[0,4],compani:0,hold:4,must:4,barebon:4,graphic:4,restor:2,setup:[0,3],work:[2,4],uniqu:4,dev:5,histori:0,can:[0,2,4,1],root:[2,1],def:1,control:1,prompt:2,tab:2,process:[3,1],share:2,templat:[0,1,2,3,4,5],want:[2,3],onlin:3,alwai:[3,1],end:4,spreadsheet:[0,2,4,1],how:[0,4,5],pure:1,subdirectori:5,answer:2,simpl:[0,4,3],css:[2,3,1,4],updat:4,product:3,clone:5,after:0,halfl:3,mac:5,s3deploi:3,date:4,default_context:1,underscor:4,data:[4,1],demonstr:4,github:5,bootstrap:[3,1],credenti:[2,3],inform:[5,1],"switch":2,environ:5,allow:2,key_id:3,"2fauth":2,order:[2,1],help:[0,2,4,3],becaus:2,veri:[5,3],through:[2,4],dynam:1,paramet:[2,1],style:[2,3,1,4],render:[5,4,3],img:3,brian:5,might:1,them:2,"return":1,thei:4,python:[0,2,5,3],handi:2,auth:2,framework:[5,1],jinja2:4,now:[5,2,4,1],choic:1,name:[0,2,3,1,4],edit:[0,2,4,3],config:[5,2,4,1],authent:[0,2,4,1],separ:4,token:2,rocki:2,truth:5,each:[4,1],whew:2,mean:1,newsapp:5,domain:3,individu:4,realli:2,"static":[0,2,4,5],our:4,"3a8080":2,out:[0,3,1],variabl:[2,4,1],ftp:3,publish:[0,1,2,3,4,5],s3config:3,rel:4,cc2502a:2,print:4,navig:4,workflow:[2,5,3],standard:0,ajax:[4,1],base:[0,5,3,1,4],dictionari:4,put:[2,1],my_filt:1,render_templ:3,script:1,static_url:4,keep:1,filter:1,turn:1,isn:1,think:3,first:2,directli:4,onc:3,system:[0,5],unlik:4,alreadi:2,done:2,wrapper:5,open:2,differ:[0,2,4,1],projectnam:[2,4,3],mamp:2,top:4,smoother:2,muckrak:0,construct:4,master:2,too:1,accept:1,white:3,store:[2,4,1],consol:[2,4],option:[2,1],namespac:4,tool:[0,5],copi:2,specifi:[2,3],part:2,grace:4,png:3,serv:4,keyid:3,target:3,provid:[4,1],lion:5,structur:[2,4],project:[0,2,3,1,4],matter:2,mkvirtualenv:5,friend:4,sensit:1,danc:2,beginn:3,seri:2,blueprint:1,modern:5,ani:[2,5,1],myproject:[4,1],sheet1:2,have:[0,1,2,3,4,5],need:[2,3,1],techniqu:2,lib:4,min:[4,3],gmailpassword:1,port:2,note:[5,3],also:1,exampl:[3,1,4],take:[4,1],which:[2,5,1],simplifi:3,sure:[2,5],unless:2,thi:[5,2,3,1,4],track:4,jst:3,most:[3,1],deploi:[0,2,3,1],pair:4,"class":4,don:[0,2,3],url:[4,1],doc:[5,2,3,1],biglongspreadsheetkey90xlk39102k4:2,drive:2,templatenam:4,awesom:[2,1],text:[4,1],freeform:4,bucketnam:3,find:[5,1],awesomeproject:2,layout:[0,4],tribapp:3,menu:2,configur:[0,1,2,3,4,5],should:[5,2,4,1],dict:1,local:[0,2,3],get:[2,4],account:[0,2,3,1],repo:[2,3],amazon:[0,5,3],report:0,requir:[2,4,5],bar:4,enabl:2,organ:2,contain:[4,1],davidead:[2,3],view:[2,4,3],user:[2,3],set:[5,2,3,1,4],see:[2,5,3],content:[4,1],sport:3,gmail:[2,1],jqueri:4,detect:4,noauth_local_webserv:2,kei:[2,3,1,4],expert:2,someth:[3,1],wikipedia:0,label:4,ad_path:1,state:1,won:2,between:[0,4],"import":[2,1],extend:4,screen:2,javascript:[0,2,4,1],cycl:2,steroid:3,fabfil:2,distinguish:0,come:4,addit:4,etc:1,redirect_uri:2,context:[4,1],navigationview:[4,3],client_secret:[0,2],browser:[2,5],com:[5,2,3,1,4],boyer:5,chicagotribun:4,load:[4,1],url_root:1,simpli:[3,1,4],author:1,header:[2,4],path:4,guid:[5,3],assum:3,canbeanyth:3,empti:[4,1],compon:3,app_context_processor:1,secret:[2,4,1],much:5,basic:[2,4,5],tini:2,life:1,fire:2,imag:4,convert:1,anywher:2,present:4,look:4,servic:2,"while":4,behavior:1,endblock:[4,1],readi:2,readm:[5,2,4,3],site:[0,5],jpg:3,tojson:1,sever:1,develop:2,welcom:[0,2],grant:2,receiv:2,make:[5,2,4,1],html:[0,2,3,1,4],document:2,oil:0,http:[5,2,4,3],screenshot:3,my_vari:1,moment:4,initi:2,app_template_filt:1,build:[0,5,4,1],off:2,whole:1,client:2,command:2,endfor:[4,1],filesystem:0,somebodi:2,ccc:2,latest:5,just:[3,1],googleapi:2,ir_black:3,collabor:2,momentj:4,hadiya:4,web:[2,5],jinja:4,easi:3,except:5,littl:2,add:[2,1],response_typ:2,input:2,save:4,app:[0,1,2,3,4,5],kick:2,futur:2,real:1,applic:[2,4,1],read:[0,5,3,1],big:1,know:2,password:[2,1],associ:2,backbon:4,insert:2,like:[2,3,1,4],success:2,google_auth:[4,1],manual:[0,2],server:[2,5],href:4,necessari:4,journalist:0,output:4,manag:4,dont_publish:1,some:[2,3,1,4],google_doc:1,refresh:3,biglongstringoflettersandnumb:1,librari:[2,4,5],virtualenv:5,total:1,exit:2,foo:4,birthrat:5,localhost:[5,2,4,3],mode:2,machin:2,peek:4,investig:0,run:[2,5,3],power:5,step:2,prerequisit:[0,2],"__name__":1,"super":4,about:0,column:[2,4],worksheet:[4,1],page:[5,3],fbrefresh:3,masterpiec:0,commit:2,disabl:[2,1],block:[4,1],ida:[0,3],googleusercont:2,own:5,regist:1,within:2,automat:4,dataset:1,been:2,strip:1,wrap:4,storag:3,your:[0,1,2,3,4,5],git:[2,4,5],log:[2,4],her:0,support:4,question:2,json:[0,2,3,1],custom:3,avail:1,start:[2,4,5],includ:[4,3],"var":[4,1],"function":4,link:4,client_id:2,oauth:2,renam:2,line:[2,1],"true":1,info:3,oauth2:2,"default":[2,4,1],checkout:2,bucket:[2,3],displai:[4,1],indefinit:2,highlight:2,clear:[2,4],featur:4,creat:[0,2,3,1,4],dure:2,"2flocalhost":2,doesn:[2,5],repres:[4,1],exist:2,cloudflar:4,file:[5,2,3,1,4],pip:5,improv:2,mybucket:3,check:3,probabl:[2,5],again:2,googl:[0,2,3,1,4],titl:[2,4],when:[3,1],detail:[2,5],virtual:5,other:[2,4],nav:[4,3],special:[2,1],branch:2,test:5,you:[5,2,3,1,4],"2fdrive":2,basketbal:3,requirej:4,directori:[5,2,3,1,4],newproject:2,time:2},objtypes:{},titles:["Welcome to Tarbell!","Reference","Create a Project","Publish a Project","Build a Project","Install Tarbell"],objnames:{},filenames:["index","reference","create","publish","build","install"]})PK hsC6^KK KK tarbell-0.8/build.html
Project layout, edit templates and manage Google spreadsheet, tweak CSS, and take a peek at the Javascript app.
Now that you’ve created a new project, let’s look at how Tarbell projects are constructed.
A Tarbell template project directory structure looks like this:
config.py: Configuration file. Required to detect the project.
secrets.py: Set GOOGLE_AUTH variable to configure authentication. Not tracked by Git.
- templates: The templates directory contains Jinja templates that will be published at /projectname/TEMPLATENAME.html.
- index.html: A basic template to start building with.
- static: The static directory contains static assets like images, CSS, and Javascript. They are published at /projectname/FILENAME.
- js/app.js: An skeleton Javascript application for your project that is automatically loaded by base template.
- css/style.css: An empty stylesheet for your project.
Static assets are simply served as-is, while templates are provided with context variables and rendered using Jinja.
Every file that ends in .html in projectname/templates will be published to projectname/TEMPLATENAME.html and can be previewed at http://localhost:5000/projectname/TEMPLATENAME.html.
Tarbell uses Jinja2 for templating and supports all Jinja2 features.
A basic template looks like:
{% extends '_base.html' %}
{% block css %}
{{ super() }} {# Load base styles #}
<link rel="stylesheet" type="text/css"
href="{{ static_url('MYPROJECT', '/css/style.css') }}" />
{% endblock css %}
{% block content %}
<h1>{{ title }}</h1>
<p class="credit">{{ credit }}</p>
{{ body|process_text }}
{% endblock content %}
The Tarbell template comes with a base template file that sets up some simple blocks and manages Javascript app loading.
The static_url(projectname, path) function constructs the path to an asset stored under projectname/static based on the project’s output URL.
The values worksheet must have “key” and “value” columns. These key-value pairs will be provided as global variables to templates. So if there’s a row with a key column value of “foo” and a value of “bar”, {{ foo }} in a template will print bar.
Other worksheets can hold freeform data, namespaced by the worksheet name. Unlike the values worksheet, data in these worksheets can be accessed by iterating through a list or, if a column named “key” is present, by reference to the value in that column. Some examples with a worksheet named updates should help make this clear.
A worksheet called “updates”
key | title | date | url |
---|---|---|---|
hadiya | Hadiya’s friends | 05-05-2013 | http://graphics.chicagotribune.com/hadiyas-friends |
grace | His Saving Grace | 02-14-2013 | http://graphics.chicagotribune.com/grace |
The worksheet will be passed to your context as an iterable list, with each column in the worksheet representing a separate item in the context dictionary. So in your template, the following code displays the contents of each row in your spreadsheet:
{% for row in updates %}
<p> <a href="{{ row.url }}">{{ row.title }}</a> </p>
{% endfor %}
If there’s a header named “key” that contains only unique, simple string values we can directly access individual rows in that worksheet:
<p> <a href="{{ updates.grace.url }}">{{ updates.grace.title }}</a> </p>
Every project comes with a barebones Javascript app in projectname/static/js/app.js.
The app uses RequireJS and provides Backbone, jQuery, and Underscore libraries by default.
Wrap your app code in a require(['dependency', ...], function(DepObj) { ... }) call to include necessary libraries and modules.
// Additional RequireJS configuration
require.config( {
paths: {
moment: '//cdnjs.cloudflare.com/ajax/libs/moment.js/2.0.0/moment.min',
},
} );
// Start our project's app
require([ 'jquery', 'base/views/NavigationView', 'moment' ],
function($, NavigationView, moment) {
console.log("Creating navigation view");
var nav = new NavigationView({
el: $('#header'),
title: { label: 'Tarbell Readme', url: '#top' },
}).render();
console.log("Demonstrating momentJS:");
console.log(new moment());
});
Configure Tarbell, set up a Flask Blueprint, special base project.
When your project was created, a config.py file was created in the project directory, which lets Tarbell find your project. This file can be empty, but also accepts several configuration options:
- GOOGLE_DOC: A dict of Google docs parameters to access a spreadsheet.
Takes key, account, and password parameters.
The default template stores account and password variables in a file called secrets.py in variable called GOOGLE_AUTH. Use secrets.py to keep your authentication information out of version control.
GOOGLE_DOC = { 'key': "BIGLONGSTRINGOFLETTERSANDNUMBERS", 'account': "some+account@gmail.com", 'password': "++GmailPassWord++", }
- DEFAULT_CONTEXT: Default context variables to make available to all project templates.
DEFAULT_CONTEXT = { 'ad_path': '', 'analytics_path': '', }
- DONT_PUBLISH: If True, this project will not be published to S3.
DONT_PUBLISH=TrueDefault: False
- URL_ROOT: Override the published URL to differ from the directory name.
URL_ROOT='totally-awesome-project'Default: None (publish using name of directory)
- CREATE_JSON: If False, do not publish JSON data. Useful if spreadsheets contain secrets or sensitive information, and so should not be public.
CREATE_JSON = FalseDefault: True
For advanced uses, you can turn your project into a Flask Blueprint in order to register template filters or dynamically set the template context.
from flask import Blueprint
blueprint = Blueprint('awesome_project', __name__)
# Register template filter
@blueprint.app_template_filter('my_filter')
def my_filter(text):
return text.strip()
@blueprint.app_context_processor
def context_processor():
"""
Add "my_variable" to context
"""
context = {
'my_variable': 'My variable would be more awesome in real life, like reading a file or API data.",
}
return context
Now you can reference {{ my_variable }} in your templates, or call your filter on a template variable {{ my_variable|my_filter }}.
If any project contains a URL_ROOT = '' configuration, that project will:
- Be available at the root URL (/index.html, /css/style.css, etc).
- Always be published when deploying.
By default, every project’s Google spreadsheet will be baked out to a JSON file representing each worksheet. For example, most projects will have a myproject/json/values.json that represents the contents of the “values” worksheet.
This means you can build pure Javascript apps using Tarbell in the framework of your choice. Just AJAX load or bootstrap the JSON data.
To disable this behavior, add a line to your config.py:
CREATE_JSON = False
If you disable this behavior and need data available to Javascript applications, simply bootstrap the dataset provided it isn’t too big. Here’s something you might put in myproject/index.html:
{% block scripts %}
<script type="text/javascript">
// Convert whole worksheet to JSON
var authors = {{ authors|tojson }}
// Filter a worksheet
var locations = [ {% for address in locations %}
{ state: '{{ address.state }}' },
{% endfor %} ];
// Now process or display 'authors' and 'locations' ...
</script>
{% endblock %}
Use fab deploy and fab project:<projectname> deploy to upload your project to Amazon S3. Customize the publishing process.
An Amazon S3 publishing workflow is included in the Tarbell template. To use it, you’ll need your Amazon S3 credentials.
Create a file called s3config.py in your Tarbell template directory.
S3CONFIG = {
'BUCKETNAME': {
'bucket': 'mybucket.domain.com',
'key': 'KEY',
'key_id': 'KEYID',
}
}
Amazon S3 is simply online file storage – think of it as FTP on steroids. Setting up an Amazon S3 account is easy. Just check out this beginners guide. If you want to use your S3 “bucket” as a website, read Amazon’s guide to S3 website hosting.
Once your Amazon S3 access credentials are configured, deploying all projects is very simple:
fab target:BUCKETNAME deploy
This will deploy to the bucket specified by BUCKETNAME in s3config.py.
To simplify deploying to the bucket named production, simply run:
fab deploy
When deploying you’ll see something like:
[localhost] local: python render_templates.py
Rendering templates.
Generating project 'base' in /Users/davideads/Repos/tarbell/out/
-- No Google doc configured for base.
Generating project 'readme' in /Users/davideads/Repos/tarbell/out/readme
-- Created JSON /Users/davideads/Repos/tarbell/out/readme/json/values.json
-- Created JSON /Users/davideads/Repos/tarbell/out/readme/json/LAST_UPDATED.json
-- Created JSON /Users/davideads/Repos/tarbell/out/readme/json/projects.json
-- Created page /Users/davideads/Repos/tarbell/out/readme/index.html
[localhost] local: python s3deploy.py
Deploying to tarbell.tribapps.com
Uploading css/style.css
Uploading js/app.js
Uploading js/templates/nav.jst
Uploading js/views/NavigationView.js
Uploading readme/index.html
Refreshing Facebook info for: http://tarbell.tribapps.com/readme/index.html?fbrefresh=CANBEANYTHING
Uploading readme/bootstrap/css/bootstrap.css
Uploading readme/bootstrap/css/bootstrap.min.css
Uploading readme/bootstrap/img/glyphicons-halflings-white.png
Uploading readme/bootstrap/img/glyphicons-halflings.png
Uploading readme/bootstrap/js/bootstrap.js
Uploading readme/bootstrap/js/bootstrap.min.js
Uploading readme/css/ir_black.css
Uploading readme/css/style.css
Uploading readme/img/google-screenshot.jpg
Uploading readme/img/html-edit-screenshot.jpg
Uploading readme/img/ida-tarbell.jpg
Uploading readme/img/s3-publish-screenshot.jpg
Uploading readme/js/app.js
Uploading readme/json/LAST_UPDATED.json
Uploading readme/json/projects.json
Uploading readme/json/values.json
To deploy a specific project, use the project:PROJECTNAME flag:
fab project:PROJECTNAME deploy
In the following example, we’ll publish a project called basketball using a bucket configuration named sports:
fab project:basketball target:sports deploy
Please note: The base template is always published – it is assumed most projects will use some base components.
Clone repository, install virtual environment, install requirements, configure your system for Amazon S3, and run a test server.
Tarbell is a Python library based on Flask which powers static sites. Truth be told, it doesn’t do much on its own except read a directory and render templates in any subdirectory it finds a config.py file. To see Tarbell in action, you should probably start with the Tarbell template, which sets up an Amazon S3 publishing workflow and basic framework for building modern web apps using Tarbell.
Make sure you have python (2.6+), git, pip, virtualenv and virtualenv-wrapper installed on your system.
git clone https://github.com/newsapps/tarbell
cd tarbell
mkvirtualenv tarbell
pip install -r requirements.txt
python runserver.py
Now visit http://localhost:5000/readme in your browser. You should see the latest version of this page.
For a very basic guide, see the Chicago Birthrates installation docs.
For more detailed, Mac-specific information, see Brian Boyer’s Lion dev environment notes.
The Tarbell template uses Python Flask and Google Spreadsheets to create simple, static sites that can be baked out to Amazon S3 or your local filesystem.
Tarbell is named after Ida Tarbell, a distinguished muckraking journalist whose 1904 The History of the Standard Oil Company is a masterpiece of investigative reporting. Read more about her on Wikipedia.
Get the client_secrets.json file if you don’t have it already. Use the fab newproject command to kick off a new project by copying a basic project structure and setting up a Google spreadsheet.
Tarbell uses the Google Drive API to create new spreadsheets, which requires going through a little OAuth2 song-and-dance. This is optional but highly recommended, in part because Tarbell will probably use this technique for all authentication and access in the future. If you want to skip this step and configure your spreadsheet manually, see Manually creating Google spreadsheets.
You ready? Let’s go.
In order to allow Tarbell to create new Google Spreadsheets, you’ll need to download a client_secrets.json file to access the Google Drive API. You can share this file with collaborators and within your organization, but do not share this file anywhere public.
Log in to the Google API Developer Console and create a new project:
Now click the “Services” tab and enable Google Drive API.
Click the “API Access” tab to create a client ID:
Add some project details. These don’t really matter:
This is the important screen. Select “installed app” and “other”:
Whew! Now you can download the client_secrets.json file:
Now put the file in the root directory of your Tarbell installation.
The first time you run fab newproject and answer yes to create a Google spreadsheet, your default browser will open and you will be prompted to grant your Tarbell client access to your API key.
The fab newproject command will prompt you if the client_secrets.json file doesn’t exist.
The first time you create a new project and spreadsheet, make sure you are not running any services on port 8080, such as MAMP. The Python Google API client library fires up a tiny little server on port 8080 to receive and store an access token during this cycle. Because the access token is stored, you won’t need to do again unless your token is revoked. You can restore any port 8080 services indefinitely.
Help us improve! We know this step is a little rocky. We’d like to make it smoother. If you are an OAuth or Google Drive API expert, we need your help. See #21 Improve OAuth workflow for newproject command and #22 Use Drive API in Tarbell library.
To create your first project, use the handy fab command:
fab newproject
You’ll be prompted with a series of questions. Here’s what you’ll see the first time you it with user input highlighted.
What is the directory name for the project? awesomeproject
What is your project's full title? Awesome project
Do you want a Google doc associated with this project? [Y/n]: y
Generating Google spreadsheet
What Google account should have access to this spreadsheet initially? (e.g. my.name@gmail.com) somebody@gmail.com
Authenticating your Google account to use Tarbell. If any services are running on
port 8080, disable them and run this command again.
Your browser has been opened to visit:
https://accounts.google.com/o/oauth2/auth?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.file&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&response_type=code&client_id=000000000000.apps.googleusercontent.com&access_type=offline
If your browser is on a different machine then exit and re-run this
application with the command-line parameter
--noauth_local_webserver
Authentication successful.
Success! View the spreadsheet at https://docs.google.com/spreadsheet/ccc?key=BIGLONGSPREADSHEETKEY90xlk39102k4
This spreadsheet is published in public on the web. To make it private
you'll need to configure the project's secrets.py file, disable
publishing using the 'Publish to the web' settings from the file menu,
and share the document with the account specified in secrets.py.
Created /Users/davideads/Repos/tarbell/awesomeproject/config.py
Created /Users/davideads/Repos/tarbell/awesomeproject/secrets.py
Created directory /Users/davideads/Repos/tarbell/awesomeproject/static/css
Created /Users/davideads/Repos/tarbell/awesomeproject/static/css/style.css
Created directory /Users/davideads/Repos/tarbell/awesomeproject/static/js
Created /Users/davideads/Repos/tarbell/awesomeproject/static/js/app.js
Created directory /Users/davideads/Repos/tarbell/awesomeproject/templates
Created /Users/davideads/Repos/tarbell/awesomeproject/templates/index.html
Would you like to create a new branch and initial commit for this project? [Y/n]: y
[localhost] local: git checkout master;
git checkout -b awesomeproject
M fabfile.py
M readme/docs/create.md
Already on 'master'
M fabfile.py
M readme/docs/create.md
Switched to a new branch 'awesomeproject'
[localhost] local: git add awesomeproject
[localhost] local: git commit -m "Started new project awesomeproject"
[awesomeproject cc2502a] Started new project awesomeproject
5 files changed, 212 insertions(+), 0 deletions(-)
create mode 100644 awesomeproject/config.py
create mode 100644 awesomeproject/secrets.py
create mode 100644 awesomeproject/static/css/style.css
create mode 100644 awesomeproject/static/js/app.js
create mode 100644 awesomeproject/templates/index.html
Welcome to Awesome project. Great work! What's next?
- Edit awesomeproject/config.py to set up template values and adjust project settings.
- Edit awesomeproject/secrets.py to configure Google spreadsheet authentication variables.
- Edit awesomeproject/templates/index.html to edit your default template.
- Edit awesomeproject/static/js/app.js to edit your default Javascript app.
- Run `python runserver.py` and view your project at http://localhost:5000/awesomeproject/
Run `fab deploy` and `fab project:projectname deploy` to deploy to S3 if you have a bucket configured.
Done.
To manually set up a Google spreadsheet for your project:
Create a new Google spreadsheet
Rename “Sheet1” to “values”
Add ‘key’ and ‘value’ column headers in the first row
Add the spreadsheet key in projectname/config.py
- Public access:
- Set the spreadsheet to ‘publish to the web’
- Private access:
- Grant access to a special user account (you’ll be storing password in the clear, so set up a new account for this)
- Add credentials to projectname/secrets.py