6 | {/* Display the article details if article is not None */}
7 | {props.articles && props.articles.map(article =>{
8 | return (
9 |
10 |
11 |
{ article.title}
12 |
{ article.body }
13 |
{ article.date }
14 |
15 |
16 | )
17 |
18 | })}
19 |
20 | )
21 | }
22 |
23 | export default ArticleList;
--------------------------------------------------------------------------------
/backend/models.py:
--------------------------------------------------------------------------------
1 | from app import db,ma
2 | from datetime import datetime
3 |
4 |
5 | class Articles(db.Model):
6 | id = db.Column(db.Integer, primary_key=True)
7 | title = db.Column(db.String(100),nullable=False)
8 | body = db.Column(db.Text, nullable=False)
9 | date = db.Column(db.DateTime(), default=datetime.utcnow)
10 |
11 |
12 | def __repr__(self):
13 | return "" % self.title
14 |
15 | # Generate marshmallow Schemas from your models
16 | class ArticlesShema(ma.Schema):
17 | class Meta:
18 | # Fields to expose
19 | fields = ("id","title", "body", "date")
20 |
21 |
22 | article_schema = ArticlesShema()
23 | articles_schema = ArticlesShema(many=True)
--------------------------------------------------------------------------------
/backend/manage.py:
--------------------------------------------------------------------------------
1 | def deploy():
2 | """Run deployment tasks."""
3 | from app import create_app,db
4 | from flask_migrate import upgrade,migrate,init,stamp
5 | from models import Articles
6 |
7 | app = create_app()
8 | app.app_context().push()
9 |
10 | # create database and tables
11 | db.create_all()
12 |
13 | # migrate database to latest revision
14 | stamp()
15 | migrate()
16 | upgrade()
17 |
18 | deploy()
19 |
20 | # Error: Working outside of application context.
21 |
22 | # This typically means that you attempted to use functionality that needed
23 | # to interface with the current application object in some way. To solve
24 | # this, set up an application context with app.app_context(). See the
25 | # documentation for more information.
--------------------------------------------------------------------------------
/frontend/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | React and Flask
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/backend/app.py:
--------------------------------------------------------------------------------
1 | # Import the required libraries
2 | from flask import Flask
3 | from flask_sqlalchemy import SQLAlchemy
4 | from flask_migrate import Migrate
5 | from flask_marshmallow import Marshmallow
6 | from flask_cors import CORS
7 |
8 |
9 | # Create various application instances
10 | # Order matters: Initialize SQLAlchemy before Marshmallow
11 | db = SQLAlchemy()
12 | migrate = Migrate()
13 | ma = Marshmallow()
14 | cors = CORS()
15 |
16 |
17 | def create_app():
18 | """Application-factory pattern"""
19 | app = Flask(__name__)
20 | app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///database.db"
21 | app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
22 |
23 | # Initialize extensions
24 | # To use the application instances above, instantiate with an application:
25 | db.init_app(app)
26 | migrate.init_app(app, db)
27 | ma.init_app(app)
28 | cors.init_app(app)
29 |
30 | return app
31 |
--------------------------------------------------------------------------------
/frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.14.1",
7 | "@testing-library/react": "^11.2.7",
8 | "@testing-library/user-event": "^12.8.3",
9 | "react": "^17.0.2",
10 | "react-dom": "^17.0.2",
11 | "react-scripts": "4.0.3",
12 | "web-vitals": "^1.1.2"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/frontend/src/App.js:
--------------------------------------------------------------------------------
1 | import { useState,useEffect } from 'react'
2 | import './App.css';
3 | import ArticleList from './Components/ArticleList'
4 |
5 | function App() {
6 | const [articles, setArticles] = useState([]);
7 |
8 | // Modify the current state by setting the new data to
9 | // the response from the backend
10 | useEffect(()=>{
11 | fetch('http://localhost:5000/articles',{
12 | 'methods':'GET',
13 | headers : {
14 | 'Content-Type':'application/json'
15 | }
16 | })
17 | .then(response => response.json())
18 | .then(response => setArticles(response))
19 | .catch(error => console.log(error))
20 |
21 | },[])
22 |
23 | return (
24 |
25 |
26 |
27 |
Connecting a React Frontend to a Flask Backend.
28 |
29 |
30 |
31 |
34 |
35 |
36 | );
37 | }
38 |
39 | export default App;
40 |
--------------------------------------------------------------------------------
/backend/migrations/alembic.ini:
--------------------------------------------------------------------------------
1 | # A generic, single database configuration.
2 |
3 | [alembic]
4 | # template used to generate migration files
5 | # file_template = %%(rev)s_%%(slug)s
6 |
7 | # set to 'true' to run the environment during
8 | # the 'revision' command, regardless of autogenerate
9 | # revision_environment = false
10 |
11 |
12 | # Logging configuration
13 | [loggers]
14 | keys = root,sqlalchemy,alembic,flask_migrate
15 |
16 | [handlers]
17 | keys = console
18 |
19 | [formatters]
20 | keys = generic
21 |
22 | [logger_root]
23 | level = WARN
24 | handlers = console
25 | qualname =
26 |
27 | [logger_sqlalchemy]
28 | level = WARN
29 | handlers =
30 | qualname = sqlalchemy.engine
31 |
32 | [logger_alembic]
33 | level = INFO
34 | handlers =
35 | qualname = alembic
36 |
37 | [logger_flask_migrate]
38 | level = INFO
39 | handlers =
40 | qualname = flask_migrate
41 |
42 | [handler_console]
43 | class = StreamHandler
44 | args = (sys.stderr,)
45 | level = NOTSET
46 | formatter = generic
47 |
48 | [formatter_generic]
49 | format = %(levelname)-5.5s [%(name)s] %(message)s
50 | datefmt = %H:%M:%S
51 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 ONDIEK ELIJAH OCHIENG
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Requirements ,Usage and Installation
2 | ## Backend - Flask
3 | ### Installation
4 |
5 | ### 1 .Clone the git repo and create an environment
6 |
7 | Depending on your operating system,make a virtual environment to avoid messing with your machine's primary dependencies
8 |
9 | **Windows**
10 |
11 | ```bash
12 | git clone https://github.com/Dev-Elie/Connecting-React-Frontend-to-a-Flask-Backend.git
13 | cd Connecting-React-Frontend-to-a-Flask-Backend/backend
14 | py -3 -m venv venv
15 | ```
16 |
17 | **macOS/Linux**
18 |
19 | ```bash
20 | git clone https://github.com/Dev-Elie/Connecting-React-Frontend-to-a-Flask-Backend.git
21 | cd Connecting-React-Frontend-to-a-Flask-Backend/backend
22 | python3 -m venv venv
23 | ```
24 |
25 | ### 2 .Activate the environment
26 |
27 | **Windows**
28 |
29 | ```venv\Scripts\activate```
30 |
31 | **macOS/Linux**
32 |
33 | ```. venv/bin/activate```
34 | or
35 | ```source venv/bin/activate```
36 |
37 | ### 3 .Install the requirements
38 |
39 | Applies for windows/macOS/Linux
40 |
41 | ```pip install -r requirements.txt```
42 | ### 4 .Migrate/Create a database - Optional during initial set up
43 |
44 | Applies for windows/macOS/Linux
45 |
46 | ```python manage.py```
47 |
48 | ### 5. Run the application
49 |
50 | **For linux and macOS**
51 | Make the run file executable by running the code
52 |
53 | ```chmod 777 run```
54 |
55 | Then start the application by executing the run file
56 |
57 | ```./run```
58 |
59 | **On windows**
60 | ```
61 | set FLASK_APP=routes
62 | flask run
63 | ```
64 | OR
65 | `python routes.py`
66 |
67 | ## Frontend - React
68 | ### Installation
69 |
70 | You just need to install the packages listed on package.json, on the frontend folder.
71 |
72 | ```
73 | cd Connecting-React-Frontend-to-a-Flask-Backend/frontend
74 | npm install
75 | ```
76 |
77 | `npm start`
78 |
79 | ## Updating pip packages
80 |
81 | In an active virtual environment install updates using the command:
82 |
83 | `pip list --outdated --format=freeze | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U`
84 |
85 | Update the reqirements.txt file.
86 |
87 | `pip freeze > requirements.txt`
88 |
89 | 
90 |
Follow me on Twitter
91 |
92 |
--------------------------------------------------------------------------------
/backend/migrations/env.py:
--------------------------------------------------------------------------------
1 | from __future__ import with_statement
2 |
3 | import logging
4 | from logging.config import fileConfig
5 |
6 | from flask import current_app
7 |
8 | from alembic import context
9 |
10 | # this is the Alembic Config object, which provides
11 | # access to the values within the .ini file in use.
12 | config = context.config
13 |
14 | # Interpret the config file for Python logging.
15 | # This line sets up loggers basically.
16 | fileConfig(config.config_file_name)
17 | logger = logging.getLogger('alembic.env')
18 |
19 | # add your model's MetaData object here
20 | # for 'autogenerate' support
21 | # from myapp import mymodel
22 | # target_metadata = mymodel.Base.metadata
23 | config.set_main_option(
24 | 'sqlalchemy.url',
25 | str(current_app.extensions['migrate'].db.get_engine().url).replace(
26 | '%', '%%'))
27 | target_metadata = current_app.extensions['migrate'].db.metadata
28 |
29 | # other values from the config, defined by the needs of env.py,
30 | # can be acquired:
31 | # my_important_option = config.get_main_option("my_important_option")
32 | # ... etc.
33 |
34 |
35 | def run_migrations_offline():
36 | """Run migrations in 'offline' mode.
37 |
38 | This configures the context with just a URL
39 | and not an Engine, though an Engine is acceptable
40 | here as well. By skipping the Engine creation
41 | we don't even need a DBAPI to be available.
42 |
43 | Calls to context.execute() here emit the given string to the
44 | script output.
45 |
46 | """
47 | url = config.get_main_option("sqlalchemy.url")
48 | context.configure(
49 | url=url, target_metadata=target_metadata, literal_binds=True
50 | )
51 |
52 | with context.begin_transaction():
53 | context.run_migrations()
54 |
55 |
56 | def run_migrations_online():
57 | """Run migrations in 'online' mode.
58 |
59 | In this scenario we need to create an Engine
60 | and associate a connection with the context.
61 |
62 | """
63 |
64 | # this callback is used to prevent an auto-migration from being generated
65 | # when there are no changes to the schema
66 | # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html
67 | def process_revision_directives(context, revision, directives):
68 | if getattr(config.cmd_opts, 'autogenerate', False):
69 | script = directives[0]
70 | if script.upgrade_ops.is_empty():
71 | directives[:] = []
72 | logger.info('No changes in schema detected.')
73 |
74 | connectable = current_app.extensions['migrate'].db.get_engine()
75 |
76 | with connectable.connect() as connection:
77 | context.configure(
78 | connection=connection,
79 | target_metadata=target_metadata,
80 | process_revision_directives=process_revision_directives,
81 | **current_app.extensions['migrate'].configure_args
82 | )
83 |
84 | with context.begin_transaction():
85 | context.run_migrations()
86 |
87 |
88 | if context.is_offline_mode():
89 | run_migrations_offline()
90 | else:
91 | run_migrations_online()
92 |
--------------------------------------------------------------------------------
/frontend/README.md:
--------------------------------------------------------------------------------
1 | # Getting Started with Create React App
2 |
3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
4 |
5 | ## Available Scripts
6 |
7 | In the project directory, you can run:
8 |
9 | ### `npm start`
10 |
11 | Runs the app in the development mode.\
12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
13 |
14 | The page will reload if you make edits.\
15 | You will also see any lint errors in the console.
16 |
17 | ### `npm test`
18 |
19 | Launches the test runner in the interactive watch mode.\
20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
21 |
22 | ### `npm run build`
23 |
24 | Builds the app for production to the `build` folder.\
25 | It correctly bundles React in production mode and optimizes the build for the best performance.
26 |
27 | The build is minified and the filenames include the hashes.\
28 | Your app is ready to be deployed!
29 |
30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
31 |
32 | ### `npm run eject`
33 |
34 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
35 |
36 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
37 |
38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
39 |
40 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
41 |
42 | ## Learn More
43 |
44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
45 |
46 | To learn React, check out the [React documentation](https://reactjs.org/).
47 |
48 | ### Code Splitting
49 |
50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
51 |
52 | ### Analyzing the Bundle Size
53 |
54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
55 |
56 | ### Making a Progressive Web App
57 |
58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
59 |
60 | ### Advanced Configuration
61 |
62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
63 |
64 | ### Deployment
65 |
66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
67 |
68 | ### `npm run build` fails to minify
69 |
70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
71 |
--------------------------------------------------------------------------------