File: app.py

package info (click to toggle)
python-azure 20250603%2Bgit-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 851,724 kB
  • sloc: python: 7,362,925; ansic: 804; javascript: 287; makefile: 195; sh: 145; xml: 109
file content (108 lines) | stat: -rw-r--r-- 3,742 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# -------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License in the project root for
# license information.
# --------------------------------------------------------------------------

import os
from datetime import datetime

from flask import Flask, redirect, render_template, request, send_from_directory, url_for

from azure.projects import AzureApp
from azure.data.tables import TableClient, UpdateMode

from models import Restaurant, Review


app = Flask(__name__, template_folder="templates", static_folder="static")


class RestaurantReviewApp(AzureApp):
    restaurants: TableClient
    reviews: TableClient


azproject = RestaurantReviewApp.load(
    attr_map={"restaurants": "restaurant_data", "reviews": "review_data"},
)


@app.route("/", methods=["GET"])
def index():
    restaurants = [Restaurant(**e) for e in azproject.restaurants.list_entities()]
    return render_template("index.html", restaurants=restaurants)


@app.route("/<id>", methods=["GET"])
def details(id):
    restaurant = next(
        azproject.restaurants.query_entities("PartitionKey eq @partition", parameters={"partition": id}), None
    )
    if not restaurant:
        return (
            '<h1>404</h1><p>Restaurant not found!</p><img src="https://httpcats.com/404.jpg" alt="cat in box" width=400>',
            404,
        )
    reviews = [Review(**e) for e in azproject.reviews.query_entities("RowKey eq @row", parameters={"row": id})]
    return render_template("details.html", restaurant=Restaurant(**restaurant), reviews=reviews)


@app.route("/create", methods=["GET"])
def create_restaurant():
    return render_template("create_restaurant.html")


@app.route("/add", methods=["POST"])
def add_restaurant():
    name = request.values.get("restaurant_name")
    street_address = request.values.get("street_address")
    description = request.values.get("description")
    if not name or not street_address:
        error = "You must include a restaurant name and address."
        return render_template("create_restaurant.html", error=error)
    else:
        restaurant = Restaurant(name=name, street_address=street_address, description=description)
        azproject.restaurants.upsert_entity(restaurant.model_dump(by_alias=True), mode=UpdateMode.REPLACE)
    return redirect(url_for("details", id=restaurant.id))


@app.route("/review/<id>", methods=["POST"])
def add_review(id):
    user_name = request.values.get("user_name")
    rating = request.values.get("rating")
    review_text = request.values.get("review_text")

    review = Review(
        restaurant=id, user_name=user_name, rating=int(rating), review_text=review_text, review_date=datetime.now()
    )
    azproject.reviews.upsert_entity(review.model_dump(by_alias=True))
    return redirect(url_for("details", id=id))


@app.context_processor
def utility_processor():
    def star_rating(id):
        reviews = azproject.reviews.query_entities("RowKey eq @row", parameters={"row": id})
        ratings = []
        review_count = 0
        for review in reviews:
            ratings += [review["rating"]]
            review_count += 1

        avg_rating = sum(ratings) / len(ratings) if ratings else 0
        stars_percent = round((avg_rating / 5.0) * 100) if review_count > 0 else 0
        return {"avg_rating": avg_rating, "review_count": review_count, "stars_percent": stars_percent}

    return dict(star_rating=star_rating)


@app.route("/favicon.ico")
def favicon():
    return send_from_directory(
        os.path.join(app.root_path, "static"), "favicon.ico", mimetype="image/vnd.microsoft.icon"
    )


if __name__ == "__main__":
    app.run()