Udacity cs253 How to Build a Blog Notebook

How the Web Works

https://www.udacity.com/wiki/cs253/unit-1

Introduction to the Web

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/AkjMCbSvTto.mp4

World Wide Web

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/NBI9kXzMHS0.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/uPTMmyZB7tw.mp4

File Types

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/ND8jAv7WrmU.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/VngVBqQYxVg.mp4

Components of the Web

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/kzyfIiVZPJA.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/cVU7hYn-B8I.mp4

Best Browser

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/57kH7Yole2k.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/eQDNuWOxaJ0.mp4

HTML Basics

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/5Kjx-NOwcSc.mp4

Intro to HTML Tags

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/VsxbuJWcxqA.mp4

Bold Tag

<b>content</b>

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/irJ9o1Uv6U8.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/JWld9DM-La4.mp4

Italics

<em>content</em>

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/4H23hC78J_A.mp4
Instructions: Make the phrase ‘HTML is reasonably straightforward’ italic.

Note: the textbox should have default text in it for you to edit. In the meantime, it should look like this:

HTML is <b>reasonably straightforward</b>

Your job is to make entire phase italicized by using the <em> tag.

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/1079BoYQUD8.mp4

Missing End Tag

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/OWjh74s_uT4.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/pKouF71QK_c.mp4

<tag attr="value">content</tag>
<a href="www.reddit.com">derp</a>

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/-0S9lBFHeo0.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/IjdvSD1tX8U.mp4
Errata:
URLs need the protocol
The URL in the link should be “http://udacity.com“ and not “udacity.com”.

If the default text is missing
The textbox should have default text in it for you to edit. In the meantime, it should look like this:

This website is my favorite

Your job is to make the words my favorite a link to udacity.com.

Adding Images

<img src="url" alt="text">
https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/Le8i8TtDleU.mp4

Whitespace

<br>
<p>content</p>

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/dEtVii1eYYY.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/at-mlJ0KeMQ.mp4

Paragraph Tag

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/fSnKsMM6DRI.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/BH46s-hYLXg.mp4

Inline vs Block

inline: <b></b> <em></em> <img src="">
block: <p></p>

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/bOh9WjucNsA.mp4

Span and Div

inline:<span>text</span>
block: <div>text</div>

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/rv1Oy-EduCk.mp4
We now recommend using scratchpad.io instead of the HTML playground Steve refers to.

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/jCdjfORR7BI.mp4

Document Structure

<!DOCTYPE html>
<html>
<head>
    <title>Title</title>
</head>
<body>
<b>context</b>
</body>
</html>

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/VL7Wm0UzY6s.mp4

Introducing URLs

Uniform Resource Locator
For those of you wondering what an IP address is, wikipedia has this to say:

An Internet Protocol address (IP address) is a numerical label assigned to each device (e.g., computer, printer) participating in a computer network that uses the Internet Protocol for communication. An IP address serves two principal functions: host or network interface identification and location addressing. Its role has been characterized as follows: "A name indicates what we seek. An address indicates where it is. A route indicates how to get there."
The URL is the human readable locator which resolves to a numerical IP Address and represents, as Steve says, "the location of the physical machine which has the document we want to fetch."

An example IPv4 address looks like this: 172.16.254.1
https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/yKKGg6ihUCs.mp4

Correct URL

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/kUMasWPRKE4.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/4_nLjYoN8ks.mp4

Query Parameters

http://example.com/foo?p=1&q=neat
name=value

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/qv5XK91OhFo.mp4
https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/e7N_4uaoNeI.mp4

Fragments

http://www.example.com/foo#fragment
http://example.com/foo?p=1#fragment

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/xq95EZdiOQc.mp4

Port

http://localhost:8000/
port-default=80

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/3P7e6R9LsRY.mp4

The url got slightly cut off at the end. It should read:

http://example.com:80/toys?p=foo#blah

Note that urls are, in general, case-sensitive, as are most subsections of urls. Keep that in mind when you answer! The full url is
http://example.com:80/toys?p=foo#blah

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/8hiQyL6lcBs.mp4

Get

http://www.example.com/foo
request line: GET /foo HTTP/1.1

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/8QjYUp3w5U0.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/rByBs2dt4dg.mp4

Most Common Method

GET
POST

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/F9Fp-LtY7So.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/pJNxDTa5uP0.mp4

Making Requests

request line: GET /foo?p=1 HTTP/1.1
Headers:
    Name: value
Host: www.example.com
User-Agent: chrome v.17

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/5X7wcZuO5mU.mp4

User Agent Header

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/oJ6MBvzgPcQ.mp4

Valid Headers

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/RdZDK0121kI.mp4

Here is some information about headers that you might find useful.
https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/li-vh81yxKI.mp4

HTTP Responses

request:
    request-line:
        GET /foo HTTP/1.1
response:
    status-line:
        HTTP/1.1 200 Ok
status code:
200 Ok
302 Found
404 Not found
500 Server Error

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/I4kUB17pTno.mp4

Response Headers

telnet www.udacity.com 80
GET / HTTP/1.0
Host: www.udacity.com

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/Ie0ONOZzNlw.mp4

NOTE:

This example does not work properly at the moment, as http://www.udacity.com redirects to https://www.udacity.com. The former uses the protocol HTTP while the site now actually uses the protocol HTTPS. The extra “S” in HTTPS stands for “secure”, and you will hear more about it later.

Opening A Terminal Window
Mac
Method 1:
Open Finder, then go to Applications -> Utilities -> Terminal

Method 2:
Open Spotlight, type ‘Terminal’, and the correct program should be the top result.

Linux
How you open the terminal varies depending on the specific distro and desktop environment. For Ubuntu, this page has a good introduction to the terminal and how to open it.

Windows
Open the Start Menu, then go to All Programs -> Accessories -> Command Prompt

Running Telnet

Running telnet in Windows requires enabling it in “Windows Features” first. This page.aspx) has a good introduction to enabling the telnet client in Windows up to version 8. Windows 10 is similar but you can find “Windows Features” with the search box in the taskbar.

Telnet should already be installed on Mac and Linux machines, so you should be able to copy the video exactly.

Telnet Request

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/CIDBvFiccXE.mp4

Since the video was recorded, the location header has changed to http://iana.org

You’ll need to use

telnet iana.org 80 

and

GET /domains/example  HTTP/1.0 
Host: iana.org

instead of using domain example.com

Since the video was recorded, the location header has changed to http://example.iana.org GET /domains/example HTTP/1.0 Host: iana.org
https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/Ly95z-I1qmA.mp4

Web Applications

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/_E8qXBHI4cg.mp4

Dynamic Content

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/543bDFHQKTs.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/4MlMQ5RJ4cc.mp4

Problem Set 1 - Creating Your First Cite

Google App Engine

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/Sj_OmHLEdEA.mp4
Check out the next lesson, “Problem Set 1 Help” for help getting Google App Engine running.

In the current version of Google App Engine (1.9.1 - 2014-03-19), the command line argument to choose a port in dev_appserver.py is no longer “-p”. The argument is now “–port”.

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/PNmji8qNL0s.mp4
tutorial in the forum

tutorial

https://console.cloud.google.com/home/dashboard?project=ssq-udacity-cs253

set path
http://docs.python-guide.org/en/latest/starting/install/win/

Welcome to Cloud Shell! Type "help" to get started.
ssq6554@ssq-udacity-cs253:~$ TUTORIALDIR=~/src/ssq-udacity-cs253/

type: TUTORIALDIR=~/src/ssq-udacity-cs253/

python_gae_quickstart-2017-05-03-15-34
ssq6554@ssq-udacity-cs253:~$ git clone https://github.com/GoogleCloudPlatform/appengine-try-python-flask.git $TUTORIALDIR

type: git clone https://github.com/GoogleCloudPlatform/appengine-try-python-flask.git $TUTORIALDIR

Cloning into '/home/ssq6554/src/ssq-udacity-cs253/python_gae_quickstart-2017-05-03-15-34'...
remote: Counting objects: 386, done.
remote: Total 386 (delta 0), reused 0 (delta 0), pack-reused 386
Receiving objects: 100% (386/386), 776.84 KiB | 355.00 KiB/s, done.
Resolving deltas: 100% (53/53), done.
ssq6554@ssq-udacity-cs253:~$ cd $TUTORIALDIR

type: cd $TUTORIALDIR

ssq6554@ssq-udacity-cs253:~/src/ssq-udacity-cs253/python_gae_quickstart-2017-05-03-15-34$ git checkout gcloud

type: git checkout gcloud

Branch gcloud set up to track remote branch gcloud from origin.
Switched to a new branch 'gcloud'
ssq6554@ssq-udacity-cs253:~/src/ssq-udacity-cs253/python_gae_quickstart-2017-05-03-15-34$ dev_appserver.py $PWD

type: dev_appserver.py $PWD

INFO     2017-05-03 07:45:50,733 devappserver2.py:692] Skipping SDK update check.
WARNING  2017-05-03 07:45:50,973 simple_search_stub.py:1152] Could not read search indexes from /tmp/appengine.None.ssq6554/search_indexes
INFO     2017-05-03 07:45:50,977 api_server.py:272] Starting API server at: http://0.0.0.0:48288
INFO     2017-05-03 07:45:50,980 dispatcher.py:205] Starting module "default" running at: http://0.0.0.0:8080
INFO     2017-05-03 07:45:50,981 admin_server.py:116] Starting admin server at: http://0.0.0.0:8000
INFO     2017-05-03 07:46:22,190 module.py:813] default: "GET /?authuser=0 HTTP/1.0" 200 12
^CINFO     2017-05-03 07:46:39,143 shutdown.py:45] Shutting down.
INFO     2017-05-03 07:46:39,144 api_server.py:863] Applying all pending transactions and saving the datastore
INFO     2017-05-03 07:46:39,144 api_server.py:866] Saving search indexes
ssq6554@ssq-udacity-cs253:~/src/ssq-udacity-cs253/python_gae_quickstart-2017-05-03-15-34$ gcloud app deploy app.yaml --project ssq-udacity-cs253

