1

I have developed a restful api using flask and python. I have created an html page that will display my groups table and allow me to add and delete a group. I want to use Angularjs to take the data from my restful api and display it on my html page and allow me to Add, Update, Delete and view my groups from my group table. Below is my Restful API

import mysql.connector
from flask import Flask, abort, jsonify, request

# Global Constants
VERSION = 'v1'
BASE_URI = '/api/' + VERSION
GROUPS = '/groups'
GROUP = '/group'
URI_FOR_ALL_GROUPS = BASE_URI + GROUPS
MYSQL_USER = 'root'
MYSQL_PASS = ''
MYSQL_HOST = 'localhost'
MYSQL_DB = 'football'

# Creating an instance of Flask
app = Flask(__name__)


def create_connection():  # Method to Create Connection to Database
    return mysql.connector.connect(user=MYSQL_USER,
                                   password=MYSQL_PASS,
                                   host=MYSQL_HOST,
                                   database=MYSQL_DB)


# POST: Adding a new Group
@app.route(URI_FOR_ALL_GROUPS, methods=['POST'])
def add_group():
    # Method to add Group
    if not request.json:
        abort(400)
    conn = create_connection()
    cursor = conn.cursor()
    query = "INSERT INTO groups(group_name, team_a," \
            "team_b, team_c, team_d)" \
            "values (%s, %s, %s, %s, %s)"
    cursor.execute(query, (request.json['group_name'],
                           request.json['team_a'],
                           request.json['team_b'],
                           request.json['team_c'],
                           request.json['team_d']))
    id = cursor.lastrowid
    conn.commit()
    query = "SELECT * FROM groups WHERE group_id=" + str(id)
    cursor.execute(query)
    row = cursor.fetchone()
    group = {}
    for (key, value) in zip(cursor.description, row):
        group[key[0]] = value
    conn.close()

    return jsonify(group), 201


# GET: Get a single groups information
@app.route(URI_FOR_ALL_GROUPS + '/<int:id>', methods=['GET'])
def get_group(id):
    # Method to retrieve the information of a single group
    conn = create_connection()
    cursor = conn.cursor()
    query = "SELECT * FROM groups WHERE group_id=" + str(id)
    cursor.execute(query)
    row = cursor.fetchone()
    group = {}
    for (key, value) in zip(cursor.description, row):
        group[key[0]] = value
    conn.close()

    return jsonify(group), 200


# GET Retrieve all the groups
@app.route(URI_FOR_ALL_GROUPS, methods=['GET'])
def get_groups():
    # Method to retrieve all groups
    conn = create_connection()
    cursor = conn.cursor()
    query = "SELECT * FROM groups"
    cursor.execute(query)
    rows = cursor.fetchall()
    groups = []
    for row in rows:
        dict = {}
        for (key, value) in zip(cursor.description, row):
            dict[key[0]] = value
        groups.append(dict)
    conn.close()

    return jsonify({'groups': groups}), 200


# PUT: Updating a group
@app.route(URI_FOR_ALL_GROUPS + '/<int:id>', methods=['PUT'])
def update_group(id):
    # Method to update a group
    conn = create_connection()
    cursor = conn.cursor()
    query = "UPDATE groups SET group_name=%s, team_a=%s," \
            "team_b=%s, team_c=%s, team_d=%s " \
            "WHERE group_id=%s"
    cursor.execute(query, (request.json['group_name'],
                           request.json['team_a'],
                           request.json['team_b'],
                           request.json['team_c'],
                           request.json['team_d'], id))
    conn.commit()
    query = "SELECT * FROM groups WHERE group_id=" + str(id)
    cursor.execute(query)
    row = cursor.fetchone()
    group = {}
    for (key, value) in zip(cursor.description, row):
        group[key[0]] = value
    conn.close()

    return jsonify(group), 200


# DELETE: Deleting a group
@app.route(URI_FOR_ALL_GROUPS + '/<int:id>', methods=['DELETE'])
def delete_group(id):
    # Method to delete a single group
    conn = create_connection()
    cursor = conn.cursor()
    query = ("DELETE FROM groups WHERE group_id = %d" % id)
    cursor.execute(query)
    conn.commit()

    return jsonify('Group Deleted'), 200

if __name__ == '__main__':
    app.run(debug=True)

And this is the html page I created

<!DOCTYPE html>
<html lang="en">
<head>
    <script src = "https://ajax.googleapis.com/ajax/libs/angularjs/1.7.5/angular.min.js"></script>
    <meta charset="UTF-8">
    <title>Groups</title>
</head>
<body>

