├── requirements.txt
├── templates
├── basic-page.html
└── dynamic-page.html
├── test
└── web_starter_tests.py
├── app.py
└── README.md
/requirements.txt:
--------------------------------------------------------------------------------
1 | Flask==0.10.1
2 | Jinja2==2.7.2
3 | MarkupSafe==0.19
4 | Werkzeug==0.9.4
5 | itsdangerous==0.24
6 | psycopg2==2.5.2
7 | wsgiref==0.1.2
8 |
--------------------------------------------------------------------------------
/templates/basic-page.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Look how cool this page is
4 |
5 |
6 | Look how cool this page is!
7 |
8 | Isn't it sweet!
9 |
10 |
11 |
--------------------------------------------------------------------------------
/templates/dynamic-page.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Look at this dynamic page
4 |
5 |
6 | Look at this dynamic page!
7 |
8 | Isn't it sweet! Try adding more query arguments to the URL, separated with "&" signs. Like this:
9 |
10 |
11 | ?name=Sarah&gender=Female&hometown=Boston
12 |
13 |
14 | {% for key, value in user_data.items() %}
15 |
16 | | {{key}} |
17 | {{value}} |
18 |
19 | {% endfor %}
20 |
21 |
22 |
--------------------------------------------------------------------------------
/test/web_starter_tests.py:
--------------------------------------------------------------------------------
1 | # Just like the main Flask app, we're going to do some imports
2 | # First, because we're writing tests for the Flask app inside
3 | # web_starter, we'll need to import it
4 | from web_starter.app import app
5 |
6 | # Now we're going to import the TestCase class from Flask.ext.testing
7 | from flask.ext.testing import TestCase
8 |
9 | # Finally, we'll import the popular unittest framework
10 | import unittest
11 |
12 |
13 | class WebStarterTest(unittest.TestCase):
14 |
15 | def test_homepage(self):
16 | """ Tests the homepage method """
17 | # Create a test variable
18 | tester = app.test_client(self)
19 | # Get the page at "/"
20 | response = tester.get('/')
21 | # Assert the response code of the page at "/" is 200 (successful)
22 | self.assertEqual(response.status_code, 200)
23 | # Assert the content of the page at "/" shows "Hello World"
24 | self.assertEqual(response.data, "Hello World")
25 |
26 | def test_basic_page(self):
27 | """ Tests the basic-page method """
28 | # Create a test variable
29 | tester = app.test_client(self)
30 | # Get the page at "/basic-page/"
31 | response = tester.get('/basic-page/', content_type='html/text')
32 | # Assert the response code of the page at "/basic-page"
33 | # is 200 (successful)
34 | self.assertEqual(response.status_code, 200)
35 | # Assert the content of the page at "/basic-page" shows "Isn't it
36 | # sweet"
37 | self.assertTrue("Isn't it sweet" in response.data)
38 |
39 | def test_dynamic_page_no_args(self):
40 | """ Tests the dynamic-page method with NO args """
41 | # Create a test variable
42 | tester = app.test_client(self)
43 | # Get the page at "/dynamic-page/"
44 | response = tester.get('/dynamic-page/', content_type='html/text')
45 | # Assert the response code of the page at "/dynamic-page/" is 200
46 | # (successful)
47 | self.assertEqual(response.status_code, 200)
48 | # Assert the response code of the page at "/dynamic-page/" shows
49 | # "Add some query arguments"
50 | self.assertTrue("Add some query arguments" in response.data)
51 |
52 | if __name__ == "__main__":
53 | unittest.main()
54 |
--------------------------------------------------------------------------------
/app.py:
--------------------------------------------------------------------------------
1 | # Welcome to your first Flask app :)
2 |
3 | # Imports usually happen at the top of the file in python. They load
4 | # in all the other libraries that your code will be using, so that you
5 | # can call the functions they define, or instantiate the classes they create.
6 |
7 | # Import the main class from the "Flask" library that we need to create our
8 | # web application, as well as the `render_template` function for returning
9 | # HTML files as responses, as well as the `request` objects which contains
10 | # information about requests that we recieve, like the URL and cookies and
11 | # stuff like that.
12 | from flask import Flask, render_template, request
13 |
14 | # Create the variable `app` which is an instance of the Flask class that
15 | # we just imported. Being an "instance of a class" is something pretty
16 | # import to any kind of software development, but you don't need to know
17 | # exactly what it means right now.
18 | app = Flask(__name__)
19 |
20 |
21 | # Here, we're creating the homepage of our application. We're defining a
22 | # function called `homepage` which doesn't take any arguments (nothing
23 | # inside the parentheses). Above the function definiton, we're adding a
24 | # "decorator" which tells our app which "route" (ie URL) should be mapped
25 | # to this function. So if you wanted to add more pages to your app, you
26 | # could add new python functions for them, and decorate them with new routes.
27 | @app.route("/")
28 | def homepage():
29 |
30 | # Inside this function, you can run whatever logic you want, running any python
31 | # code your heart desires. You could check the cookies on the request to see if
32 | # there's a logged in user making the requests, you could read or write to a
33 | # database or run any kind of functions you want. Here, we're just returning a
34 | # simple string to be returned as the response.
35 | return "Hello World"
36 |
37 |
38 | @app.route("/basic-page/")
39 | def basic_page():
40 | # But you don't want to have to write the HTML for your webpages inside a python
41 | # string. That'd get really annoying quickly. Thankfully, most web frameworks
42 | # come with a "template engine" that can take basic HTML files and spit it out
43 | # in a response. Here, we're rendering the 'basic-page.html' file inside the
44 | # templates folder, which is where Flask looks for template files by default.
45 | # Rending just means taking the template and turning it into a complete HTML documet.
46 | return render_template("basic-page.html")
47 |
48 | # Using templates is cool and all, but web applications are supposed to by dynamic,
49 | # not just showing the same content every time you load the page. So let's build a
50 | # page that returns different output based on some query arguments that the user
51 | # passes in. Those are the parts of the URL after the "?" sign.
52 | @app.route("/dynamic-page/")
53 | def dynamic_page():
54 |
55 | # If there are no query arguments on the URL (ie length of query arguments is 0)
56 | # then tell the user to try adding some.
57 | if len(request.args) == 0:
58 | return "Add some query arguments to the end of the URL. Like this ?name=Ben"
59 |
60 | # Here, we're rendering a different template, and passing the query arguments
61 | # to the template to be mixed into the content. This will create a variable
62 | # called `user_data` that we can user in the HTML template, and it contains the
63 | # values that were in the query arguments. Go check out that file to see how that
64 | # works.
65 | return render_template("dynamic-page.html", user_data=request.args)
66 |
67 |
68 | # Some boilerplate code that just says "if you're running this from the command
69 | # line, start here." It's not critical to know what this means yet.
70 | if __name__ == "__main__":
71 | app.debug = True
72 | app.run()
73 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Web Basic
2 | This is a project I made to cover the very basics of building a super simple web application using the [Python programming language](https://www.python.org/) and the [Flask web framework](http://flask.pocoo.org/).
3 |
4 | I wrote this for anyone who might know a bit of Python from a basic programming class, but who needs a good place to start for web development.
5 |
6 | *****
7 |
15 | ## Getting the App Running On You Computer
16 | In order to work on the code and test it on your computer, we'll need to quickly setup your computer to be able to run Flask applications. This might seem like a lot of work but **don't worry because you'll really on have to do this once.** It might take a few confusing minutes before you even get started, but unfortunately the tedium is necessary to make sure your computer is ready to work on the app.
17 |
18 | First, you'll want to pull up your system's terminal window. I'm going to assume you're working on a Mac OSX computer. Open the "Terminal" app by searching for it in spotlight search, or opening it from the Applications folder. We're going to run two commands to make sure our system is all setup.
19 |
20 | ### Ensuring Python is Installed
21 | First, type `python` and hit enter. You should see something like this
22 |
23 | Python 2.7.5 (default, Aug 25 2013, 00:04:04)
24 | [GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
25 | Type "help", "copyright", "credits" or "license" for more information.
26 | >>>
27 |
28 | This ensures that you have Python installed on your system, which we'll need to run our app. Note that your version number might look a little different, but as long as your version of Python is 2.6 or greater, you should be fine.
29 |
30 | If you want, you can start typing and hit enter, you'll be writing Python code! Try typing `2+2` or `2**8` to do some basic math. If you're ready to move on, just hit `Ctrl+D` to exit out of the Python interactive interpreter.
31 |
32 | ### Ensuring Git is Installed
33 | The next command we're goint to try running is called "git" and it's a program that's used to keep track of changes to files over time. This is known as "version control" and is super important if you'll be working on real apps.
34 |
35 | Git allows you to see all of the different changes that were made to the app over time, and what was added and removed every time a change was made. This lets you "step through" the changes and see the stages the app went through as it was being built.
36 |
37 | We'll also use git to download a copy of the app on your computer. Try typing `git` in your terminal window, hit "enter" and see what happens. If you see a big output about usage and commonly used commands, then you already have it installed on your system and you're ready to go and can skip to the next section.
38 |
39 | Unfortunately, most new Macs don't have git installed by default, so you'll probably need to install it [from here](http://sourceforge.net/projects/git-osx-installer/). Once you download the installer and run through all the steps, you should be able to close and re-open the terminal application, type `git` and press enter, and see some output that looks like this:
40 |
41 | usage: git [--version] [--help] [-C ] [-c name=value]
42 | [--exec-path[=]] [--html-path] [--man-path] [--info-path]
43 | [-p|--paginate|--no-pager] [--no-replace-objects] [--bare]
44 | [--git-dir=] [--work-tree=] [--namespace=]
45 | []
46 |
47 | The most commonly used git commands are:
48 | add Add file contents to the index
49 | bisect Find by binary search the change that introduced a bug
50 | branch List, create, or delete branches
51 | checkout Checkout a branch or paths to the working tree
52 | clone Clone a repository into a new directory
53 | commit Record changes to the repository
54 | diff Show changes between commits, commit and working tree, etc
55 | fetch Download objects and refs from another repository
56 | grep Print lines matching a pattern
57 | init Create an empty Git repository or reinitialize an existing one
58 | log Show commit logs
59 | merge Join two or more development histories together
60 | mv Move or rename a file, a directory, or a symlink
61 | pull Fetch from and integrate with another repository or a local branch
62 | push Update remote refs along with associated objects
63 | rebase Forward-port local commits to the updated upstream head
64 | reset Reset current HEAD to the specified state
65 | rm Remove files from the working tree and from the index
66 | show Show various types of objects
67 | status Show the working tree status
68 | tag Create, list, delete or verify a tag object signed with GPG
69 |
70 | 'git help -a' and 'git help -g' lists available subcommands and some
71 | concept guides. See 'git help ' or 'git help '
72 | to read about a specific subcommand or concept.
73 |
74 |
75 | ### Downloading the Project Locally Using Git
76 | Alright, now that we have ensured your system has both Python and git installed, we're ready to start getting the application setup. Note that we'll be running a bunch of commands in the same terminal window, so it's important to leave that up the whole time.
77 |
78 | First, you'll want to move to your desktop by running
79 |
80 | `cd ~/Desktop`
81 |
82 | And then run the following command to download a copy of the app onto your desktop:
83 |
84 | `git clone git@github.com:hartleybrody/web_starter.git`
85 |
86 | You should see the folder for the app appear on your desktop with some folders and files inside it!
87 |
88 | You're almost ready to being working on the app, but first we're going to get a "development environment" running on your local computer so that you can make changes and test what they look like quickly.
89 |
90 | ### Setting up the Python Environment
91 | Still in your terminal window, we're going to install "pip" which is a tool for managing Python libraries. Run the following:
92 |
93 | `sudo easy_install pip`
94 |
95 | Note that you might need to enter your user account's password to approve the install. Don't worry if you start typing and nothing shows up, that's how the terminal handles password fields (the same way that browsers show dots or stars when you type a password into a web form). Hit "enter" when you're done typing your password to continue the installation.
96 |
97 | Once pip is installed, the only thing that's left is to install the Python packages that our app requires. You'll want to make sure you're in the same folder as the project, so you'll probably need to run
98 |
99 | `cd ~/Desktop/web_starter`
100 |
101 | Then, to install the packages, you run
102 |
103 | `pip install -r requirements.txt`
104 |
105 | This tells pip to install all of the packages listed inside the `requirements.txt` file. That might take a few seconds to download and install everything, and then everything is ready to go!
106 |
107 | ### Starting Your Local Server
108 | If you're still hanging in there, nice work! You will almost never have to run those steps again when you're first starting out, so you should be able to let them slide right out of your brain. Go take a break if need be to let your mind rest (but leave the terminal window open).
109 |
110 | Now that we're ready to start working on the app, simply type
111 |
112 | `python app.py`
113 |
114 | and you should see the following output
115 |
116 | * Running on http://127.0.0.1:5000/
117 | * Restarting with reloader
118 |
119 | Now, open up your browser and navigate to `http://localhost:5000/` and you should see the homepage of your app! Woohoo!
120 |
121 | ## Working On the App
122 | Using your favorite text editor (not Microsoft Word, try TextEdit), open the `app.py` file that's inside the app folder and start reading what's inside. There are tons of comments -- pieces of text that are meant for humans and are ignored by the program -- with every line of code, so it should be easy to read along and see what's happening.
123 |
124 | Once you've read through the basics, you'll be itching to start tinkering. Feel free to edit the code and play with your app. The local development server should reload every time you change a file, so edit something and then go see your changes by refreshing the app in your browser.
125 |
126 | If you want to learn more about other functions and tools that the Flask framework provides (like user sessions and showing messages and redirecting requests), check out the [Flask Quickstart Guide](http://flask.pocoo.org/docs/quickstart/) for more.
127 |
128 | ### You Should Learn Basic Git
129 | Whenever you make some big changes to the app that you're happy with, you should use git to "commit those changes", in order to save your progress. That way, if something goes wrong or you somehow mess everything up, you can easily revert back to your happy state. It also makes it easy to share your code with others and merge in changes someone else might want to make to help you.
130 |
131 | Using git is outside the scope of this tutorial, and you won't need it if you're just tinkering around. But if you start building something cool that you might actually launch and use, you should definitely take the time to [learn the basics of git](https://www.atlassian.com/git/tutorial/git-basics).
132 |
133 | ### Learning More About Web Development
134 | Building applications for the web, you might be overwhelmed by the vast number of complex concepts that come into play. From HTTP and networks, to databases and analytics, to caching and client-side Javascript code, there's a lot you need to learn to become a "full stack web developer", capable of building an entire web application yourself.
135 |
136 | But don't fret about that now. You'll learn about those concepts as you need them. There's no point trying to learn them all at once and then getting overwhelmed. Just keep an open mind, don't be scared to "Google" things when you're stuck ([stackoverflow.com](http://stackoverflow.com) is your friend!) and try to find a buddy or mentor you can bounce questions off of when you're really stuck.
137 |
138 | Being a software developer in any field -- web, mobile, systems, etc -- requires being a constant, life long learner. Technologies change, best practices evolve. If you keep working at it over time, you'll become more proficient and learn how to tackle the same problem in different ways, moving from [Hacker to Developer to Engineer](http://blog.hartleybrody.com/hacker-developer-engineer/).
139 |
140 | ### More Great Web Development Resources
141 | * [The Official Flask Tutorial](http://flask.pocoo.org/docs/tutorial/) - Walks you through the steps of creating a basic twitter clone. You'll learn how to store things in a database for later retrieval and how to do super basic user authentication.
142 |
143 | * [The Tuts+ Flask Tutorial](http://code.tutsplus.com/tutorials/an-introduction-to-pythons-flask-framework--net-28822) - This expands a bit on what we did in our app, adding template inhertence, so that you don't need to rewrite the same HTML in every template file.
144 |
145 | * [The Flask Mega Tutorial](http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world) - This is a really long tutorial but it covers most of the major aspects of building web applications, like using forms, sending email, doing (proper) user authentication, writing tests to let you know if you accidentally broke something, and deploying your application to a web server.
146 |
147 | * [Flaskr - Intro to Flask, Test Driven Development, and jQuery](https://github.com/mjhea0/flaskr-tdd) - This tutorial takes the Official Flask Tutorial to the next level by adding Test Driven Development as well as jQuery and AJAX, Bootstrap 3, and SQLAlchemy.
148 |
149 | ### Example Projects
150 | One of the best ways to learn any sort of coding is to look at working example code that's already being used in production. Here are some projects I've built using the Flask web framework.
151 |
152 | * [Project Naming](http://project-naming.herokuapp.com/) - A simple app that checks to see if the name you're thinking of using for a project would be available on Twitter, Facebook and as a domain name. [Code on github, here](https://github.com/hartleybrody/naming).
153 |
154 | * [Rooster App](http://www.roosterapp.co/) - An app that sends you a text message with your local forecast each morning. The code is a bit more complex than the Project Naming example, but you should still be able to recognize things you've seen before. [Code on github, here](https://github.com/hartleybrody/rooster).
155 |
156 |
157 | ## Contribute!
158 | If there are things you'd like to see added to this app, feel free to send me a pull request. Please keep in mind that the audience is people who are making their first foyer into web development, so anything that's too complex will be rejected.
159 |
160 | Things I'd love to add examples of:
161 |
162 | * Using SQL Alchemay to create an ORM
163 | * Using Users and Sessions
164 | * Template Inheretence
165 | * Writing some basic tests
166 |
167 |
--------------------------------------------------------------------------------