type: gcloud app deploy app.yaml --project ssq-udacity-cs253

You are about to deploy the following services:
 - ssq-udacity-cs253/default/20170503t155355 (from [/home/ssq6554/src/ssq-udacity-cs253/python_gae_quickstart-2017-05-03-15-34/app.yaml])
     Deploying to URL: [https://ssq-udacity-cs253.appspot.com]

Do you want to continue (Y/n)?  y

type: y

Beginning deployment of service [default]...
Some files were skipped. Pass `--verbosity=info` to see which ones.
You may also view the gcloud log file, found at
remote: Counting objects: 386, done.
[/tmp/tmp.QsMJk5uBEu/logs/2017.05.03/15.53.52.611133.log].
╔════════════════════════════════════════════════════════════╗
╠═ Uploading 77 files to Google Cloud Storage               ═╣
╚════════════════════════════════════════════════════════════╝
File upload done.
Updating service [default]...done.                                                                                                                            
Deployed service [default] to [https://ssq-udacity-cs253.appspot.com]
You can stream logs from the command line by running:
  $ gcloud app logs tail -s default
To view your application in the web browser run:
  $ gcloud app browse
ssq6554@ssq-udacity-cs253:~/src/ssq-udacity-cs253/python_gae_quickstart-2017-05-03-15-34$

succeed in deploying

http://ssq-udacity-cs253.appspot.com/

(success)Try locally

type:

gcloud init
gcloud components list

Your current Cloud SDK version is: 153.0.0
The latest available version is: 153.0.0

+-------------------------------------------------------------------------------
------------------------------+
|                                                  Components
                              |
+---------------+------------------------------------------------------+--------
------------------+-----------+
|     Status    |                         Name                         |
    ID            |    Size   |
+---------------+------------------------------------------------------+--------
------------------+-----------+
| Not Installed | App Engine Go Extensions                             | app-eng
ine-go            |  48.4 MiB |
| Not Installed | Bigtable Command Line Tool                           | cbt
                  |   3.9 MiB |
| Not Installed | Cloud Datalab Command Line Tool                      | datalab
                  |   < 1 MiB |
| Not Installed | Cloud Datastore Emulator                             | cloud-d
atastore-emulator |  15.4 MiB |
| Not Installed | Cloud Datastore Emulator (Legacy)                    | gcd-emu
lator             |  38.1 MiB |
| Not Installed | Cloud Pub/Sub Emulator                               | pubsub-
emulator          |  21.0 MiB |
| Not Installed | Emulator Reverse Proxy                               | emulato
r-reverse-proxy   |  14.5 MiB |
| Not Installed | Google Container Registry's Docker credential helper | docker-
credential-gcr    |   3.3 MiB |
| Not Installed | gcloud Alpha Commands                                | alpha
                  |   < 1 MiB |
| Not Installed | gcloud Beta Commands                                 | beta
                  |   < 1 MiB |
| Not Installed | gcloud app Java Extensions                           | app-eng
ine-java          | 128.6 MiB |
| Not Installed | gcloud app PHP Extensions (Windows)                  | app-eng
ine-php-windows   |  19.1 MiB |
| Not Installed | gcloud app Python Extensions                         | app-eng
ine-python        |   6.1 MiB |
| Not Installed | kubectl                                              | kubectl
                  |  14.9 MiB |
| Installed     | BigQuery Command Line Tool                           | bq
                  |   < 1 MiB |
| Installed     | Cloud SDK Core Libraries                             | core
                  |   5.9 MiB |
| Installed     | Cloud Storage Command Line Tool                      | gsutil
                  |   2.9 MiB |
| Installed     | Default set of gcloud commands                       | gcloud
                  |           |
+---------------+------------------------------------------------------+--------
------------------+-----------+
To install or remove components at your current SDK version [153.0.0], run:
  $ gcloud components install COMPONENT_ID
  $ gcloud components remove COMPONENT_ID

To update your SDK installation to the latest version [153.0.0], run:
  $ gcloud components update

type:gcloud components install app-engine-python

Restarting command:
  $ gcloud components install app-engine-python

There appears a new cmd window

Your current Cloud SDK version is: 153.0.0
Installing components from version: 153.0.0

+--------------------------------------------------+
|       These components will be installed.        |
+------------------------------+---------+---------+
|             Name             | Version |   Size  |
+------------------------------+---------+---------+
| gcloud app Python Extensions |  1.9.52 | 6.1 MiB |
+------------------------------+---------+---------+

For the latest full release notes, please visit:
  https://cloud.google.com/sdk/release_notes

Do you want to continue (Y/n)?  

type: y

#============================================================#
#= Creating update staging area                             =#
#============================================================#
#= Installing: gcloud app Python Extensions                 =#
#============================================================#
#= Creating backup and activating new installation          =#
#============================================================#

Performing post processing steps...done.

Update done!

请按任意键继续. . .

open git bash
type: git clone https://github.com/GoogleCloudPlatform/python-docs-samples
type: cd G:/\Udacity/\cs253

Cloning into 'python-docs-samples'...
remote: Counting objects: 10835, done.
remote: Compressing objects: 100% (161/161), done.
remote: Total 10835 (delta 58), reused 1 (delta 1), pack-reused 10649
Receiving objects: 100% (10835/10835), 4.60 MiB | 190.00 KiB/s, done.
Resolving deltas: 100% (5742/5742), done.

type: cd python-docs-samples/\appengine/\standard/\hello_world

type: dev_appserver.py .
look in http://localhost:8080/

(failed)or

open cmd

Go to cloud.google.com
Login and create a project
Copy the project id and create a project in App Engine on your machine with same id
Install Google Cloud SDK
Open Google Cloud SDK shell
Type 'gcloud init '
It will show ur gmail id OR ask u to log in
Select the project you created in step 2
Type 'gcloud beta app create'
It will ask for region - choose the closest region
Hit Deploy button in App Engine OR Type 'gcloud app deploy ' in the shell

type: gcloud beta app create

You do not currently have this command group installed.  Using it
requires the installation of components: [beta]

Restarting command:
  $ gcloud components install beta

Installing component in a new window.

Please re-run this command when installation is complete.
    $ C:\Users\SSQ\AppData\Local\Google\Cloud SDK\google-cloud-sdk\bin\..\lib\gc
loud.py beta app create

there opens a new window

Your current Cloud SDK version is: 153.0.0
Installing components from version: 153.0.0

+---------------------------------------------+
|     These components will be installed.     |
+----------------------+------------+---------+
|         Name         |  Version   |   Size  |
+----------------------+------------+---------+
| gcloud Beta Commands | 2017.03.24 | < 1 MiB |
+----------------------+------------+---------+

For the latest full release notes, please visit:
  https://cloud.google.com/sdk/release_notes

Do you want to continue (Y/n)?  y

#============================================================#
#= Creating update staging area                             =#
#============================================================#
#= Installing: gcloud Beta Commands                         =#
#============================================================#
#= Creating backup and activating new installation          =#
#============================================================#

Performing post processing steps...done.

Update done!

请按任意键继续. . .

type: gcloud beta app create

ERROR: (gcloud.beta.app.create) The project [ssq-udacity-helloworld] already con
tains an App Engine application in region [us-central].  You can deploy your app
lication using `gcloud app deploy`.

type: cd G:\Udacity\cs253\helloworld g:
type: gcloud app deploy

ERROR: gcloud crashed (UnicodeEncodeError): 'ascii' codec can't encode character
 u'\xad' in position 22: ordinal not in range(128)

If you would like to report this issue, please run the following command:
  gcloud feedback

To check gcloud for common problems, please run the following command:
  gcloud info --run-diagnostics

failed
type:

C:\Users\SSQ>python "C:\Users\SSQ\AppData\Local\Google\Cloud SDK\google-cloud-sdk\bin\dev_appserver.py" G:\Udacity\cs253\python-docs-samples\appengine\standard\hello_world\app.yaml

success

(Fail)try locally again

open Google Cloud SDK Shell
type:

python "C:\Users\SSQ\AppData\Local\Google\Cloud SDK\google-cloud-sdk\bin\dev_appserver.py" G:\Udacity\cs253\helloworld\app.yaml

it appears:

Updates are available for some Cloud SDK components.  To install them,
please run:
  $ gcloud components update

Traceback (most recent call last):
  File "C:\Users\SSQ\AppData\Local\Google\Cloud SDK\google-cloud-sdk\platform\go
ogle_appengine\dev_appserver.py", line 103, in <module>
    _run_file(__file__, globals())
  File "C:\Users\SSQ\AppData\Local\Google\Cloud SDK\google-cloud-sdk\platform\go
ogle_appengine\dev_appserver.py", line 97, in _run_file
    execfile(_PATHS.script_file(script_name), globals_)
  File "C:\Users\SSQ\AppData\Local\Google\Cloud SDK\google-cloud-sdk\platform\go
ogle_appengine\google\appengine\tools\devappserver2\devappserver2.py", line 899,
 in <module>
    main()
  File "C:\Users\SSQ\AppData\Local\Google\Cloud SDK\google-cloud-sdk\platform\go
ogle_appengine\google\appengine\tools\devappserver2\devappserver2.py", line 895,
 in main
    dev_server.stop()
  File "C:\Users\SSQ\AppData\Local\Google\Cloud SDK\google-cloud-sdk\platform\go
ogle_appengine\google\appengine\tools\devappserver2\devappserver2.py", line 775,
 in stop
    metrics.GetMetricsLogger().Stop()
  File "C:\Users\SSQ\AppData\Local\Google\Cloud SDK\google-cloud-sdk\platform\go
ogle_appengine\google\appengine\tools\devappserver2\metrics.py", line 119, in St
op
    total_run_time = int((Now() - self._start_time).total_seconds())
TypeError: unsupported operand type(s) for -: 'datetime.datetime' and 'NoneType'

type: gcloud components update
there’s a new window:

Your current Cloud SDK version is: 153.0.0
You will be upgraded to version: 154.0.1

+-------------------------------------------------+
|        These components will be updated.        |
+--------------------------+------------+---------+
|           Name           |  Version   |   Size  |
+--------------------------+------------+---------+
| Cloud SDK Core Libraries | 2017.05.04 | 6.0 MiB |
| gcloud cli dependencies  | 2017.05.01 | 1.6 MiB |
+--------------------------+------------+---------+

The following release notes are new in this upgrade.
Please read carefully for information about new features, breaking changes,
and bugs fixed.  The latest full release notes can be viewed at:
  https://cloud.google.com/sdk/release_notes

154.0.1 (2017-05-04)
  Cloud SDK
      o Fixed issue in for gcloud init command. See
        https://issuetracker.google.com/37968909.

154.0.0 (2017-05-03)
  Cloud SDK
      o Added support for project creation during the gcloud init flow.

  Google Cloud Logging
      o BUG FIX: gcloud beta logging sinks update would remove any start time
        or end time from a sink

      o gcloud beta logging sinks describe now reports values of start_time,
        end_time and include_children

      o The --include-children flag is now available for gcloud beta logging
        sinks create to create sinks that apply to an organization or folder
        and also to all of its child projects and folders.

  Google Compute Engine
      o Workaround problems with alpha and beta versions of compute ssh
        command fail an attempt to use clouduseraccounts APIs.

  Google Container Engine
      o Promote --cluster-version from beta to GA in gcloud container
        clusters create.

      o '--no-source' flag for 'gcloud container builds submit' allows builds
        with no source input.

  Google Cloud ML Engine
      o Added --config parameter to gcloud ml-engine versions create; this
        parameter allows specifying scaling settings for a version.

  Google Cloud Speech
      o The gcloud ml speech commands to recognize spoken words in recorded
        speech using the Cloud Speech API are now available in beta. Please run
        gcloud beta ml speech --help or visit
        https://cloud.google.com/speech/docs/ to learn more.

  Google App Engine
      o gcloud beta app deploy now attempts to use the Service Management API
        to enable the Appengine Flexible Environment API for Flexible
        deployments, if needed. Before deploying a Flexible app, please ensure
        that the Flexible Environment API is enabled on the app's project.

      o The new Node.js Runtime Builder pipeline will now be used to deploy
        apps when using gcloud beta app deploy.

  Google Cloud SQL
      o Promote gcloud sql operations to GA. The beta surface still remains
        and is identical.

  Google Cloud Source Repositories
      o Add a source repos describe command to describe a repository to the
        beta track.

Do you want to continue (Y/n)?

type: y

#============================================================#
#= Creating update staging area                             =#
#============================================================#
#= Uninstalling: Cloud SDK Core Libraries                   =#
#============================================================#
#= Uninstalling: gcloud cli dependencies                    =#
#============================================================#
#= Installing: Cloud SDK Core Libraries                     =#
#============================================================#
#= Installing: gcloud cli dependencies                      =#
#============================================================#
#= Creating backup and activating new installation          =#
#============================================================#

Performing post processing steps...done.

Update done!

To revert your SDK to the previously installed version, you may run:
  $ gcloud components update --version 153.0.0

请按任意键继续. . .

type: ``

Traceback (most recent call last):
  File "C:\Users\SSQ\AppData\Local\Google\Cloud SDK\google-cloud-sdk\platform\go
ogle_appengine\dev_appserver.py", line 103, in <module>
    _run_file(__file__, globals())
  File "C:\Users\SSQ\AppData\Local\Google\Cloud SDK\google-cloud-sdk\platform\go
ogle_appengine\dev_appserver.py", line 97, in _run_file
    execfile(_PATHS.script_file(script_name), globals_)
  File "C:\Users\SSQ\AppData\Local\Google\Cloud SDK\google-cloud-sdk\platform\go
ogle_appengine\google\appengine\tools\devappserver2\devappserver2.py", line 899,
 in <module>
    main()
  File "C:\Users\SSQ\AppData\Local\Google\Cloud SDK\google-cloud-sdk\platform\go
ogle_appengine\google\appengine\tools\devappserver2\devappserver2.py", line 895,
 in main
    dev_server.stop()
  File "C:\Users\SSQ\AppData\Local\Google\Cloud SDK\google-cloud-sdk\platform\go
ogle_appengine\google\appengine\tools\devappserver2\devappserver2.py", line 775,
 in stop
    metrics.GetMetricsLogger().Stop()
  File "C:\Users\SSQ\AppData\Local\Google\Cloud SDK\google-cloud-sdk\platform\go
ogle_appengine\google\appengine\tools\devappserver2\metrics.py", line 119, in St
op
    total_run_time = int((Now() - self._start_time).total_seconds())
TypeError: unsupported operand type(s) for -: 'datetime.datetime' and 'NoneType'

Deploy your app to the cloud

cd to hello_world dir and type gcloud app deploy

G:\Udacity\cs253\python-docs-samples\appengine\standard\hello_world>gcloud app deploy

You are about to deploy the following services:
 - ssq-udacity-cs253/default/20170503t210424 (from [G:\Udacity\cs253\python-docs
-samples\appengine\standard\hello_world\app.yaml])
     Deploying to URL: [https://ssq-udacity-cs253.appspot.com]

Do you want to continue (Y/n)?  y

type y

Beginning deployment of service [default]...
Some files were skipped. Pass `--verbosity=info` to see which ones.
You may also view the gcloud log file, found at
[C:\Users\SSQ\AppData\Roaming\gcloud\logs\2017.05.03\21.04.21.920000.log].
#============================================================#
#= Uploading 0 files to Google Cloud Storage                =#
#============================================================#
File upload done.
Updating service [default]...done.
Deployed service [default] to [https://ssq-udacity-cs253.appspot.com]

You can stream logs from the command line by running:
  $ gcloud app logs tail -s default

To view your application in the web browser run:
  $ gcloud app browse

type gcloud app browse

G:\Udacity\cs253\python-docs-samples\appengine\standard\hello_world>gcloud app browse
Opening [https://ssq-udacity-cs253.appspot.com] in a new tab in your default bro
wser.

Problem Set 1 Help

Intro

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/IFYmvf_RNT0.mp4

Install Google App Engine

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/euox_iFW2eM.mp4

Install Google App Engine

Make sure you are downloading Python 2 rather than Python 3, as this is what Google App Engine uses!

Changes to Google App Engine

The Google App Engine system (now part of Google Cloud) has changed a lot since this course was created. You will need to create an app with a new, unique name using the Developer Console before you can deploy it. For more information, take a look at these guides written by Udacity mentor Steven Wooding: (Windows), (Mac and Linux)

Installing Python on Linux

If you’re on a Mac or Linux machine, open a terminal and type ‘python -v’ at the prompt. If it returns some information about Python, then you already have Python installed! If not, then Mac users can follow the instructions in the video, and Linux users can use their package managers instead.

For Ubuntu or Debian, type ‘sudo apt-get install python’ into your terminal, then your password. For Fedora, type ‘sudo yum install python’ into your terminal, then your password. For other Linux distros, their should be documentation available for your specific package manager.

Running Google App Engine on Mac OS

Unfortunately Google no longer supports the GoogleAppengineLauncher program that Steve demonstrates in this video. You follow use the instructions below for Linux, or you can download the deprecated GoogleAppengineLauncher installer from the “Supporting Materials” list below. Warning: Use the GoogleAppengineLauncher program at your own peril! As Google no longer supports the tool it may stop working in the future. The gcloud command-line program is the currently supported tool.

Running Google App Engine on Linux

To run the Development Web Server locally, run:

dev_appserver.py myapp

Where myapp is the name you want your app to have.

To upload your code to Google App Engine, run:

appcfg.py update helloworld/

Where helloworld/ is the directory you’re running your web app from.

Further help is available here and here
Have questions? Head to the forums for discussion with the Udacity Community.

Supporting Materials
Windows Installation Guide for App Engine.pdf
GoogleAppEngineLauncher-1.9.40-OSX
https://discussions.udacity.com/t/problem-set-1-seems-to-be-nothing-like-help-video-shows/215184/3

Office Hours 1

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/QKTIOnISsCw.mp4

Forms and Input

https://www.udacity.com/wiki/cs253/unit-2

Introduction

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/3qgaev6_ZkY.mp4

Forms




https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/OnptThLQb_k.mp4

User Input

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/qNdg3ZKoKnA.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/PmF0C6dWzFk.mp4

Naming Input

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/IOkzztrmxbg.mp4
how to implement play.html:
https://discussions.udacity.com/t/unit2-this-is-fustrating/68505/2

Entering Input

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/JDwulMznybc.mp4

Try the HTML code

<form>
    <input name="q">
</form>

Note that if you chose the text disappears in addition to the the URL changes with my text, that you are also correct. However, we’re focused on the latter, and arguably more interesting, of these two events. But, you may always re-submit your answer to any quiz.
https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/vUHabH7bsTc.mp4

Submitting Input

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/easPpLBGf2w.mp4

<form>
    <input name="q">
    <input type="submit">
</form>


https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/GMNVeltn0ms.mp4

The Action Attribute

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/UR-I9lkV3No.mp4

<form action="http://www.google.com/search">
    <input name="q">
    <input type="submit">
</form>

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/7YawG07y9lg.mp4

URL Encoding

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/Z3udiqgW1VA.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/lSjOr6_LaMs.mp4

Hello Webapp World

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/t9qqgCvHxgs.mp4

Content Type

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/a0k61hlrO9M.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/TGHZjKuxTB0.mp4

More Handlers

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/9624RoIt2pk.mp4

GET /testform?q=hello+world%21 HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8
Content-Type: ; charset="utf-8"
Cookie: _xsrf=2|69d62867|9814fd50905531e52e958841989ec6fb|1491708993; username-localhost-8890="2|1:0|10:1491841902|23:username-localhost-8890|44:NzI4YzlkMzc5MzIyNGQ5YTgxMWMzMDAyZDZiY2M4NTY=|69e8bf9e2ec4a47c684886256bda319f88bbbbe1cc4bf5c9193aa52c9449bab1"; username-localhost-8891="2|1:0|10:1491842087|23:username-localhost-8891|44:YThkM2ViMzc0NmJjNDVhNGE4YWI4OTgwZGE5M2RlYzk=|cd0850025b097f89ae64b4bda7911166954a2384ecd7eb8a17991270ad4111a4"; username-localhost-8889="2|1:0|10:1492581579|23:username-localhost-8889|44:NGM1MDZlMTUzNWE1NGUzNmFkYTNhMzRiMjdmOGYyNWY=|a15a04a3925f6c3954789ffbdb5b01f5bda3a0c4e9e47420ac1564c5302aaf9d"; username-localhost-8888="2|1:0|10:1493640422|23:username-localhost-8888|44:NjYzZDYzYThhNmQwNDZiODk2ZTVlZDU0YjkxOTI5MWM=|fb58980d83c777e3d64786ba156f12ab1834a9c404151d3d5dacb943ca4e0616"; Hm_lvt_3c8ad2ecdd2387b44044b1d7cd3536a9=1492997775,1493349600,1493631556,1493712288; _ga=GA1.1.1682530332.1487774100
Host: localhost:8080
Referer: http://localhost:8080/
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36
X-Appengine-Country: ZZ

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/6BpCLwYGwBA.mp4

The Method Attribute

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/eDotptZ1Nyo.mp4

405 Method Not Allowed

The method POST is not allowed for this resource. 

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/BOnkFj9uMkg.mp4

http://localhost:8080/testform
hello world!

Methods and Parameters

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/E_OiAN5VKOM.mp4

import webapp2

form="""
<form method="post" action="/testform">
    <input name="q">
    <input type="submit">
</form>
"""

class MainPage(webapp2.RequestHandler):
    def get(self):
        #self.response.headers['Content-Type'] = 'text/plain'
        self.response.write(form)

class TestHandler(webapp2.RequestHandler):
    def post(self):
        #q=self.request.get("q")
        #self.response.out.write(q)

        self.response.headers['Content-Type'] = 'text/plain'
        self.response.out.write(self.request)

app = webapp2.WSGIApplication([
    ('/', MainPage),
    ('/testform',TestHandler)
], debug=True)


POST /testform HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8
Cache-Control: max-age=0
Content-Length: 16
Content-Type: application/x-www-form-urlencoded; charset="utf-8"
Content_Length: 16
Content_Type: application/x-www-form-urlencoded
Cookie: _xsrf=2|69d62867|9814fd50905531e52e958841989ec6fb|1491708993; username-localhost-8890="2|1:0|10:1491841902|23:username-localhost-8890|44:NzI4YzlkMzc5MzIyNGQ5YTgxMWMzMDAyZDZiY2M4NTY=|69e8bf9e2ec4a47c684886256bda319f88bbbbe1cc4bf5c9193aa52c9449bab1"; username-localhost-8891="2|1:0|10:1491842087|23:username-localhost-8891|44:YThkM2ViMzc0NmJjNDVhNGE4YWI4OTgwZGE5M2RlYzk=|cd0850025b097f89ae64b4bda7911166954a2384ecd7eb8a17991270ad4111a4"; username-localhost-8889="2|1:0|10:1492581579|23:username-localhost-8889|44:NGM1MDZlMTUzNWE1NGUzNmFkYTNhMzRiMjdmOGYyNWY=|a15a04a3925f6c3954789ffbdb5b01f5bda3a0c4e9e47420ac1564c5302aaf9d"; username-localhost-8888="2|1:0|10:1493640422|23:username-localhost-8888|44:NjYzZDYzYThhNmQwNDZiODk2ZTVlZDU0YjkxOTI5MWM=|fb58980d83c777e3d64786ba156f12ab1834a9c404151d3d5dacb943ca4e0616"; Hm_lvt_3c8ad2ecdd2387b44044b1d7cd3536a9=1492997775,1493349600,1493631556,1493712288; _ga=GA1.1.1682530332.1487774100
Host: localhost:8080
Origin: http://localhost:8080
Referer: http://localhost:8080/
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36
X-Appengine-Country: ZZ

q=hello+world%21

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/9Hj83VRhOQY.mp4

Differences Between Get and Post

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/UObINRj2EGY.mp4

Problems with Get

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/cIliEo0zOwg.mp4

When to Use Get and Post

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/CprytP12okM.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/KYPi9loZE-M.mp4

Passwords

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/xS71dGcER_s.mp4

<form>
    <input type="password" name="q">
    <input type="submit">
</form>

file:///G:/Udacity/cs253/L5%20Forms%20and%20Input/play.html?q=hello

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/oWvmNCuI47k.mp4

Checkboxes

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/bFK7ZIwnVik.mp4

<form>
    <input type="checkbox" name="q">
    <input type="submit">
</form>

file:///G:/Udacity/cs253/L5%20Forms%20and%20Input/play.html?

Multiple Checkboxes

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/Td_6JT-1MQ0.mp4

<form>
    <input type="checkbox" name="q">
    <input type="checkbox" name="r">
    <input type="checkbox" name="s">
    <br>
    <input type="submit">
</form>

file:///G:/Udacity/cs253/L5%20Forms%20and%20Input/play.html?q=on&r=on
https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/HEACkANsj9o.mp4

Radio Buttons

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/di_FzsEzyQk.mp4

<form>
    <input type="radio" name="q">
    <input type="radio" name="r">
    <input type="radio" name="s">
    <br>
    <input type="submit">
</form>

file:///G:/Udacity/cs253/L5%20Forms%20and%20Input/play.html?q=on&r=on

Grouping Radio Buttons

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/QKxqWDx2bcs.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/5GqK_VmlrAY.mp4

Radio Button Values

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/xPTL73OT5IY.mp4

<form>
    <input type="radio" name="q">
    <input type="radio" name="q">
    <input type="radio" name="q">
    <br>
    <input type="submit">
</form>


file:///G:/Udacity/cs253/L5%20Forms%20and%20Input/play.html?q=two
https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/hTDenQDEvqU.mp4

Label Elements

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/XnBMnDGQqtw.mp4

<form>
    <label>
        One
        <input type="radio" name="q" value="one">
    </label>
    <label>
        Two
        <input type="radio" name="q" value="two">
    </label>
    <label>
        Three
        <input type="radio" name="q" value="three">
    </label>
    <br>
    <input type="submit">
</form>

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/gVtTvYfc5NA.mp4

<form>
    <select name="q">
        <option>One</option>
        <option>Two</option>
        <option>Three</option>
    </select>
    <br>
    <input type="submit">
</form>

file:///G:/Udacity/cs253/L5%20Forms%20and%20Input/play.html?q=Two

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/joUhCZw_zG0.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/q2jmRGrAixc.mp4

The Number One

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/mRTBZNTmimA.mp4

<form>
    <select name="q">
        <option value="1">the number One</option>
        <option>Two</option>
        <option>Three</option>
    </select>
    <br>
    <input type="submit">
</form>

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/zCBUF8oDJPE.mp4

Validation

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/uC8ny0rTzIE.mp4

What Is Your Birthday?

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/Gx16pZ7crqU.mp4

import webapp2

form="""
<form method="post">
    What's your birthday?
    <br>
    <label>
        Month
        <input type="text">
    </label>
    <label>
        Day
        <input type="text">
    </label>
    <label>
        Year
        <input type="text">
    </label>
    <br>
    <br>
    <input type="submit">
</form>
"""

class MainPage(webapp2.RequestHandler):
    def get(self):
        #self.response.headers['Content-Type'] = 'text/plain'
        self.response.write(form)

app = webapp2.WSGIApplication([
    ('/', MainPage)
], debug=True)

405 Method Not Allowed

The method POST is not allowed for this resource. 

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/psynonn163k.mp4

Handling Posts

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/NyIz4ht6NGI.mp4

import webapp2

form="""
<form method="post">
    What's your birthday?
    <br>
    <label>
        Month
        <input type="text">
    </label>
    <label>
        Day
        <input type="text">
    </label>
    <label>
        Year
        <input type="text">
    </label>
    <br>
    <br>
    <input type="submit">
</form>
"""

class MainPage(webapp2.RequestHandler):
    def get(self):
        #self.response.headers['Content-Type'] = 'text/plain'
        self.response.out.write(form)
    def post(self):
        self.response.out.write("Thanks! That's a totally valid day!")

app = webapp2.WSGIApplication([
    ('/', MainPage)
], debug=True)

Handling Bad Data

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/fcrTA3_iHLY.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/u7vPsxvUNMA.mp4

Valid Month

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/mOAcUVFqIO0.mp4

Hint: You may want to look into the string.capitalize() function

In this answer video, Steve is using list comprehensions to create the dictionary of month abbreviations. If we were to translate this code: month_abbvs = dict((m[:3].lower(),m) for m in months) it would be: month_abbvs = {} for m in months: month_abbvs[m[:3].lower()] = m You can read more about list comprehensions here

# -----------
# User Instructions
# 
# Modify the valid_month() function to verify 
# whether the data a user enters is a valid 
# month. If the passed in parameter 'month' 
# is not a valid month, return None. 
# If 'month' is a valid month, then return 
# the name of the month with the first letter 
# capitalized.
#

months = ['January',
          'February',
          'March',
          'April',
          'May',
          'June',
          'July',
          'August',
          'September',
          'October',
          'November',
          'December']

def valid_month(month):


# print valid_month("january") 
# => "January"    
# print valid_month("January") 
# => "January"
# print valid_month("foo")
# => None
# print valid_month("")
# => None

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/a2sLiEgBl9k.mp4

month_abbvs = dict((m[:3].lower(),m) for m in months)
def valid_month(month):
    if month:
        short_month=month[:3].lower()
        return month_abbvs.get(short_month)

Valid Day

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/jj44KNeNK3A.mp4

# -----------
# User Instructions
# 
# Modify the valid_day() function to verify 
# whether the string a user enters is a valid 
# day. The valid_day() function takes as 
# input a String, and returns either a valid 
# Int or None. If the passed in String is 
# not a valid day, return None. 
# If it is a valid day, then return 
# the day as an Int, not a String. Don't 
# worry about months of different length. 
# Assume a day is valid if it is a number 
# between 1 and 31.
# Be careful, the input can be any string 
# at all, you don't have any guarantees 
# that the user will input a sensible 
# day.
#
# Hint: The string function isdigit() might be helpful.

def valid_day(day):


# print valid_day('0') 
# => None    
# print valid_day('1') 
# => 1
# print valid_day('15') 
# => 15
# print valid_day('500') 
# => None

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/6CdFM4grsXc.mp4

def valid_day(day):
    if day and day.isdigit():
        day=int(day)
        if day>0 and day<=31:
            return day

Valid Year

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/g1f2nOw7a9M.mp4

# -----------
# User Instructions
# 
# Modify the valid_year() function to verify 
# whether the string a user enters is a valid 
# year. If the passed in parameter 'year' 
# is not a valid year, return None. 
# If 'year' is a valid year, then return 
# the year as a number. Assume a year 
# is valid if it is a number between 1900 and 
# 2020.
#

def valid_year(year):


#print valid_year('0') 
#=> None    
#print valid_year('-11') 
#=> None
#print valid_year('1950') 
#=> 1950
#print valid_year('2000') 
#=> 2000

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/YHEqWp6R0IA.mp4

def valid_year(year):
    if year and year.isdigit():
        year=int(year)
        if year>1900 and year<=2020:
            return year

Checking Validation

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/WbBDizcryiA.mp4

Responding Based On Verification

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/3EgN3NxgH-Y.mp4

import webapp2

form="""
<form method="post">
    What's your birthday?
    <br>
    <label>
        Month
        <input type="text" name="month">
    </label>
    <label>
        Day
        <input type="text" name="day">
    </label>
    <label>
        Year
        <input type="text" name="year">
    </label>
    <br>
    <br>
    <input type="submit">
</form>
"""


def valid_day(day):
    if day and day.isdigit():
        day=int(day)
        if day>0 and day<=31:
            return day


months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August',
                        'September', 'October', 'November', 'December']
month_abbvs = dict((m[:3].lower(),m) for m in months)
def valid_month(month):
    if month:
        short_month=month[:3].lower()
        return month_abbvs.get(short_month)


def valid_year(year):
        if(year and year.isdigit()):
                year = int(year)
        if(year < 2020 and year > 1880):
                return year


class MainPage(webapp2.RequestHandler):

    def get(self):
        #self.response.headers['Content-Type'] = 'text/plain'
        self.response.out.write(form)
    def post(self):
        user_month=valid_month(self.request.get('month'))
        user_day=valid_day(self.request.get('day'))
        user_year=valid_year(self.request.get('year'))

        if not (user_month and user_day and user_year):
            #self.response.out.write(user_month)
            self.response.out.write(form)
        else:
            self.response.out.write("Thanks! That's a totally valid day!")

app = webapp2.WSGIApplication([
    ('/', MainPage)
], debug=True)

String Substitution

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/DYncK4Tuthc.mp4

# User Instructions
# 
# Write a function 'sub1' that, given a 
# string, embeds that string in 
# the string: 
# "I think X is a perfectly normal thing to do in public."
# where X is replaced by the given 
# string.
# The function should return the new string.

given_string = "I think %s is a perfectly normal thing to do in public."
def sub1(s):


#print sub1("running") 
# => "I think running is a perfectly normal thing to do in public."    
#print sub1("sleeping") 
# => "I think sleeping is a perfectly normal thing to do in public."

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/0h0RYI_MGtU.mp4

def sub1(s):
    return given_string % s

Substituting Multiple Strings

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/ahNxN_Ly5sE.mp4

# User Instructions
# 
# Write a function 'sub2' that, given two 
# strings, embeds those strings in the string: 
# "I think X and Y are perfectly normal things to do in public."
# where X and Y are replaced by the given 
# strings.
# The function should return the new string.

given_string2 = "I think %s and %s are perfectly normal things to do in public."
def sub2(s1, s2):


# print sub2("running", "sleeping") 
# => "I think running and sleeping are perfectly normal things to do in public."
# print sub2("sleeping", "running") 
# => "I think sleeping and running are perfectly normal things to do in public."

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/K7mx3o3-X3Y.mp4

def sub2(s1, s2):
    return given_string2 %(s1,s2)

Advanced String Substitution

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/4OXzeuhwM-E.mp4

# User Instructions
# 
# Write a function 'sub_m' that takes a 
# name and a nickname, and returns a 
# string of the following format: 
# "I'm NICKNAME. My real name is NAME, but my friends call me NICKNAME."
# 

given_string2 = "I'm %(nickname)s. My real name is %(name)s, but my friends call me %(nickname)s."
def sub_m(name, nickname):



#print sub_m("Mike", "Goose") 
# => "I'm Goose. My real name is Mike, but my friends call me Goose."

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/3iHZY-xJJUY.mp4

def sub_m(name, nickname):
    return given_string2 % {"nickname":nickname,"name":name}

Substituting into Our Form

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/trxe2U-OplI.mp4

import webapp2

form="""
<form method="post">
    What's your birthday?
    <br>
    <label>
        Month
        <input type="text" name="month">
    </label>
    <label>
        Day
        <input type="text" name="day">
    </label>
    <label>
        Year
        <input type="text" name="year">
    </label>
    <div style="color: red">%(error)s</div>
    <br>
    <br>
    <input type="submit">
</form>
"""


def valid_day(day):
    if day and day.isdigit():
        day=int(day)
        if day>0 and day<=31:
            return day


months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August',
                        'September', 'October', 'November', 'December']
month_abbvs = dict((m[:3].lower(),m) for m in months)
def valid_month(month):
    if month:
        short_month=month[:3].lower()
        return month_abbvs.get(short_month)


def valid_year(year):
        if(year and year.isdigit()):
                year = int(year)
        if(year < 2020 and year > 1880):
                return year

class MainPage(webapp2.RequestHandler):
    def write_form(self, error=""):
        self.response.out.write(form %{"error": error})    

    def get(self):
        #self.response.headers['Content-Type'] = 'text/plain'
        #self.response.out.write(form)
        self.write_form()

    def post(self):
        user_month=valid_month(self.request.get('month'))
        user_day=valid_day(self.request.get('day'))
        user_year=valid_year(self.request.get('year'))

        if not (user_month and user_day and user_year):
            #self.response.out.write(user_month)
            #self.response.out.write(form)
            self.write_form("That doesn't look valid to me, friend.")
        else:
            self.response.out.write("Thanks! That's a totally valid day!")

app = webapp2.WSGIApplication([
    ('/', MainPage)
], debug=True)

Preserving User Input

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/BpNhr-xc0Nw.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/lwHWqkMijss.mp4

Problems with HTML Input

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/iWX-XylQsH8.mp4

import webapp2

form="""
<form method="post">
    What's your birthday?
    <br>
    <label>
        Month
        <input type="text" name="month" value="%(month)s">
    </label>
    <label>
        Day
        <input type="text" name="day" value="%(day)s">
    </label>
    <label>
        Year
        <input type="text" name="year" value="%(year)s">
    </label>
    <div style="color: red">%(error)s</div>
    <br>
    <br>
    <input type="submit">
</form>
"""


def valid_day(day):
    if day and day.isdigit():
        day=int(day)
        if day>0 and day<=31:
            return day


months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August',
                        'September', 'October', 'November', 'December']
month_abbvs = dict((m[:3].lower(),m) for m in months)
def valid_month(month):
    if month:
        short_month=month[:3].lower()
        return month_abbvs.get(short_month)


def valid_year(year):
        if(year and year.isdigit()):
                year = int(year)
        if(year < 2020 and year > 1880):
                return year

class MainPage(webapp2.RequestHandler):
    def write_form(self, error="", month="", day="", year=""):
        self.response.out.write(form %{"error": error, "month": month, "day": day, "year": year})    

    def get(self):
        #self.response.headers['Content-Type'] = 'text/plain'
        #self.response.out.write(form)
        self.write_form()

    def post(self):
        user_month = self.request.get('month')
        user_day = self.request.get('day')
        user_year = self.request.get('year')

        month = valid_month(user_month)
        day = valid_day(user_day)
        year = valid_year(user_year)

        if not (month and day and year):
            #self.response.out.write(user_month)
            #self.response.out.write(form)
            self.write_form("That doesn't look valid to me, friend.", user_month, user_day, user_year)
        else:
            self.response.out.write("Thanks! That's a totally valid day!")

app = webapp2.WSGIApplication([
    ('/', MainPage)
], debug=True)


https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/OpOOJcP-fY0.mp4

Handling HTML Input

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/K37Ldm4GSPo.mp4

HTML Escaping

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/teNvqTRP5EY.mp4

Using HTML Escaping

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/Hp-z-SVf3fw.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/2T-ubUA5xLk.mp4

Implementing HTML Escaping

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/NmCRWl-OZ60.mp4

# User Instructions
# 
# Implement the function escape_html(s), which replaces
# all instances of:
# > with &gt;
# < with &lt;
# " with &quot;
# & with &amp;
# and returns the escaped string
# Note that your browser will probably automatically 
# render your escaped text as the corresponding symbols, 
# but the grading script will still correctly evaluate it.
# 

def escape_html(s):


# print escape_html('>')
# print escape_html('<')
# print escape_html('"')
# print escape_html("&")

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/4NKBjlnV530.mp4

def escape_html(s):
    for (i,o) in (("&","&amp;"),(">","&gl;"),("<","&lt;"),('"',"&quot;")):
        s=s.replace(i,o)
    return s

or

import cgi

def escape_html(s):
    return cgi.escape(s, quote = True)

Problems Reinventing the Wheel

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/4YEcl5g3ADA.mp4

Current Limitations

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/_lRKZMPh5R8.mp4

import webapp2
import cgi

def escape_html(s):
    return cgi.escape(s, quote = True)

form="""
<form method="post">
    What's your birthday?
    <br>
    <label>
        Month
        <input type="text" name="month" value="%(month)s">
    </label>
    <label>
        Day
        <input type="text" name="day" value="%(day)s">
    </label>
    <label>
        Year
        <input type="text" name="year" value="%(year)s">
    </label>
    <div style="color: red">%(error)s</div>
    <br>
    <br>
    <input type="submit">
</form>
"""


def valid_day(day):
    if day and day.isdigit():
        day=int(day)
        if day>0 and day<=31:
            return day


months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August',
                        'September', 'October', 'November', 'December']
month_abbvs = dict((m[:3].lower(),m) for m in months)
def valid_month(month):
    if month:
        short_month=month[:3].lower()
        return month_abbvs.get(short_month)


def valid_year(year):
        if(year and year.isdigit()):
                year = int(year)
        if(year < 2020 and year > 1880):
                return year

class MainPage(webapp2.RequestHandler):
    def write_form(self, error="", month="", day="", year=""):
        self.response.out.write(form %{"error": error,
                                        "month": escape_html(month),
                                        "day": escape_html(day),
                                        "year": escape_html(year)})

    def get(self):
        #self.response.headers['Content-Type'] = 'text/plain'
        #self.response.out.write(form)
        self.write_form()

    def post(self):
        user_month = self.request.get('month')
        user_day = self.request.get('day')
        user_year = self.request.get('year')

        month = valid_month(user_month)
        day = valid_day(user_day)
        year = valid_year(user_year)

        if not (month and day and year):
            self.write_form("That doesn't look valid to me, friend.", user_month, user_day, user_year)
        else:
            self.response.out.write("Thanks! That's a totally valid day!")

app = webapp2.WSGIApplication([
    ('/', MainPage)
], debug=True)

Redirection

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/gjPdQ-ywbPM.mp4

Redirection Advantages

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/k84dleLQ-WI.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/eygchvjmP60.mp4

Implementing Redirection

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/46HPScqA0CA.mp4

import webapp2
import cgi

def escape_html(s):
    return cgi.escape(s, quote = True)

form="""
<form method="post">
    What's your birthday?
    <br>
    <label>
        Month
        <input type="text" name="month" value="%(month)s">
    </label>
    <label>
        Day
        <input type="text" name="day" value="%(day)s">
    </label>
    <label>
        Year
        <input type="text" name="year" value="%(year)s">
    </label>
    <div style="color: red">%(error)s</div>
    <br>
    <br>
    <input type="submit">
</form>
"""


def valid_day(day):
    if day and day.isdigit():
        day=int(day)
        if day>0 and day<=31:
            return day


months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August',
                        'September', 'October', 'November', 'December']