<div ng-app = "app" ng-controller = "getGroups">
    <table>
        <tr>
            <th>Group Name</th>
            <th>Team A</th>
            <th>Team B</th>
            <th>Team C</th>
            <th>Team D</th>
        </tr>
        <tbody ng-repeat = "groups in allGroups">
            <tr ng-repeat = "item in groups">
                <td ng-bind = "item.group_name"></td>
                <td ng-bind = "item.team_a"></td>
                <td ng-bind = "item.team_b"></td>
                <td ng-bind = "item.team_c"></td>
                <td ng-bind = "item.team_d"></td>
                <td><button ng-click = "deleteGroup(item.group_id)">Delete Group</button></td>
            </tr>
        </tbody>
    </table>
    <br>

    <form name = "addGroup" ng-submit = "submit()">
        <label>Group Name: </label><input type = "text" name = "Group Name" ng-model = "form.group_name" required ng-pattern = "[a-zA-z]*"><br>
        <label>Team A: </label><input type = "text" name = "Team A" ng-model = "form.team_a"><br>
        <label>Team B: </label><input type = "text" name = "Team B" ng-model = "form.team_b"><br>
        <label>Team C: </label><input type = "text" name = "Team C" ng-model = "form.team_c"><br>
        <label>Team D: </label><input type = "text" name = "Team D" ng-model = "form.team_d"><br>
        <input type = "submit">
    </form>
</div>

<script>
    var app = angular.module('app',[]);

    app.controller('getGroups', function($scope, $http)
    {
        $http({
            method: "GET",
            url: "http://127.0.0.1:5000/api/v1/groups"
        }).then(function onSuccess(response) {
            $scope.allGroups = response.data;
        }, function error(response) {
            $scope.allGroups = response.statusText;
            alert("Something went wrong: Error No. 1")
        });

        $scope.submit = function()
        {
            $http({
                method: "POST",
                url: "http://127.0.0.1:5000/api/v1/groups",
                data: $scope.form,
                headers: { 'Content-Type' : 'application/json' }
            }).then(function onSuccess(response) {
                alert("Group has been added");
            }, function error() {
                alert("Something has gone wrong: Error No. 2");
            });
        };

        $scope.deleteGroup = function(id)
        {
            $http({
                method: "DELETE",
                url: ("http://127.0.0.1:5000/api/v1/groups" + id)
            }).then(function onSuccess() {
                alert("Group has been deleted");
            }, function error() {
                alert("Something went wrong: Error No. 3");
            });
        };
    });
</script>

</body>
</html>

When I run my webpage, my alert displays with Error 1 and my groups are not shown on my table. Im not sure if I have left something out. My restful api works correctly and I can view the table contents on api/v1/groups.


Sorry my bad, this is the error I get on the browser console

Error: [$parse:ueoe] https://errors.angularjs.org/1.7.5/$parse/ueoe?p0=%5Ba-zA-z%5D* at angular.js:99 at p.consume (angular.js:16101) at primary (angular.js:15976) at p.unary (angular.js:15960) at p.multiplicative (angular.js:15950) at p.additive (angular.js:15938) at p.relational (angular.js:15929) at p.equality (angular.js:15920) at p.logicalAND (angular.js:15912) at p.logicalOR (angular.js:15904) ""

Access to XMLHttpRequest at '127.0.0.1:5000/api/v1/groups' from origin 'localhost:63342' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

georgeawg
  • 48,608
  • 13
  • 72
  • 95
Alan
  • 23
  • 6
  • Were there any errors in console ? – user3392782 Dec 03 '18 at 00:25
  • 127.0.0.1 - - [03/Dec/2018 00:34:15] "GET /api/v1/groups HTTP/1.1" 200 - from the console. My alert triggers though, alert(Something went wrong: Error No. 1) – Alan Dec 03 '18 at 00:35
  • That looks like the server side message ? Do you see any errors in the browser console ? – user3392782 Dec 03 '18 at 00:52
  • Sorry my bad, this is the error I get on the browser console – Alan Dec 03 '18 at 00:58
  • Error: [$parse:ueoe] http://errors.angularjs.org/1.7.5/$parse/ueoe?p0=%5Ba-zA-z%5D* at angular.js:99 at p.consume (angular.js:16101) at primary (angular.js:15976) at p.unary (angular.js:15960) at p.multiplicative (angular.js:15950) at p.additive (angular.js:15938) at p.relational (angular.js:15929) at p.equality (angular.js:15920) at p.logicalAND (angular.js:15912) at p.logicalOR (angular.js:15904) "" – Alan Dec 03 '18 at 00:58
  • Access to XMLHttpRequest at 'http://127.0.0.1:5000/api/v1/groups' from origin 'http://localhost:63342' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. – Alan Dec 03 '18 at 00:59

1 Answers1

1

Clearly it is a CORS issue. Please return the relevant header Access-Control-Allow-Origin in your response headers with the domain name from where the request is sent or * (not recommended) for allowing all the domains.

user3392782
  • 181
  • 4
  • Thanks, I installed a chrome extension that has fixed the issue for me. – Alan Dec 03 '18 at 01:44
  • installing a chrome extension is not the solution, you're going to face the issue when deploying to production – Sajeetharan Dec 03 '18 at 01:48
  • I don't know how to deal with CORS. Im hoping I wont have this issue when I build it on my university computer which is where is will be hosted – Alan Dec 03 '18 at 01:52
  • I added code to my api.py file which deals with CORS so I no longer need to use the extension – Alan Dec 03 '18 at 02:02