Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
I can run Flaskinni after having cloned its code, configured its dependencies in a virtual environment, set up a database, and added an environmental variables file.
A day before some hackathons or events like RailsBridge, experts will host a session to help everyone install the tools they'll need. If you serve pizza, you can call pretty much anything a party.
Whether you're using Windows, macOS, or Linux, you have a responsibility to your teammates that you keep your machine updated and organized. Run system updates, keep files off your desktop, have a system of organizing your project files. Knock this out early so it doesn't jam you up while installing complex programming tools.
Go slowly. Go patiently. Things may not work. You will have to Google stuff, study, maybe ask for help, and solve your problems. Keep hacking at the problem. That's how we all learn best.
Your computer only understands Python code through a compiler or interpreter. Your computer uses bytecode to run the software. Our interpreter changes our beautiful Python code into a jumble of machine instructions. Ensure you use the same version in development as you do in production. That means if your server will run, say, Python 3.10, that's what you use to build the thing.
This is the open-source database tool we're going to use. You'll set up Postgres to host your own private database. It won't be available outside of your computer. It's just so while you work on an app, it can access a practice source of information.
Remember postgres
password. Since my computer's database is only used for building and testing apps, I set the password also to postgres
Mac users should have Xcode and run xcode-select --install
in their terminals. Windows users need to install Git for Windows. This gives you the commands to clone a repository, manage your changes to code, and sync
Once upon a time, Javascript was just used to make pictures slowly spin on a webpage. Now we've got NodeJS letting this language that used to be purely stuck inside a web browser to now run independently on your computer. It's so popular, the npm tool to quickly install awesome new Node packages is a must-have.
Node Package Manager often encourages the installation of amazing CLI installers like choco
or brew
(Mac and Windows respectively). So if you like quickly installing awesome things and can accept the responsibility to do so safely, get one!
https://chocolatey.org/ (Windows) https://brew.sh/ (Mac)
Old-school CSS is a pain to program at a large scale. Sass is much more powerful. Your computer has to have it to run the WebAssembly service built into Flaskinni. If you've got Choco or Brew installed, adding Sass is a breeze.
I recommend these extensions
Custom icons (they make it much easier to see your files)
You can edit your code on the cloud with cool sites like SourceLair. A cloud-based IDE is likely going to be based on Linux. That means you'll need to know a bit about Linux CLI. Linux plays well with coders and a cloud-based IDE makes it easy to share your development progress with people and get feedback faster. That's big.
You can also set up right on your computer. You should know how to do this just so you can practice putting all the pieces together. I prefer to program in the cloud and locally and use GitHub to keep the two environments in sync.
Use VS Code's git tool to pull down the repo from GitHub.com: https://github.com/dadiletta/flaskinni
"Stand up" a database just sounds so much cooler than "set up," but it's the same idea. You can see in settings.py
that Flaskinni by default is going to reach out to a PSQL database named db-flaskinni
on the server 0.0.0.0
. The username and password used to access the database are also loaded there. Changes to this information shouldn't be done in settings.py
but rather a .env
fille. But before we do any of that, fire up pgAdmin and create a database.
Our .env
file doesn't and shouldn't ever get synced to GitHub. It's our secure place to keep the unique variables for each environment where our app will run.
First you use the correct version of Python to launch its venv module to create a folder for our dependencies (also named venv):
Windows: python -m venv venv
Mac: python3 -m venv venv
(as of this writing, Mac still comes with now-defunct Python2, so you need to distinguish between them)
Let's say you're using Windows and you need to specify a non-default version of Python. You may need a line like:/c/Users/smithj/AppData/Local/Programs/Python/Python3XX/python -m venv venv
Then we activate the virtual environment so all our required "expansion packs" or dependencies will be installed in our little bubble:
Mac: source venv/bin/activate
Windows: (might need) Set-ExecutionPolicy Unrestricted -Scope Process
.\venv\Scripts\activate
Windows (using bash instead of default Powershell): source venv/Scripts/activate
If you've got a happy little (venv)
before your terminal prompt, you're ready to run:
pip install -r requirements.txt
Did one of the dependencies listed in requirements.txt
fail to install correctly? It's a common problem that must be solved. uWSGI doesn't need to be installed in the development environment so you can #comment
that line out. If psycopg2 is failing to install, you can comment that out and manually install the binary alternative, pip install psycopg2-binary
. Running pip install wheel
may also resolve many of the installation issues.
You're likely going to end up with the wrong version of Flask-Security. So next run:
pip uninstall flask-security
pip uninstall flask-security-too
pip install flask-security-too
After running flask run
in VS Code, you should be able to visit http://127.0.0.1:5000 to see your website.
This is important! Pity the poor programmers that forget to set up their migration tools. Once Flaskinni is up and running the first time, run flask db init
to allow Flask-Migrate to help with any future changes to your models. We'll talk about why that's super important later.
Help! I don't know how to configure Replit's database service with SQLAlchemy. Their technical support doesn't know how to do it. They point me to the forums... and those folks can't crack it, either.
I need to study up on Docker. These are notes that I'll use to redo this section later. Trying new stuff is important, even if you're not moving it into your stack. Docker represents a booming growth in containers, and that's something serious web dev folks need to deploy at scale.
Make sure Docker is installed, running, and logged in.
Clone Flaskinni
git clone http://github.com/dadiletta/flaskinni
Edit the Dockerfile
with environmental variables
docker-compose up --build
You're going to get stuck... a lot. This is where you can distinguish yourself as a programmer. Every problem big and small you hack your way through makes you more legit. So enjoy the grind. It's important to read around the problem and not just through it. Sloppy copying from StackOverflow once you copy and paste the error into Google can get you in trouble. Get background research done to understand some of the bigger concepts. Be willing to reach out for help, but respect that other people are grinding away too. Always show evidence of your research when asking for help as it will build trust with your support network.
Produce a full-stack web application in Python's Flask framework. While this is difficult and complex, it'll be a rewarding challenge.
This section of 's Computer Science Department's GitBook is also the official documentation of the . If you would like to skip the background information about web applications, you can proceed straight to .
Web Development is my favorite area of Computer Science to study. Programming at the hub of all information gives you a bird’s eye view of how business operations fit together. If an organization has mobile apps, websites, and some sort of critical information for their business, then web developers are the people holding systems together. There's so much happening in this field, too. In fact, we've got to be careful that all this cool tech doesn't overwhelm you.
Pro-level challenge
Little kids like to keep asking, “Why?”
A thread of inquiry can always get more detailed. It never stops. You can keep digging deeper. Sooner or later we just accept the idea of something and stop asking questions. For example, I know hardly any of the electrical engineering involved to build a stick of RAM but I would still claim I know what RAM is. I’ve just accepted that there’s a thing called RAM and it works like so and I’m okay not knowing any more details than that for right now.
We are going to narrow our focus to building a Python Flask app using templates and a pre-built starting point. We can build really cool things but it means that we’re going to brush over big concepts that are totally worth studying. Sometimes it’s hard to feel like you understand something if you can’t take the time to closely examine all of the pieces and principles involved. Write down questions, don’t stifle your curiosity, but be patient as we setup lots of abstract ideas that we won’t be able to satisfactorily investigate for a while. TLDR: Be patient and keep a running list of concepts and questions to research later.
Guided Training: Do your homework! Actually grind out the projects in tutorials. Learn the rules of new languages.
Publishing: How do we get our Flask app online?
Books at give superpowers
In the last section, you learned there's a lot of layers to a stack. But even within our stack's application layer, there's a lot of complexity. If you don't keep organized, your code quickly gets overwhelming and difficult for other people to understand if you need help. But we find that we can sort-of split our code into three areas, 1) code that stores stuff like user data, 2) "logic" code, or rather the stuff that loads data executes actions like making a sale, and 3) the HTML visuals we see when we interact with the app. This pattern was originally called MVC. We use a slight twist on that called MVT.
I can describe the rationale for the MVT design pattern.
Model: Database schema or rather, what gets stored in memory. But we won't have to learn a database language like SQL just yet. We'll have a tool called an ORM to convert Python into SQL for us. We'll use that to setup our SQL database tables for each object
View: Routes internet traffic. Here's where we connect the /url/someone/typed/
to the Python thinking that will respond to request for that certain webpage. The view is our controller. It's our application logic--our central brain.
Template: HTML with bits of {{ python }}
. It's not just a regular HTML page. Python will render this so we can respond to different conditions. For example, if a user is logged in we can so the "Logout" button but if not, we show the "Login" button. Careful though, avoid putting too much logic here.
The model (M) is a model or representation of your data. It’s not the actual data, but an interface to the data. The model allows you to pull data from your database without knowing the intricacies of the underlying database. The model usually also provides an abstraction layer with your database, so that you can use the same model with multiple databases.
The view (V) is what you see. It’s the presentation layer for your model. On your computer,the view is what you see in the browser for a Web app, or the UI for a desktop app. The view also provides an interface to collect user input. In our MVT pattern, this becomes T. So MVT and MVC both use the term "view" but for different parents of the same triangle. This seems needlessly cruel to those studying this stuff.
The controller (C) controls the flow of information between the model and the view. It uses programmed logic to decide what information is pulled from the database via the model and what information is passed to the view. It also gets information from the user via the view and implements business logic: either by changing the view, or modifying data through the model, or both. In our MVT pattern, this is the V and will be found in our views.py
file.
If I launched flask shell
I could talk with Python while flask is running app
and I could ask app.models
for all the objects we use around our code. Like app.models.User
. That would be the schema. It's not an actual user that I'm referring to when I say app.models.User
. That's the definition, the skeleton or the schema. The individual records in the User
table will used for the instantiated objects in my code.
Schema is more than just the list of properties (like first_name
and such) and functions of an object in your app. It also describes how objects are connected in your database.
There's more: Instead of just connecting two objects, what if we wanted to qualify that relationship? Not only do you want to say "this user belongs to this club," but you also want to mark down that she's the president of the club. So now we have a Membership object that can have all sorts of properties that describe your role on the club and what you're allowed to do or not do. Association objects are super cool.
book_list = new List(); sql = "SELECT book FROM library WHERE author = 'Linus'"; data = query(sql); while (row = data.next()) { book = new Book(); book.setAuthor(row.get('author'); book_list.add(book); }
With an ORM library, it would look like this:
book_list = BookTable.query(author="Linus");
The mechanical part is taken care of automatically via the ORM library.
Questions
So object-relational mapping is a programming technique for manipulating data?
Yes, it’s the tool (ours is called SQLALchemy) that keeps us from having to write many SQL commands of our own.
There's no reason to write every page used in your app on separate html files. Templating allows us to extend or start from a base file that has all the nav bar and footer stuff we need. This is a type of inheritance and it's pretty neat.
Static assets are your images and CSS files and other stuff that doesn't get run like code and have to get served up to your users. We'll find ways of making this process go fast.
Slow down. Get your head around these ideas before we lean into the code. Being able to come back and reference these terms as they come up will help you put the whole puzzle together.
I can describe a full-stack application and the tools required to build one using relevant vocabulary.
A stack is all the systems used to run an app. Usually, several computers are involved but that's not a must. Let's look at the various layers in a stack...
Let's understand the layers by discussing the programming languages used in each.
... but how do we get this HTML / CSS / JS on our client computer?
Okay, we've got a web server receiving signals from our client's computer. Now comes the part where our server runs the app we've built and gives us cool information.
Imagine two people watching a movie at the same time. Because those two people have different life experiences, they will interpret the movie in a different way. When your app is running, it loads variables and libraries that gives it a particular “experience.” Our application context refers to the references at play.
A module is a loose term. Python uses the term to describe a single file, sometimes just one part of a larger library of tools that you can import and use within your app. If you put a single line of code in a file, you’ve built a module.
Virtual environment does not include “your app” this is separate. And you may have meant modules, not models. The model refers to the objects and database tables we’ll use in our app. Meanwhile, the libraries or modules that our app depends on in order to run will be installed in our virtual environment.
An efficient programmer keeps their dependencies in a virtualenv, but it’s not required to do so. You can install them globally if you’d like, but other apps running on that machine might complicate things. There are other ways to manage dependencies too.
Throughout the course of the semester how often will we be referring back to older versions of our app?
In-line comments are written with a # and add extra notes around our app. ‘’’DocString’’’ comments provide more detailed explanations right underneath class and function headers.
Where are you going to do your coding? If you try to run your app, what other software is required? How are you going to save or publish your work? Configuring your , , and is essentially your workspace.
I can create and view a blank Flask app.
Before we get into the structure and mechanics of our code, let’s build the most basic of Flask apps. It’ll help set some context as we then start to learn particular skills. It’s important that you start from scratch as it builds confidence knowing you can start from the ground-up.
Let's look at the most simple possible Flask app.
In case Repl.it isn't cooperating with your browser, here's a simple view of a basic "Hello Flask" app.
If I go to /hello/george
, can you make the screen say, "Hello, George?" How do we pull a variable from the URL on that GET request?
Build another route and switch between two pages.
Use render_template
If you can understand some of the elements that are missing from this simple example, you’ll have a greater appreciation for the core of our Flask app and the many components that we’re about to study.
Our initial application, hello flask, had one singular route @app.route('/')
which is very basic. Just a homepage, that’s it. On the other side, “Flaskinni” includes numerous routes so you see blog and account pages just to name a few. Each route in Flaskinni calls templates with method calls like render_template('index.html')
. These are just as their name suggests, templates or outlines of the final HTML page a user sees. Templates are a big deal (⅓ of our whole MVT structure).
In the Hello Flask application, there is no database or model schema being used. There are no objects like user, admin, blog post in the app. Also in the Hello Flask app, we had no database, but in Flaskinni there is a database, and a schema that shows how the database will be set up. Also in Flaskinni there is code that creates database tables and is able to send the data to the database in the format laid out by the schema.
Our initial Hello Flask application had no interactivity whatsoever as illustrated by the one simple message that is sent to the user. Our app only responds to GET requests, never a POST request. In other words, the user is only getting static information and is never sending information back to the server or requesting more specific information. For example in the Flaskinni application a user can post a blog post or can request or a certain blog post.
Libraries are expansion packs, they're files containing compiled code that allow the app to reference them later in other files. Libraries allow the app the run faster and have more capabilities. Instead of calling methods over and over while writing the app, the user can call the library file. The linking of libraries allows a file to gain the capabilities of the library module without having to define those methods again.
Want to jump in with both feet and go hard on the research? See if you can get your head around the growing change from to . What are those and why is there a change happening? Don't sweat it if YouTube videos and articles go right over your head. It's good to start dabbling and exposing yourself to top-level discussion.
(Python)
There are countless ways to organize the files and code used in an application. How does one choose? How do you plan out the parts of your app? There’s big advantages to following best practices, using a pattern that others can recognize. You may hear people references the Gang of Four (GoF) when referring to . MVC is one such pattern, but for reasons I'm still figuring out, Flask uses a conflicting acronym for remarkably similar pattern.
(We will be using a modification of this pattern called MVT)
: Communication diagrams model the interactions between objects in sequence. They describe both the static structure and the dynamic behavior of a system.
: table that associates two other tables in a many-to-many relationship. Let's say you make a website to manage school clubs. Students can be in many different clubs and clubs can have many different students. Somewhere in our database we need to write down a connection between each Student.id
and each Club.id
. It's the list of connections between two objects. You want to leave the club? Remove the record that links the two id
's.
: a technique that lets you query and manipulate data from a database using an object-oriented paradigm. When talking about ORM, most people are referring to a library that implements the Object-Relational Mapping technique, hence the phrase "an ORM". An ORM library is a completely ordinary library written in your language of choice that encapsulates the code needed to manipulate the data, so you don't use SQL anymore; you interact directly with an object in the same language you're using. For example, here is a completely imaginary case with a pseudo language: You have a book class, you want to retrieve all the books of which the author is "Linus". Manually, you would do something like that:
: a method of associating user-defined Python classes with database tables, and instances of those classes (objects) with rows in their corresponding tables.
: the process of transferring data between computer storage types or file formats. If we ever want to change our SQL tables to add new information to every record, we’ll need to migrate the data from the old table to the new table. We’ll use a tool called Alembic to do this.
: moving data from source to destination. Our Flask controller will take requests to, for example, yourwebsite/home
and match it to the code that builds the home page
: Session is the time interval when a client logs into a server and logs out of it. The data, which is needed to be held across this session, is stored in a temporary directory on the server.
: generating HTML code from a mix of Python and HTML, this is done in Flask using Jinja2.
: a template engine for the Python programming language. It’s the software that takes the mix of HTML and Python and renders it down to just HTML which is then sent to the user.
: Web stack contains an operating system (OS), a programming language, database software and a Web server. A full-stack developer is someone capable of building an app or solution that addresses each of these components.
This is what you see on your page. HyperText Markup Language, gives content structure and meaning by defining that content as, for example, headings, paragraphs, or images. CSS, or Cascading Style Sheets, is a presentation language created to style the appearance of content—using, for example, fonts or colors.
is a programming language commonly used in web development. It was originally developed by Netscape as a means to add dynamic and interactive elements to websites. It used to be used solely for client-side purposes, but now servers are running apps build using NodeJS. JavaScript has nothing to do with Java.
: the message system that runs the World Wide Web. This is how website information is sent over the Internet. There are many different types of HTTP requests, including GET and POST, one asks for information from the server and the other submits information to the server.
: In computing, a shell is a user interface for access to an operating system's services. In general, operating system shells use either a command-line interface (CLI) or graphical user interface (GUI). CLI is used to communicate to the shell in the form of text input.
(Secure Sockets Layer) is the standard security technology for establishing an encrypted link between a web server and a browser. This link ensures that all data passed between the web server and browsers remain private and integral.
: An Operating System provides services to both the users and to the programs. It provides programs an environment to execute. It provides users the services to execute the programs in a convenient manner.
: Python is a high-level programming language designed to be easy to read and simple to implement. It is open source, which means it is free to use, even for commercial applications. Python can run on Mac, Windows, and Unix systems and has also been ported to Java and .NET virtual machines. Most Python distributions rely on CPython, which means your code will boil down and run using the C language. Flask is a Python library.
Framework is described as “an abstraction, in which software providing generic functionality can be selectively changed by additional user-written code, thus providing application-specific software, is a software framework that is designed to support the development of web applications including web services, web resources, and web APIs. Web frameworks provide a standard way to build and deploy web applications. Web frameworks aim to automate the overhead associated with common activities performed in web development. For example, many web frameworks provide libraries for database access, templating frameworks, and session management, and they often promote code reuse. (additional )
Structured Query Language, used to request information from a database. SQL has been the favorite query language for database management systems running on and . Increasingly, however, SQL is being by PC database systems because it supports (databases that are spread out over several ). This enables several on a to the same database simultaneously.
: is an (ORDBMS). As a database server, its primary functions are to store data securely and return that data in response to requests from other software applications.
: a computer program that directly executes, i.e. performs, instructions written in a programming or scripting language, without requiring them previously to have been compiled into a machine language program.
: One of the design ideas behind Flask is that there are two different “states” in which code is executed. The application setup state in which the application implicitly is on the module level and request handling.
: encapsulates code and data to implement a particular functionality, has an interface that lets clients to access its functionality in an uniform manner, is easily pluggable with another module that expects its interface, is usually packaged in a single unit so that it can be easily deployed.
: A folder where a copy of all dependencies is kept separate from the system installation. This allows you to work on several apps without having to manually toggle which version of the language interpreter your system is using. It's a safe and responsible way to develop your apps.
: “a collection of implementations of behavior, written in terms of a language, that has a well-defined interface by which the behavior is invoked.”
: A dependency is a file that something you are trying to install requires. These are the required libraries and modules for your app to function.
: is a system for tracking changes in computer files and coordinating work on those files among multiple people. Version control is a system that records changes to a file or set of files over time so that you can recall specific versions later.
: An item in memory with a variable name, location reference, and the instantiated code provided by some class definition. Objects have individuality, and multiple names (in multiple scopes) can be bound to the same object. This is known as aliasing in other languages. This is usually not appreciated on a first glance at Python, and can be safely ignored when dealing with immutable basic types (numbers, strings, tuples).
A method is a function that “belongs to” an object. (In Python, the term method is not unique to class instances: other object types can have methods as well. For example, list objects have methods called append, insert, remove, sort, and so on. However, in the following discussion, we’ll use the term method exclusively to mean methods of class instance objects, unless explicitly stated otherwise.)
In almost all programming languages, functions accept variables that are used in their code, (i.e. f(x) = x + 1). The parameter is simply the variables that are referenced within a method or behavior. This can also be referred to as an argument. A Python module which can contain submodules or recursively, subpackages. Technically, a package is a Python module with an __path__
attribute. parameter. A named entity in a function (or method) definition that specifies an argument (or in some cases, arguments) that the function can accept.
: In class-based object-oriented programming, a constructor (abbreviation: ctor) is a special type of subroutine called to create an object. It prepares the new object for use, often accepting arguments that the constructor uses to set required member variables.
: Inheritance is a feature that represents the "is a" relationship between different classes. Inheritance allows a class to have the same behavior as another class and extend or tailor that behavior to provide special action for specific needs.
: A string literal specified in source code that is used, like a comment, to document a specific segment of code.
Want to know the difference between ‘GET’ and ‘POST’? You see them mentioned as a on line 16 in the picture below? Well, you should know the name Tim Berners Lee. GET and POST are two of the HTTP requests that travel over our network and provide us the Internet. Simply put, GET is a request for a page and POST is when the user is submitting a form. Knowing the types of HTTP requests gets really important if you ever decide to use to use this web app to power mobile apps, too.
If you don't start visualizing things before you're knee-deep in code, your product will lack a cohesive visual style and an intuitive workflow. Building an app starts with colors, logos and most importantly, wireframes.
I can develop a brand identify for my product including logos, color pallets, fonts, and tone of voice.
I can outline the workflow of my app in a wireframe.
Setup a local folder using something like Google Drive to collaborate with your team. Download a theme. Start a PowerPoint or Google Slides document to take notes, build a scrapbook of visual designs that can help you shape the message you’re trying to send.
Rather than design our own HTML layout and polish the finer details and effects, we’re going to use a theme. We’ll look at paid themes and free themes. You must make sure your theme is based on Bootstrap, preferably the most recent version. You want to make sure that the theme has a variety of elements and layouts that will allow you to mockup pages quickly.
For rapid prototyping, don't be afraid of using Flaskinni's default theme. Proving your app concept with a pleasant, neutral design is smart.
Never make changes to theme.css, style.css or whatever your file is called that governs the primary rules of your theme. We will override the rules using different files. That way we can more easily upgrade the theme in the future. The custom.css
file (that hopefully you're using Sass to produce) in our <head>
after the theme’s CSS. That way, our rules will overwrite the theme’s. We’ll have the final say.
Implementing a new theme is tricky business. You'll have to rebuild your static assets and modify all the templates. The base.html file will need the most amount of work as it will need to reflect We talk about that more next chapter.
Building your app, your team, and your company requires a lot of drive. A brand identity is a flag on a battlefield for your soldiers to rally.
Go to the websites of some major brand names you know and look at the colors used. If you did deep enough, you'll find a variety of button colors, but most things follow a pretty consistent pattern. It's time to set up such a pattern inside our CSS.
http://coolors.co These palettes can help you color your logo
https://color.adobe.com/create/color-wheel/ expand the 5 colors you get from coolors
https://colors.eva.design/ Eva will help you fill in any gaps on the standard Bootstrap colors (primary, success, info, warning, danger)
http://designmodo.github.io/Flat-UI/ When in doubt, use Flat design
Hopefully you have a _variables.scss
file where you can drop all your color palette. Many themes include these assets. Flaskinni's default theme comes from startbootstrap so you can take advantage of the Sass structure to quickly implement your colors.
If you're using SourceLair, you may need to upgrade Sass so it can handle recent Bootstrap templates. So first run npm install -g sass
so you can then run:
sass app/static/scss/custom.scss:app/static/css/custom.min.css
The code below are example MacOS settings for the Live Sass Compiler extension for VS Code.
You'll need a header and a body font at least. Sometimes a logo font is used as the headers, sometimes not. You may want to pick out your logo first and then find complementary fonts afterwards.
Start sketching ideas on your branding document. It can be very powerful to have a logo designed early in project development as it sets styles, colors and gives you something to reference when discussing your project.
Shutterstock.com -- start building collections of images you might want to use
Add images to your branding document. Scrapbook images that you don’t intend or are unable to buy and use but speak to the type of look and feel you want (or want to avoid). Have a different section for images that you may want to purchase and use later on. Free images you can start to download and organize into your team’s project folder. Paid images you can start to save in bookmarks, links on your slides, or in other ways.
The wire-framing that needs to be added to your branding document is essentially just shapes illustrating what your app can do. You could use Google Slides in a real hurry. Ideally though, you should use the wire-framing process not only to determine all the steps your users will need to take, but also how you'll organize the interface. You're making UI decisions as well as UX.
I try to start by first looking through the pages that come with my HTML theme and see what sort of layout, widgets and objects are readily accessible. Keep them in mind when designing your wire-frames. After this early phase, we will be building full HTML mockups to illustrate these wire-frames.
Building HTML mockups is much, much slower than Adobe XD. You ought to sketch out your apps before you code HTML elements. But designing the HTML elements using the theme assets you'll have in production takes you from planning the outline of the user experience (UX) to the mechanics of the actual interface (UI).
Before you advance, be sure you’re making steady progress through the Flask Udemy course (and getting help when stuck)
I can describe the MVT components of Flaskinni.
I can describe the thread's steps as my app starts up.
Remember, you can help add comments and docstrings to Flaskinni and submit pull requests. Even beginners can help contribute to open source projects in surprisingly substantial ways.
We've got a handy little method that instantiates our app, loads the settings, and straps on all its expansion packs. Let's start our tour of the code where Flask is spawned. From "Demystifying Flask’s Application Factory":
The reason why the Application Factory is so important has to do with something called Flask's Application Context. Our app's "context" is what takes the assortment of Python files and modules which make up our app and brings them together so that they see and work with one another.
When your app is serving hundreds or thousands of people at a time, your server will run many instances of your app. You may also run your app in different modes, like a text-only shell. An application factory addresses this need by spitting out instances of app
Flaskinni comes with a main
and an api
blueprint. That'll affect your use of url_for
. So if you wanted to make a link to the homepage, it'd be <a href="{{ url_for('main.index') }}">home</a>
Now that Flaskinni is running in your environment, local or cloud-based, let's take a tour.
The T part of our MVT all starts with base.html
. See how much of the documentation you can read before your brain wimps out
The purpose of the base template is to give all the pages in your app common assets. This such as fonts, CSS files, nav bar. Every page must link to the base file. It is kept in the /templates
folder, as base.html
. The base template is like a picture frame, loading common elements like the nav bar, footer, and your little favicon.
This is the whole parent-child thing. The parent is the skeleton of your page. We named it base.html and it has <link>
s to our Google Fonts, CSS files, and sets up nav bars and any other element that’s site-wide. It’s great! Pretty much sets up the whole theme of our site.
To put our pages inside this metaphorical picture frame, we use the command, {% extends "base.html" %}
at the top of every other HTML we put in our templates folder.
The base template extends across all pages, so the website can share HTML code.
We’re going to make a new template that inherits from our base.html so you can experiment with this handy tool. Create a new file in your templates folder called about.html. This page will need hardly any information at all because all the setup is done in the parent. All we need to do is pass some HTML into any block.
Sass makes CSS easier, even if you have to spend a few minutes here and there refreshing yourself on how to use the Sass tricks and how to compile your Sass down to CSS. I personally use a VSCode extension to manage this automatically.
Don't want to learn? There is a lazy way out and that's to edit your CSS directly. No judgments.
Pick out a header and a body font at fonts.google.com
Add them to your collection and get the <link> we’ll use to embed a connection to Google Fonts.
Replace the other <link> to fonts.google.com that was in your base.html file
Add your CSS code to custom.css, something like:
Launch your server
(make sure you’ve got venv activated) source venv/bin/activate
or on Windows: source venv/Scripts/Activate
(use our flask-script to run the server) flask run
Check out your font changes!
If you want to see the new template file in action, we’ve got to build a route to that page. As of this writing, there are only two locations for routes in Flaskinni, the master __init__.py
file and the views.py
file inside the blog module folder. Since our homepage route is in the first file, we’ll put our about route there, too.
We later passed a variable to the template. We dropped <h1> {{ some_variable }} </h1>
in our about.html
file. Nothing shows up until we change the render_template call to something like this:
Congratulations! You just passed your first variable to a template.
We have cool, color-changing notifications in Flaskinni that rely on Bootstrap classes. So if you want to send a good alert message that something worked, you'd say:
flash("Your message has been sent!", "success")
But if something failed, you'd write:
flash("Your message was destroyed by mistake. Whoops!", "danger")
What other Flash notifications are there? How are the flash notifications being built? Let's look at where they come up in the base.html file, trace back the macro that builds the flash messages and then see what other options come with Flaskinni.
Cookies!
Let's talk about how this blog post is queried from our database:
Check out line #20.
Publish your Flask app to a web server. This is a challenging process often with unique challenges for every app. We'll get there.
We’re going to use Digital Ocean to host our app. I also considered Heroku. If we were better with Docker, I’d also consider using Azure or Google Cloud. So don’t be afraid to look around at other options besides the stuff I spell out here. You really can figure this stuff on your own and chart a different path if you're willing to grind it out
Once you get your venv activated, don't forget pip install --upgrade pip wheel
If admin rights are needed, you may need a command like this:
sudo -H /home/myuser/venv/bin/python -m pip install -r requirements.txt
My wsgi.py file:
from myapp import app
if __name__ == "__main__":
app.run(host='0.0.0.0')
There are many critical files in this process, but the one that ties them all together is:
sudo nano /etc/systemd/system/flaskinni.service
I use sudo cat /var/log/syslog
frequently to see the errors being reported by the uWSGI service
and use sudo less /var/log/nginx/error.log
to see the errors just from nginx (they'll otherwise be mixed in with the syslog)
If everything is working up to this point, your project will load a 500 error. Track down the error and it should be reporting that the connection to the database has failed.
sudo nano /etc/nginx/sites-available/myproject
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
Postgres starts with a super user with the somewhat unoriginal name of postgres. You can use your admin powers to switch to that user by typing sudo -iu postgres
and now you can use psql
and you'll have full control to setup a new user. Read up on how to add a new user in psql. The lazy, slightly dangerous way is to createuser -P -s -e user_name
Once you've created your user in psql, update your .env
file with the user and password.
We've got to test to make sure your database user can log into the database you've created. If your database user also exists in Linux, you can do the same sudo -iu
trick we did before and then open up psql
. This command will allow you to be more specific:
psql user_name -h 127.0.0.1 -d db_name
You may end up using ALTER USER user_name WITH PASSWORD 'new_password';
from the postgres user.
Change the passwords and hash codes used in .env
and remember that changes to secret keys or salt could break passwords currently saved in your database. For random strings to use as secret keys for apps, use a line of code like this to make one:
Practice deploying updates. Add, commit, and push from your development environment and pulling over SSH. Make a change to the database and use migrations to update your models without losing data.
Making changes to your application
After building a cool new feature on Cloud9
git add .
git commit -m “fixed the thing”
git push origin master
Then SSH to your server, navigate to your folder and git pull origin master
During this phase of your project, you can implement a new cosmetic layer. This will help setup the visual tone of your project while buying us some more time while we learn fundamentals. We will also add a new folder inside app/
that will store your routes
I can implement a new HTML theme into a web app's base template.
I can create my own blueprint and prepare to expand my database schema.
We’ve got to build our base.html. That one file is the frame to our whole app. It’s a key HTML file in the T of our MVT. We’ll need to carefully setup the <head>
’s attached files, the <body>
and any wrapper/container structure your theme might be using, the <nav>
bar, the {% block container %}
where all other pages will be inserted, and your footer.
Pro Tip: Sometimes it's nice to have more than one base.html, if say, you have areas of your site that look dramatically different than others. I sometimes have marketing_base.html for my front page and a base.html with all the controls a user has when logged in.
Your theme, whether you got it for free or paid for it, will have a pattern to how it organizes the HTML each page (some themes use a series of containers, others <section>
s, for example). Implementing a theme is about transferring static assets (like images and files) and separating the parts of your HTML code that are common on every page (and putting that in the base.html) and what is unique to the individual page (and putting that in individual template files).
Figure out where all of these messages are listed in their container. Replace the stock objects, (probably will be li
elements) and that will be generated instead by this line: {% include "security/_messages.html" %}
Note: When an HTML file is unable to stand up on its own because it's just a partial element, we put an underscore and the start of its filename.
Here's a demonstration showing the implementation of Flaskinni's old theme.
The different parts of your app should be kept in separate sections or blueprints. It'll make it easier to take one cool blog feature from one site and add it to another project later on. It also keeps your code more organized and easier to work on.
The stuff we have to add to create a new blueprint can be divided up into the MVT (which I'll address in reverse). But first, do you know the name of your blueprint? It should be an easy shorthand because you'll be typing it a lot like so: {{ url_for('why_is_my_blueprint_name_so_long.dashboard') }}
This example uses a blueprint named "project" which is a pretty lame name. Hopefully you can do better.
Inside the templates/
folder, create a new folder with your blueprint's name. I almost always use a _cards.html
full of macros ready to build cards for all sorts of objects in my app. Might as well add that now, too. For all the new pages you add to your app, you should use use a blank_page.html that you can copy and paste then rename.
Create a new folder within the app/
folder. Like always, spaces and capitals are a bad idea in folder names. Inside that folder create an __init__.py
file. In the file, you'll need to customize this code for a folder name unoriginally titled project/
:
We keep a separate folder for our models. I typically have quite a few files. We'll talk more about building your schema next chapter. For now, know that any new classes you make need to be imported in the __init__.py
file. That keeps our imports more organized.
When our app factory in app/__init__.py
puts together an instance of our software, it registers our blueprints and imports our models. The app factory is the knot that holds everything together. So the final step is to register our blueprint there. You're now ready to start taking Flaskinni's application logic in a whole new direction.
The right way to handle this situation is discussed in the next section. Let’s look at the lazy, dangerous way of keeping your database up-to-date through gross destruction. DANGER: This will destroy all saved user data. You have a sacred mission to keep this safe and private. This practice is only tolerable at this very early stage of development when we’re learning how to form effective and efficient database schemas. So if you can say to yourself, “who cares? There’s no data here and never has been,” then this might be the right way to update your database.
Check private.py
for the name of the database being used in our app: BLOG_DATABASE_NAME. In this example, it’s called, “db”.
psql
\l
drop database db;
\l
create database db;
\q
Once your database has been configured and your tables all have columns, making changes is tough. Sure, rows (aka “records”) can be added and deleted without any major problem. But changing the schema so that an object, or table, has new properties (columns in your tables) is much more difficult. Changing the columns in your database tables is a delicate process. Fortunately there are tools like Flask-Migrate to help migrate the data from one version of the table to the next.
If you do it to one, you've got to do it to them all
Typically, we don’t work on just one database at a time. Most projects have a staging version and a production version and both have their own databases. If you make a change to one, you'll have to migrate the other. That’s why we have Flask-Migrate! Don’t start this process until your teacher has told you your database schema is largely stabilized, (this should happen at the end of the next section of this guide).
Getting started:
flask db init
-- this command you'll only do the first time
flask db migrate
-- this command detects any changes and builds a migration strategy to change your database
flask db upgrade
-- this command executes the migration
From here on out, your project is going to vary from everyone else’s. Once your models are done, you’ve now got to build out each view and template that will serve the workflow of your . Work with your teacher to identify what your MVP needs to do, (we’ll call this your requirements based off of the ). Once we work out what exactly you’re building in your module, we’ll populate your Trello backlog with loads of tasks. And as we solve those weird tasks, we’ll start to build the collection of topics below.
I can research and hack together an MVP.
When filling out a form, you may want to have a drop-down of a user's friends or some other set of data unique to that user. How can you provide those dynamic options within a form template?
And what if you want one drop-down to populate the options of another dropdown?
Just use a SelectField
with no real options and populate them after you build the form.
Examples:
Two back_populates equals one backref. Using backref declares a two-way relationship. It’s more efficient than dropping a back_populates on both ends of the relationship but I prefer it because I’ve been confused too many times staring at a class wondering about its relationships unaware that another class has declared a relationship backref in a different file.
This is a really useful skill we should go over as it helps us test and figure out where things go wrong.
flask shell
if python just said it doesn't know what that is, then you need this line:
from extensions import db
from user.models import User
my_users = User.query.all()
look at your user(s):
my_users
my_users[0].email
my_users[0].first_name
Let's make sure we can login directly to our database. You can skip this step if you're, say, in the midst of a hackathon, the app is working, and you've got to keep moving. In the long-run, it's critical you know how to flex control over your database directly.
If you're using Terminal, bash or PowerShell, you should be able to type psql
to open a command-line version of PostgreSQL. You can also use a friendlier interface like pgAdmin, though I recommend making the effort to explore both. You'll need to specify your user when accessing psql. Specifying your user can vary a lot depending on how you approach it. Good thing you know how to Google.
Linux:
sudo service postgresql start
psql
(try listing the current databases) \l
(if you need to quit) \q
If you’re the superuser using sudo -i
then you’ll be on the root account (don’t do that). Postgres has a built-in admin you can log into with su - postgres
and then psql
(you shouldn’t need that but it’s useful).
You can edit accounts' psql access and credentials with stuff like:
ALTER ROLE ubuntu WITH PASSWORD 'ubuntu';
You probably won’t need this very often, but it’s important to know if you want to understand how your app works. Launch psql
and be very careful as you tiptoe through our database:
(connect to our database, which in this example is named “db”) \c db
(check out the tables in our database) \dt
(see what we’ve got in our post table) SELECT * FROM post;
If there are no posts, we’re going to create the first one, which will have the ID of zero. If there are posts already, we’re going to create one with the next highest number.
INSERT INTO post (id, user_id, title, subtitle, body, slug, live) VALUES (0, 0, “Some title”, “Some subtitle”, “Some body”, “someslug”, True);
(let’s quit psql) \q
DELETE FROM post WHERE id=0;
(make sure it’s gone) SELECT * FROM post;
This line needs to be in your settings.py:
SECURITY_EMAIL_SENDER = private.ADMIN_EMAIL
Just as we keep a custom.css file, your project should have a custom.js function. Something like this could be very handy. Now you can just add class=”confirmation” attribute to any <a></a> and it’ll have a JS-powered confirmation window.
Actions of our app are triggered by routes in our view. If you type in the url of your site, /index,
your browser sends a GET request to that route to the homepage route in your app. Your browser loads the page. But what if you want to avoid refreshing the page? What if you want to send a message from a modal window and press submit without losing your spot on the current page?
<a onclick="hidePaidBills()" href="javascript:void(0);" data-toggle="tooltip" data-placement="top" title="hide paid"><i class="fa fa-eye"></i></a>
Update all libraries (copied from StackOverflow)
sudo -H python3 -m pip freeze --local | grep -v '^-e' | cut -d = -f 1 | xargs -n1 sudo python3 -m pip install -U
If you don't want to overdo it with the sudo nonsense: pip freeze --local | grep -v '^-e' | cut -d = -f 1 | xargs -n1 pip install -U
Create a requirements document:
pip freeze > requirements.txt
Test to make sure the app works. If it doesn't, undo changes tracked by git to get you your previous version of the requirements.txt
. Reinstall your dependencies based on all the previously recorded versions.
Enable the support of the Google-style docstrings which are much easier to read:
The most responsible way to build software is to start with unit tests. A script will mimic various types of users as they test every function on your site. The unit test will report when something acts differently than expected. I struggle with keeping to this discipline. A more sophisticated implementation of Flask’s unit test system will be the best sign of my own professional growth in this area.
By now you should have created your module or blueprint’s folder in your project’s directory and another in your templates. Now, we'll talk about what we should add into the models/ folder
I can create an ERD/UML to describe the data that will be stored in my app.
I can write new relational database objects and successfully stand up my database.
Here's a semi-accurate diagram of Flaskinni's starting objects. Make a copy of this document and share it with your team. Compare your UML's and your wireframes, to make sure all the data you need in your app is stored in a logical hierarchy.
Fipplr allows businesses to log work, manage invoices, and accept payment. This set of tools can be used by freelancers and employers. Fipplr works similarly to many other accounting tools but its simplicity and guided structure protects young entrepreneurs.
Invoice Count:
Invoice.query.count()
len(Invoice.query.all())
Count how many invoices have been submitted system-wide
Paid/Unpaid:
Invoice.query.filter(Invoice.date_paid != None).all()
Check to see if an invoice has been officially paid. This will be a simple boolean check to see if it has been paid or not. Eventually, you will be able to filter paid and unpaid but to begin, it will just be paid.
Project List:
Project.query.join(Project_User).filter(Project_User.user_id==current_user.id).all()
Print the list of all your current working (live) projects. For employers, this list would include the project name and who is assigned to it. For freelancers, it will list all the projects you are assigned to.
Client/Employer List:
[Function name]
Find the full list of your clients. For employers, each client would be your subcontractors. For freelancers it will list all the clients that have hired you.
Company List:
Company.query.join(Company_User).filter(Company_User.user_id==current_user.id).all()
All companies a user is connected to.
Invoiced Work Check:
Query: [Function name]
Find the full list of work officially invoiced (submitted). If work is not invoiced pull up a separate list. In total there will be two lists, one for the officially invoiced (submitted) work and another for the unofficially invoiced (submitted) work.
Star Sight is a collaborative story editor with a growing array of tools to help writers. You can control access to your work, track your characters, and roll dice to help make decisions. Stories also support rich media so your work can stand out.
Database architecture, the way we build and connect elements in an app, often goes unappreciated by the average user. It’s a complex software engineering challenge that’s unique to every problem being solved. In this example we have some of the following relationships:
Story_Chapter
User_Story: A user has its own attributes (First and last name, email, and ID). A story also has its own attributes (A series it belongs to, and its own ID). In order to connect these two things, a helper table is created and used by pairing the ID of the user and the story it’s associated with.Its an additional object that connects to the two. It told to, it also gives the user permission to give other users access to a particular story.
Story.query.join(Story_User).filter(User.id==current_user.id).all()
All stories the current user has
Chapter.query.join(Character_Story).filter(Character.id==x.id).all()
All chapters that have a certain character
Series.query.join(Story).join(Story_User).filter(User.id==1).all()
All series that the current user has
User.query.join(Story_User)).all()
All users that have stories linked in the Story_User join table
User.query.except_(User.query.join(Story_User)).all()
All users that don’t have stories
Overhaul Repair is an app that allows users to sign up to request a mail-in phone repair service. This web app will allow users to create accounts to monitor their device status and also add their devices into the account, allowing users to easily create repair orders from previously added devices. The app will also include an admin only finance management system.
Query: Task.query.filter(Task.date_completed==None)
Explanation: Query searching through all phones that have unsolved open issues
Query: Task.query.order_by(Task.price)
Explanation: Order all tasks by price
Query:
Explanation: All phones that have completed repairs
Query: Device.query.filter(device. odel_number.contains(‘A1’))
Explanation:
Query: Message.query.filter(Message.user_id.contains('Robert Hayek'))
Explanation: All messages sent by employees
Tgene is a website that connects the Gilmour Academy molecular genetics lab to others around the world. My app allows the students and lab instructor, Doctor Edward Turk, to write and upload blog posts, pictures, and research about the current work being done in the lab. Through this shared information, collaboration can occur between labs through a contact feature to get teachers and researchers in touch. Collaboration also includes the sale of plasmids from the Gilmour Academy lab to other schools. Tgene is a project that allows Gilmour Academy high school molecular genetics class to share their research, work, and plasmids to other students and researchers across the country.
Class for my register form that allows me to register as an admin
Query: Moneyplasmid = DBSession.query(Plasmid).filter(plasmid.price)
Explanation: Returns all plasmids that cost money
Query: Freeplasmid= DBSession.query(Plasmid).filter(plasmid.price<1)
Explanation: Returns all plasmids that are free/ link to assistance
Query: PlasmidOrder=DBSession.query(Plasmid).order_by(Plasmid.price)
Explanation: Query all plasmids ordered by price
Query: Plasmidall= DBSession.query(plasmid)
For plasmid in Plasmid:
print plasmid.name
Explanation: Query all available plasmids for sale (free and $$)
plasmidgene = DBSession.query(Book).filter_by(gene_id=str)
Query that shows all the plasmids bought that include a specific gene (sort by genes)
An app to organize announcements for school clubs and teams and to efficiently communicate them to students. Our platform is a way for groups to connect with users. Members can subscribe to groups to stay up to date on what is going on with a group. Groups can post announcements and members can comments and react to them.
Lists all the groups a certain user is in
Group.query.join(Membership).filter(Membership.user_id == 2).all()
Lists all of the announcement for a particular school base on school id
Announcement.query.filter(Announcement.school_id == 2).all()
Lists all of the groups at a particular school
Group.query.filter(Group.school_id == 2).all()
# Gives all the announcements that a certain user has made
Announcement.query.filter_by(user_id=2).all()
# Gives all of the announcements of a particular group
Announcement.query.filter(Announcement.group_id == 2).all()
Membership.query.filter(Membership.user_id==current_user.id, Membership.role=='Leader').all()
# NOT WORKING---- Gives all of the announcements for a particular user based on their groups
Announcement.query.join(Group.query.join(Membership)).filter(Membership.user_id == 2).all()
.filter(Membership.user_id == 2).all()
Group.query.join(Membership).filter(Announcement.query.filter_by(user_id=2).all()
Assuming you’re responsible enough to use some sort of project management tool like Trello, use the UML or ERD you’ve sketched as a reference to build out your todo list. For almost every table you’ve created in your database, you’ll probably need:
A form built in your forms.py that defines each field a user will fill out
A .html template where that form can be displayed. This form will be used to create a new object as well as editing an existing object
A route and function in your views.py for both the new and edit mode of your object form
A link that will trigger the creation of a new object or editing an existing object
The point here is to think through the absolute minimal displays required to add and manage your data. Then layer in some basic commands next to that table of data.
Once your models.py
file is complete and your app is running, the first route I recommend building is /superadmin.
We'll build control tables, here's how we load the data for the first one, users.
Register a domain and point your domain’s to DigitalOcean’s nameservers:
Setup your server’s basic settings: This includes our ufw firewall: . Don't forget to disable root ssh login.
Setup python (check on your version of ubuntu). You're not trying to get a demo app online, we're mostly using commands like sudo apt install python3.7-dev
:
Make sure we have the basics for our database (install, install, install!):
Install and configure nginx, your webserver (remember the ): -[ at this point you should be able to go to http://your-domain and see a blank, nginx page ]-
Update your git repository and (). We’ve got to package your app ready to ship. Calling the deployment of software “shipping” is really cool and people think you’re cool when you say it. So instead of "setting up my app on a remote server" we can say, "shipping a new version." Nice.
Pull your app’s repo and setup your dependencies before serving up your app: Notes to complement the Digital Ocean guide:
Helpful articles if you’re running into some trouble:
(adjust to the version of Ubuntu you're using)
Secure your HTTP connection: sudo apt install python-certbot-nginx
sudo certbot --nginx -d mysite.net
If you modified any db.Column
then, you need to track that migration on . Reading the is how you can best safeguard your users’ data.
Get ready to handle errors:
is an awesome tool to get notifications of any error happening on your server
Our next task is to apply your theme’s design to the built-in login page. Applying a cosmetic, HTML layer to your application is sometimes referred to as “skinning.” The login’s template is provided by our installed in Flaskinni. If you were to delete one of the template files, the app would default to the built-in Flask-Security template. By having the files in our templates folder, we override the built-in look of the pages.
If you haven't learned about flash notices yet for homework, you can , or talk about them in class. Assuming you get the idea and see how Flaskinni uses them, let's now rewire the system so it looks good in your HTML template. Maybe we'll use a dismissible Bootstrap alert but maybe want to tie into some fancier features that come with some themes.
In the next section, we’re about to build . You must understand that anytime you tinker with a models.py
file, (from the /inni folder or elsewhere) then you’ve altered your schema and now your database is likely now out of sync. For example, let’s say you wanted to combine User.first_name with User.last_name so there was just one field, User.name. The SQL tables that stored that information can’t adjust to your modified Python code so easily. All of the existing records (i.e. the rows in your tables) will need to now be migrated to a the new set of columns you’ve constructed. That can be really tricky!
These commands are different and likely to change in the future. Think about it: we're not using our Flask app. Instead, we're using some tool that detects changes in our database and automates the migration of our data in our old table to our new table. Delicate stuff! Before we'd use Flask-Script as an intermediate. Now we use to access terminal commands that will migrate our database.
Must read:
The term decorators in programming refers to a sort of flag or notice put at the start of a method to signal some sort of special treatment. We use @login_required to trigger Flask-Security’s verification that the user is carrying the encrypted token from our system given to a confirmed user. I would imagine verification of authority and privileges is the most common reason to use a decorator in Flask. We use them .
The form is our primary method of collecting information from the user. Depending on your application's need, you may need to looking closely into . Meanwhile, here are a few recipes that have been requested.
The most typically recommended answer is the .
(placeholders)
Let’s say you want to query the database for a user’s contacts with a built-in relationship such as current_user.contacts. You can get a list back from the database with just that one command. However, what if you know you’ll always need additional filters on that query. You don’t want the results quite so fast, instead you’d like the SQLAlchemy query not to complete its task but rather to keep the search open and ready for additional filtering or sorting.
( of a post)
Launch your app and check it out. ?
(go back into psql and connect to our db then what we made)
We use as a sort of bubble that contains our version of Python, Flask, and all the many other libraries used. Each library is likely to see improvements and security fixes. It’s important to keep this codebase updated but it’s an awfully risky process. Updates might change how some of the libraries work and may force you to change or cause new bugs. Best practice is to keep a previous version of your handy and to build thorough .
Before asking to do a lot of work, you may want it upgrade it first: pip install --upgrade pip
Inside docs/
folder are files produced by .
There's a few ways to trigger a database query. I like to call the object statically so I can explain to students about those terms. You'll more often see db.session.query(Post)
.
.