month_abbvs = dict((m[:3].lower(),m) for m in months)
def valid_month(month):
    if month:
        short_month=month[:3].lower()
        return month_abbvs.get(short_month)


def valid_year(year):
        if(year and year.isdigit()):
                year = int(year)
        if(year < 2020 and year > 1880):
                return year

class MainPage(webapp2.RequestHandler):
    def write_form(self, error="", month="", day="", year=""):
        self.response.out.write(form %{"error": error,
                                        "month": escape_html(month),
                                        "day": escape_html(day),
                                        "year": escape_html(year)})

    def get(self):
        self.write_form()

    def post(self):
        user_month = self.request.get('month')
        user_day = self.request.get('day')
        user_year = self.request.get('year')

        month = valid_month(user_month)
        day = valid_day(user_day)
        year = valid_year(user_year)

        if not (month and day and year):
            self.write_form("That doesn't look valid to me, friend.", user_month, user_day, user_year)
        else:
            self.redirect("/thanks")

class ThanksHandler(webapp2.RequestHandler):
    def get(self):
        self.response.out.write("Thanks! That's a totally valid day!")

app = webapp2.WSGIApplication([
    ('/', MainPage),
    ('/thanks', ThanksHandler)
], debug=True)

Problem Set 2

Rot13

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/uMGNwoFHfB4.mp4
In order to be graded correctly for this homework, there are a few things to keep in mind. We’ll be grading your web app by POSTing to your form and retrieving the text that has been encoded with ROT13. There are a few main issues you need to keep in mind in order for this to work:

  • The textarea form element where the user inputs the text to encode must be named ‘text’. In other words, you must have ‘textarea name=”text”‘ for us to post to.
  • The form method must be POST, not GET.
  • You must enter the full url into the supplied textbox above, including the path. For example, our example app is running at http://udacity-cs253.appspot.com/unit2/rot13, but if we instead only entered http://udacity-cs253.appspot.com/ then the grading script would not work.
  • Don’t forget to escape your output!

User Signup

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/SkSJp6IIZfw.mp4
In order to be graded correctly for this homework, there are a few things to keep in mind. We’ll be grading your web app by posting to your form and then checking the HTTP Response we receive. There are a few main issues you need to keep in mind in order for this to work:

  • The form elements where the user inputs their username, password, password again, and email address must be named “username”, “password”, “verify”, and “email”, respectively.
  • The form method must be POST, not GET.
  • Upon invalid user input, your web app should re-render the form for the user.
  • Upon valid user input, your web app should redirect to a welcome page for the user.
    • This page must include both “Welcome” and the user’s username.
  • You must enter the full url into the supplied textbox above, including the path. For example, our example app is running at http://udacity-cs253.appspot.com/unit2/signup, but if we instead only entered http://udacity-cs253.appspot.com/ then the grading script would not work.

Regular Expressions
A regular expression is a handy tool for matching text to a pattern. The regular expressions that we’re using to validate you input are as follows:

  • Username: “^[a-zA-Z0-9_-]{3,20}$”
  • Password: “^.{3,20}$”
  • Email: “^[\S]+@[\S]+.[\S]+$”

Example code for validating a username is as follows:

import re
USER_RE = re.compile(r"^[a-zA-Z0-9_-]{3,20}$")
def valid_username(username):
return USER_RE.match(username)

More information on using regular expressions in Python can be found here

NOTE: When you go off to make real applications that require form validation, remember that using regex to check an email address is not quite as simple as we make it seem here. See this Stack Overflow question for more on email validation.

Rot13 Solution

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/NYzMnbSjOWA.mp4
The solution files are here. In order to open them, Windows users will need an archive utility that opens tgz files, like 7zip. Linux and Mac users can use the built-in functionality of their archive managers. Barring that, Linux and Mac users can directly use the command:

tar xf hw2.tgz

User Signup Solution

The solution files are here. In order to open them, Windows users will need an archive utility that opens tgz files, like 7zip. Linux and Mac users can use the built-in functionality of their archive managers. Barring that, Linux and Mac users can directly use the command:

tar xf hw2.tgz

Office Hours 2

Question 1

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/0uBFVZRVnrQ.mp4
Jinja2 Documentation

Question 2

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/5-UWdqZQOIw.mp4

Question 3

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/YY7joMbML8k.mp4

Question 4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/9vTJkEjXw6Q.mp4
We now have a course for beginner Object Oriented Programming in Python:

https://www.udacity.com/course/ud036

Question 5

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/rLPeR3A3CnM.mp4

Lesson 8: Lesson 2a-Templates

Writing a Basic Form

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/ScXJ5au8q_w.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/Bnh2EnFQdkw.mp4

Hidden Inputs

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/dfFiYpxh4js.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/EHACuozhDQA.mp4
http://localhost:8080/?food=steak&food=eggs

Shopping List Take 1

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/h_EkzhX0D0I.mp4

1
2
"hello %s" % "SSQ"
'hello SSQ'


https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/87ieO3hrkDI.mp4

Introducing Templates

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/nT0wOJ3pQMw.mp4
jinja

Template Refactor

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/9HoEid5G4I4.mp4

Variable Substitution

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/D6q5TePkyo0.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/ppsNOLB7p4M.mp4


Errata
Don’t include quotation marks in your solution.

For additional clarification on the different render methods, see this discussion thread.
<h2>Hello, </h2>

Statement Syntax

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/13P8ncVwL_o.mp4

1
2
3
4
5
{% if name=="steve" %}
hello, steve!
{% else %}
who are you?
{% endif %}

Testing Statement Syntax

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/zI4rmjjICmU.mp4

Templates and Types

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/4VYTtyHnKEs.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/d-PAPeH0bd0.mp4

1
2
3
4
5
{% if n==1 %}
n=1
{% else %}
n!=1
{% endif %}

1
2
3
4
5
def get(self):
n=self.request.get("n")
if n:
n=int(n)
self.render("shopping_list.html", n=n)

Templates and Types

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/4VYTtyHnKEs.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/d-PAPeH0bd0.mp4

1
2
3
4
5
{% if n==1 %}
n=1
{% else %}
n!=1
{% endif %}

1
2
3
4
5
def get(self):
n=self.request.get("n")
if n:
n=int(n)
self.render("shopping_list.html", n=n)

For Loop Syntax

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/KzZwbKZweKA.mp4

1
2
3
{% for statement %}
body
{% endfor %}

1
2
3
4
5
<ol>
{% for x in range(1,n+1) %}
<li>{{x ** 2}}</li>
{% endfor %}
</ol>

FizzBuzz

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/nxoQoSYJryc.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/KhrAMbp2MRA.mp4

1
2
3
n=self.request.get("n")
if n:
n=int(n)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<ol>
{% for i in range(1,n+1) %}
<li>
{% if i % 3 ==0 and i % 5 ==0 %}
fizzbuzz
{% elif i % 3 ==0 %}
fizz
{% elif i % 5 ==0 %}
buzz
{% else %}
{{i}}
{% endif %}
</li>
{% endfor %}
</ol>

Shopping List Take 2

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/BkqW2HKdL0M.mp4
get rid of

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
output = form_html
output_hidden=""
items=self.request.get_all("food")
if items:
output_items=""
for item in items:
output_hidden+=hidden_html % item
output_items+=item_html % item
output_shopping = shopping_list_html % output_items
output += output_shopping
output=output % output_hidden
self.write(output)

and

1
2
3
4
5
6
7
8
9
10
11
12
13
14
hidden_html="""
<input type="hidden" name="food" value="%s">
"""
item_html="<li>%s</li>"
shopping_list_html="""
<br>
<br>
<h2>Shopping List</h2>
<ul>
%s
</ul>
"""

change following code in your shopping_list.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<form>
<h2>Add a food</h2>
<input type="text" name="food">
{% if items %}
{% for item in items %}
<input type="hidden" name="food" value="{{item}}">
{% endfor %}
{% endif %}
<button>Add</button>
{% if items %}
<br>
<br>
<h2>Shopping List</h2>
<ul>
{% for item in items %}
<li>{{item}}</li>
{% endfor %}
</ul>
{% endif %}
</form>


https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/9DaCBZImS54.mp4

self.request.get_all()
self.request.get_all() is a function that returns a list of all values that belong to string that matches a key in our query parameter. For example, if we pass in these query parameters: mysite.com?food=chips&food=fruit&food=milk, then get_all() will return a list that contains the strings chips,food,milk

Jinja2 Templates
Note that the bracket and the percent sign needs to be next to each other such as:

1
{% keyword %}

AND NOT

1
{ % keyword % }

Escaping Templates

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/oQJCuxvH_VM.mp4
(recommand)first way

1
2
jinja_env = jinja2.Environment(loader = jinja2.FileSystemLoader(template_dir),
autoescape=True)

except:
<li></li>
second way:
<li></li>

Helpful Tips

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/4eXgr5beSkU.mp4

Template Inheritance

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/v81yoy1L1Bo.mp4

FizzBuzz Inheritance

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/ls9qRh8LVts.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/nmEgJJYhW-I.mp4

Conclusion

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/O60XPmSy1OY.mp4

Lesson 9: Lesson 3-Databases

note:
https://www.udacity.com/wiki/CS253%20Unit%203

Databases

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/EK0lMxBKRRw.mp4

Databases Continued

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/Y1av5nYgQKM.mp4

What Is a Database?

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/7yEjSZvZOAo.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/ngXxI8Q0WTg.mp4

Tables

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/7ldYR0Uis0I.mp4

Implementing Tables in Python

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/j-KIhN7LKJ8.mp4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
from collections import namedtuple
# make a basic Link class
Link = namedtuple('Link', ['id', 'submitter_id', 'submitted_time', 'votes',
'title', 'url'])
# list of Links to work with
links = [
Link(0, 60398, 1334014208.0, 109,
"C overtakes Java as the No. 1 programming language in the TIOBE index.",
"http://pixelstech.net/article/index.php?id=1333969280"),
Link(1, 60254, 1333962645.0, 891,
"This explains why technical books are all ridiculously thick and overpriced",
"http://prog21.dadgum.com/65.html"),
Link(23, 62945, 1333894106.0, 351,
"Learn Haskell Fast and Hard",
"http://yannesposito.com/Scratch/en/blog/Haskell-the-Hard-Way/"),
Link(2, 6084, 1333996166.0, 81,
"Announcing Yesod 1.0- a robust, developer friendly, high performance web framework for Haskell",
"http://www.yesodweb.com/blog/2012/04/announcing-yesod-1-0"),
Link(3, 30305, 1333968061.0, 270,
"TIL about the Lisp Curse",
"http://www.winestockwebdesign.com/Essays/Lisp_Curse.html"),
Link(4, 59008, 1334016506.0, 19,
"The Downfall of Imperative Programming. Functional Programming and the Multicore Revolution",
"http://fpcomplete.com/the-downfall-of-imperative-programming/"),
Link(5, 8712, 1333993676.0, 26,
"Open Source - Twitter Stock Market Game - ",
"http://www.twitstreet.com/"),
Link(6, 48626, 1333975127.0, 63,
"First look: Qt 5 makes JavaScript a first-class citizen for app development",
"http://arstechnica.com/business/news/2012/04/an-in-depth-look-at-qt-5-making-javascript-a-first-class-citizen-for-native-cross-platform-developme.ars"),
Link(7, 30172, 1334017294.0, 5,
"Benchmark of Dictionary Structures", "http://lh3lh3.users.sourceforge.net/udb.shtml"),
Link(8, 678, 1334014446.0, 7,
"If It's Not on Prod, It Doesn't Count: The Value of Frequent Releases",
"http://bits.shutterstock.com/?p=165"),
Link(9, 29168, 1334006443.0, 18,
"Language proposal: dave",
"http://davelang.github.com/"),
Link(17, 48626, 1334020271.0, 1,
"LispNYC and EmacsNYC meetup Tuesday Night: Large Scale Development with Elisp ",
"http://www.meetup.com/LispNYC/events/47373722/"),
Link(101, 62443, 1334018620.0, 4,
"research!rsc: Zip Files All The Way Down",
"http://research.swtch.com/zip"),
Link(12, 10262, 1334018169.0, 5,
"The Tyranny of the Diff",
"http://michaelfeathers.typepad.com/michael_feathers_blog/2012/04/the-tyranny-of-the-diff.html"),
Link(13, 20831, 1333996529.0, 14,
"Understanding NIO.2 File Channels in Java 7",
"http://java.dzone.com/articles/understanding-nio2-file"),
Link(15, 62443, 1333900877.0, 1244,
"Why vector icons don't work",
"http://www.pushing-pixels.org/2011/11/04/about-those-vector-icons.html"),
Link(14, 30650, 1334013659.0, 3,
"Python - Getting Data Into Graphite - Code Examples",
"http://coreygoldberg.blogspot.com/2012/04/python-getting-data-into-graphite-code.html"),
Link(16, 15330, 1333985877.0, 9,
"Mozilla: The Web as the Platform and The Kilimanjaro Event",
"https://groups.google.com/forum/?fromgroups#!topic/mozilla.dev.planning/Y9v46wFeejA"),
Link(18, 62443, 1333939389.0, 104,
"github is making me feel stupid(er)",
"http://www.serpentine.com/blog/2012/04/08/github-is-making-me-feel-stupider/"),
Link(19, 6937, 1333949857.0, 39,
"BitC Retrospective: The Issues with Type Classes",
"http://www.bitc-lang.org/pipermail/bitc-dev/2012-April/003315.html"),
Link(20, 51067, 1333974585.0, 14,
"Object Oriented C: Class-like Structures",
"http://cecilsunkure.blogspot.com/2012/04/object-oriented-c-class-like-structures.html"),
Link(10, 23944, 1333943632.0, 188,
"The LOVE game framework version 0.8.0 has been released - with GLSL shader support!",
"https://love2d.org/forums/viewtopic.php?f=3&amp;t=8750"),
Link(22, 39191, 1334005674.0, 11,
"An open letter to language designers: Please kill your sacred cows. (megarant)",
"http://joshondesign.com/2012/03/09/open-letter-language-designers"),
Link(21, 3777, 1333996565.0, 2,
"Developers guide to Garage48 hackatron",
"http://martingryner.com/developers-guide-to-garage48-hackatron/"),
Link(24, 48626, 1333934004.0, 17,
"An R programmer looks at Julia",
"http://www.r-bloggers.com/an-r-programmer-looks-at-julia/")]
# links is a list of Link objects. Links have a handful of properties. For
# example, a Link's number of votes can be accessed by link.votes if "link" is a
# Link.
# make the function query() return the number of votes for the link whose ID is
# 15
def query():

Here is more information on namedtuple used in this exercise.
https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/0jE0n6deDpk.mp4

Querying

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/2TFA879U_pc.mp4

1
2
3
4
5
6
7
8
9
def query():
submision=[]
for l in links:
if l.submitter_id==62443:
submision.append(l)
submision.sort(key=lambda x: x.submitted_time)
return submision
print query()

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/aXwzyv11_4Q.mp4
Here is more information on sorting and Lambda expressions in Python .

Why Databases?

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/bGvBewhooJc.mp4

Types of Databases

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/MORw_tCy42A.mp4
https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/Q3tsjEH9W-c.mp4

SQL

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/vgP5bfu0na4.mp4

Databases in Python

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/oleOUdXSfs0.mp4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
from collections import namedtuple
import sqlite3
# make a basic Link class
Link = namedtuple('Link', ['id', 'submitter_id', 'submitted_time', 'votes',
'title', 'url'])
# list of Links to work with
links = [
Link(0, 60398, 1334014208.0, 109,
"C overtakes Java as the No. 1 programming language in the TIOBE index.",
"http://pixelstech.net/article/index.php?id=1333969280"),
Link(1, 60254, 1333962645.0, 891,
"This explains why technical books are all ridiculously thick and overpriced",
"http://prog21.dadgum.com/65.html"),
Link(23, 62945, 1333894106.0, 351,
"Learn Haskell Fast and Hard",
"http://yannesposito.com/Scratch/en/blog/Haskell-the-Hard-Way/"),
Link(2, 6084, 1333996166.0, 81,
"Announcing Yesod 1.0- a robust, developer friendly, high performance web framework for Haskell",
"http://www.yesodweb.com/blog/2012/04/announcing-yesod-1-0"),
Link(3, 30305, 1333968061.0, 270,
"TIL about the Lisp Curse",
"http://www.winestockwebdesign.com/Essays/Lisp_Curse.html"),
Link(4, 59008, 1334016506.0, 19,
"The Downfall of Imperative Programming. Functional Programming and the Multicore Revolution",
"http://fpcomplete.com/the-downfall-of-imperative-programming/"),
Link(5, 8712, 1333993676.0, 26,
"Open Source - Twitter Stock Market Game - ",
"http://www.twitstreet.com/"),
Link(6, 48626, 1333975127.0, 63,
"First look: Qt 5 makes JavaScript a first-class citizen for app development",
"http://arstechnica.com/business/news/2012/04/an-in-depth-look-at-qt-5-making-javascript-a-first-class-citizen-for-native-cross-platform-developme.ars"),
Link(7, 30172, 1334017294.0, 5,
"Benchmark of Dictionary Structures", "http://lh3lh3.users.sourceforge.net/udb.shtml"),
Link(8, 678, 1334014446.0, 7,
"If It's Not on Prod, It Doesn't Count: The Value of Frequent Releases",
"http://bits.shutterstock.com/?p=165"),
Link(9, 29168, 1334006443.0, 18,
"Language proposal: dave",
"http://davelang.github.com/"),
Link(17, 48626, 1334020271.0, 1,
"LispNYC and EmacsNYC meetup Tuesday Night: Large Scale Development with Elisp ",
"http://www.meetup.com/LispNYC/events/47373722/"),
Link(101, 62443, 1334018620.0, 4,
"research!rsc: Zip Files All The Way Down",
"http://research.swtch.com/zip"),
Link(12, 10262, 1334018169.0, 5,
"The Tyranny of the Diff",
"http://michaelfeathers.typepad.com/michael_feathers_blog/2012/04/the-tyranny-of-the-diff.html"),
Link(13, 20831, 1333996529.0, 14,
"Understanding NIO.2 File Channels in Java 7",
"http://java.dzone.com/articles/understanding-nio2-file"),
Link(15, 62443, 1333900877.0, 1244,
"Why vector icons don't work",
"http://www.pushing-pixels.org/2011/11/04/about-those-vector-icons.html"),
Link(14, 30650, 1334013659.0, 3,
"Python - Getting Data Into Graphite - Code Examples",
"http://coreygoldberg.blogspot.com/2012/04/python-getting-data-into-graphite-code.html"),
Link(16, 15330, 1333985877.0, 9,
"Mozilla: The Web as the Platform and The Kilimanjaro Event",
"https://groups.google.com/forum/?fromgroups#!topic/mozilla.dev.planning/Y9v46wFeejA"),
Link(18, 62443, 1333939389.0, 104,
"github is making me feel stupid(er)",
"http://www.serpentine.com/blog/2012/04/08/github-is-making-me-feel-stupider/"),
Link(19, 6937, 1333949857.0, 39,
"BitC Retrospective: The Issues with Type Classes",
"http://www.bitc-lang.org/pipermail/bitc-dev/2012-April/003315.html"),
Link(20, 51067, 1333974585.0, 14,
"Object Oriented C: Class-like Structures",
"http://cecilsunkure.blogspot.com/2012/04/object-oriented-c-class-like-structures.html"),
Link(10, 23944, 1333943632.0, 188,
"The LOVE game framework version 0.8.0 has been released - with GLSL shader support!",
"https://love2d.org/forums/viewtopic.php?f=3&amp;t=8750"),
Link(22, 39191, 1334005674.0, 11,
"An open letter to language designers: Please kill your sacred cows. (megarant)",
"http://joshondesign.com/2012/03/09/open-letter-language-designers"),
Link(21, 3777, 1333996565.0, 2,
"Developers guide to Garage48 hackatron",
"http://martingryner.com/developers-guide-to-garage48-hackatron/"),
Link(24, 48626, 1333934004.0, 17,
"An R programmer looks at Julia",
"http://www.r-bloggers.com/an-r-programmer-looks-at-julia/")]
# links is a list of Link objects. Links have a handful of properties. For
# example, a Link's number of votes can be accessed by link.votes if "link" is a
# Link.
# make and populate a table
db = sqlite3.connect(':memory:')
db.execute('create table links ' +
'(id integer, submitter_id integer, submitted_time integer, ' +
'votes integer, title text, url text)')
for l in links:
db.execute('insert into links values (?, ?, ?, ?, ?, ?)', l)
# db is an in-memory sqlite database that can respond to sql queries using the
# execute() function.
#
# For example. If you run
#
# c = db.execute("select * from links")
#
# c will be a "cursor" to the results of that query. You can use the fetchmany()
# function on the cursor to convert that cursor into a list of results. These
# results won't be Links; they'll be tuples, but they can be passed turned into
# a Link.
#
# For example, to print all the votes for all of the links, do this:
#
# c = db.execute("select * from links")
# for link_tuple in c:
# link = Link(*link_tuple)
# print link.votes
#
# QUIZ - make the function query() return the number of votes the link with ID = 2 has
def query():
c = db.execute("PUT YOUR SQL HERE")
link = Link(*c.fetchone())
return link.votes

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/F35zP0xOMFM.mp4

1
2
3
4
5
6
def query():
c = db.execute("select * from links where id=2")
link = Link(*c.fetchone())
return link.votes
print query()

More Advanced SQL

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/aWIoeUm-HVA.mp4

Advanced SQL in Python

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/u2nQqxMfLE4.mp4

1
2
3
4
5
def query():
c = db.execute("select * from links where submitter_id=62443 AND votes > 1000")
link = Link(*c.fetchone())
return link.id
print query()

or

1
2
3
4
5
6
def query():
c = db.execute("select * from links where submitter_id=62443 AND votes > 1000")
for link_tuple in c:
link = Link(*link_tuple)
return link.id
print query()

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/KsGqEVJsmO4.mp4

Order By

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/L55IfVfNvL8.mp4
You can find out more information about list comprehensions in the Python documentation and a supplementary lesson found here

1
2
3
4
5
6
7
8
9
def query():
results=[]
c=db.execute("select * from links where submitter_id=62443 ORDER BY submitted_time ASC")
for link_tuple in c:
link = Link(*link_tuple)
print link
results.append(link.id)
return results
print query()

better

1
2
3
4
5
def query():
c=db.execute("select id from links where submitter_id=62443 order by submitted_time asc")
results=[t[0] for t in c]
return results
print query()

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/kWvI1pvxYZ4.mp4

Joins

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/KddpLKB5JYA.mp4

Indexes

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/kgC5ZwM9BS8.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/dLAZvKNkZcs.mp4

1
2
3
4
5
6
7
8
# QUIZ - implement the function link_by_id() that takes a link's ID and returns
# the Link object itself
def link_by_id(link_id):
for l in links:
if l.id==link_id:
return l
print link_by_id(24)

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/ASrkP2-oBuM.mp4

Using Dictionaries As Indices

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/4c3leET2nzg.mp4

1
2
3
4
5
6
7
# QUIZ - implement the function build_link_index() that creates a python dictionary
# the maps a link's ID to the link itself
def build_link_index():
result={}
for l in links:
result[l.id]=l
return result

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/snkHGcSRRsk.mp4

Lookup

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/pq5cH9fx524.mp4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def build_link_index():
index = {}
for l in links:
index[l.id] = l
return index
link_index = build_link_index()
def link_by_id(link_id):
return link_index.get(link_id)
# QUIZ - implement the function add_new_link() that both adds a link to the
# "links" list and updates the link_index dictionary.
def add_new_link(link):

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/v-nktgcT2A4.mp4

1
2
3
4
5
6
7
8
def add_new_link(link):
links.append(link)
link_index[link.id]=link
l=Link(50,1,1,1,'title','url')
add_new_link(l)
print links[-1]
print link_by_id(50)

output

1
2
Link(id=50, submitter_id=1, submitted_time=1, votes=1, title='title', url='url')
Link(id=50, submitter_id=1, submitted_time=1, votes=1, title='title', url='url')

Advantages of Indices

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/9CoBxepbSR4.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/da2uj4wK10Y.mp4

Real-World Example

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/31XAKJmp0sk.mp4

Indices for Sorting

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/REgL9DoFMdU.mp4

Another Real-World Example

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/XkuT8x6Y94A.mp4

Scaling Databases

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/dkhOZOmV7Fo.mp4

note:
method | replicate | shard
— | — | —
downside: | 1. doesn’t increase the write speed. 2. replication lag | 1. complex queries(range queries). 2. joins become difficult

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/NTpHCHAD2tM.mp4

Growing Databases

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/cFFM_GCvrYs.mp4

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/R9T3hQ1axaw.mp4

ACID

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/j-r6Fmzr4PM.mp4
note:
atumicity
consistency
isolation
durability

Google App Engine Datastore

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/r-wl-VZhNXo.mp4

GQL

https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/SnaxUDryqaU.mp4
note:
GQL:

  1. all queries begin with SELECT *
  2. no joins
  3. all queries must be indexed
    SQL:
    run arbitrary queries

    Automatic Sharding and Replication

    https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/i4Fgm_XQ10M.mp4
    https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/TmPtKXgjZwQ.mp4

    ASCII Chan

    https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/dtlAAUtkvgQ.mp4

    Getting Started on ASCII Chan

    https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/hiyj6fDFm3c.mp4

    Creating the Form

    https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/yx4SvoTbiuI.mp4

    https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/gHsG6aYIaXo.mp4

    Textarea

    https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/u5iR0i5KOMY.mp4

    Form Handling

    https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/odSexP9bScI.mp4

    Form Handling Continued

    https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/iB5cwOZK0JU.mp4

    Creating Entities

    https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/dFX5Dp-v04s.mp4

    Datastore Types

    https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/_opjCcw2Al0.mp4
    https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/y4o26tQcAqc.mp4

    Creating Entities Continued

    https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/gmgKRL1wiCk.mp4

    Working with Entities

    https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/JUDj8fXp3eY.mp4

    Running Queries

    https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/h7LyH4cvYJo.mp4
    https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/cbpxkj6DGIg.mp4

    Styling

    https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/1pvAum4H7-Y.mp4

    Lesson 10: Problem Set 3-Building a Basic Blog

    Basic Blog

    https://s3.cn-north-1.amazonaws.com.cn/u-vid-hd/ysFzedoB3Rg.mp4