Skip to content

Commit 73d40e5

Browse files
committed
Initial Commit
1 parent 73deffd commit 73d40e5

17 files changed

+500
-0
lines changed

.txt

Whitespace-only changes.

Dockerfile

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Use an official Python runtime as a parent image
2+
FROM python:3.8
3+
4+
# Set the working directory in the container
5+
WORKDIR /app
6+
7+
# Copy only the requirements file first to leverage Docker cache
8+
COPY requirements.txt .
9+
10+
# Install any needed packages specified in requirements.txt
11+
RUN pip install --no-cache-dir -r requirements.txt
12+
13+
# Copy the rest of the application code into the container
14+
COPY . /app
15+
16+
# Make port 5000 available to the world outside this container
17+
EXPOSE 5000
18+
19+
# Define environment variable
20+
ENV NAME World
21+
22+
# run the command python
23+
ENTRYPOINT [ “python” ]
24+
25+
# and pass in the argument app.py
26+
CMD [ “app.py” ]

app-deployment.yaml

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: flask-deployment
5+
spec:
6+
replicas: 1
7+
selector:
8+
matchLabels:
9+
app: flask-app
10+
template:
11+
metadata:
12+
labels:
13+
app: flask-app
14+
spec:
15+
containers:
16+
- name: flask-app-container
17+
image: ain-project:latest
18+
ports:
19+
- containerPort: 5000
20+
env:
21+
- name: MONGODB_URI
22+
valueFrom:
23+
configMapKeyRef:
24+
name: flask-app-configmap
25+
key: MONGODB_URI
26+
resources:
27+
limits:
28+
cpu: "1"
29+
memory: "512Mi"
30+
requests:
31+
cpu: "0.5"
32+
memory: "256Mi"

app.py

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from flask import Flask
2+
from pymongo import MongoClient
3+
4+
5+
app = Flask(__name__)
6+
app.config['SECRET_KEY'] = 'mysecretkey'
7+
8+
9+
# Connect to MongoDB
10+
connection_string = "mongodb://localhost:27017/"
11+
client = MongoClient(connection_string)
12+
db = client["bookstore_db"]
13+
collection = db["bookstore_db"]
14+
15+
from routes import *
16+
17+
18+
if __name__ == "__main__":
19+
app.run(host="0.0.0.0", debug=True)
20+
21+

flask-app-configmap.yaml

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
apiVersion: v1
2+
kind: ConfigMap
3+
metadata:
4+
name: flask-app-configmap
5+
data:
6+
MONGODB_URI: "mongodb://localhost:27017/"
7+

forms.py

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from flask_wtf import FlaskForm
2+
from wtforms import StringField, SubmitField
3+
from wtforms.validators import DataRequired
4+
5+
class AddBookForm(FlaskForm):
6+
isbn = StringField('ISBN', validators=[DataRequired()])
7+
title = StringField('Title', validators=[DataRequired()])
8+
year = StringField('Year', validators=[DataRequired()])
9+
price = StringField('Price', validators=[DataRequired()])
10+
page = StringField('Page', validators=[DataRequired()])
11+
category = StringField('Category', validators=[DataRequired()])
12+
coverPhoto = StringField('Cover Photo', validators=[DataRequired()])
13+
publisher = StringField('Publisher', validators=[DataRequired()])
14+
author = StringField('Author', validators=[DataRequired()])
15+
submit = SubmitField('Submit')
16+
17+
class EditBookForm(FlaskForm):
18+
title = StringField('Title', validators=[DataRequired()])
19+
submit = SubmitField('Submit')
20+
21+
class DeleteBookForm(FlaskForm):
22+
submit = SubmitField('Delete')

model.py

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# model.py
2+
3+
class Book:
4+
def __init__(self, isbn, title, year, price, page, category, coverPhoto, publisher, author):
5+
self.isbn = isbn
6+
self.title = title
7+
self.year = year
8+
self.price = price
9+
self.page = page
10+
self.category = category
11+
self.coverPhoto = coverPhoto
12+
self.publisher = publisher
13+
self.author = author
14+
15+
def to_dict(self):
16+
return {
17+
"isbn": self.isbn,
18+
"title": self.title,
19+
"year": self.year,
20+
"price": self.price,
21+
"page": self.page,
22+
"category": self.category,
23+
"coverPhoto": self.coverPhoto,
24+
"publisher": self.publisher,
25+
"author": self.author
26+
}

mongo-service.yaml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
apiVersion: v1
2+
kind: Service
3+
metadata:
4+
name: mongo-service
5+
spec:
6+
selector:
7+
app: mongo
8+
ports:
9+
- protocol: TCP
10+
port: 27017
11+
targetPort: 27017

mongo-statefulset.yaml

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
apiVersion: apps/v1
2+
kind: StatefulSet
3+
metadata:
4+
name: mongodb
5+
spec:
6+
serviceName: "mongodb"
7+
replicas: 1
8+
selector:
9+
matchLabels:
10+
app: mongodb
11+
template:
12+
metadata:
13+
labels:
14+
app: mongodb
15+
spec:
16+
containers:
17+
- name: mongodb
18+
image: mongo:latest
19+
ports:
20+
- containerPort: 27017
21+
name: mongo
22+
volumeMounts:
23+
- name: mongodb-storage
24+
mountPath: /data/db
25+
volumeClaimTemplates:
26+
- metadata:
27+
name: mongodb-storage
28+
spec:
29+
accessModes: [ "ReadWriteOnce" ]
30+
storageClassName: "standard"
31+
resources:
32+
requests:
33+
storage: 1Gi

requirements.txt

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Flask==3.0.0
2+
Werkzeug==3.0.1
3+
pymongo==4.6.1
4+
Flask-WTF==1.2.1

routes.py

+135
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
# routes.py
2+
3+
from app import app, collection
4+
from flask import render_template, redirect, url_for, flash, request, jsonify
5+
from datetime import datetime
6+
from forms import AddBookForm, EditBookForm, DeleteBookForm
7+
from bson import ObjectId # Import ObjectId
8+
9+
@app.route('/')
10+
@app.route('/index')
11+
def index():
12+
books = list(collection.find())
13+
return render_template('index.html', books=books)
14+
15+
@app.route('/add', methods=['GET', 'POST'])
16+
def add():
17+
form = AddBookForm()
18+
19+
if form.validate_on_submit():
20+
isbn = form.isbn.data
21+
title = form.title.data
22+
year = form.year.data
23+
price = form.price.data
24+
page = form.page.data
25+
category = form.category.data
26+
coverPhoto = form.coverPhoto.data
27+
publisher = form.publisher.data
28+
author = form.author.data
29+
30+
date = datetime.utcnow()
31+
collection.insert_one({
32+
"isbn": isbn,
33+
"title": title,
34+
"year": year,
35+
"price": price,
36+
"page": page,
37+
"category": category,
38+
"coverPhoto": coverPhoto,
39+
"publisher": publisher,
40+
"author": author,
41+
"date": date
42+
})
43+
44+
flash('The book was added to the database.')
45+
return redirect(url_for('index'))
46+
47+
return render_template('add.html', form=form)
48+
49+
@app.route('/edit/<string:book_id>', methods=['GET', 'POST'])
50+
def edit(book_id):
51+
book = collection.find_one({"_id": ObjectId(book_id)})
52+
form = EditBookForm()
53+
54+
if book:
55+
if form.validate_on_submit():
56+
title = form.title.data
57+
date = datetime.utcnow()
58+
collection.update_one({"_id": ObjectId(book_id)}, {"$set": {"title": title, "date": date}})
59+
flash('The book in the database was updated.')
60+
return redirect(url_for('index'))
61+
form.title.data = book['title']
62+
return render_template('edit.html', form=form, book_id=book_id, book=book) # Pass 'book' variable to the template
63+
else:
64+
flash('The book ID is not in the database.')
65+
return redirect(url_for('index'))
66+
67+
68+
@app.route('/delete/<string:book_id>', methods=['GET', 'POST'])
69+
def delete(book_id):
70+
book = collection.find_one({"_id": ObjectId(book_id)}) # Use ObjectId
71+
form = DeleteBookForm()
72+
73+
if book:
74+
if form.validate_on_submit():
75+
collection.delete_one({"_id": ObjectId(book_id)}) # Use ObjectId
76+
flash('The book in the database was deleted.')
77+
return redirect(url_for('index'))
78+
return render_template('delete.html', form=form, book_id=book_id, title=book['title'])
79+
else:
80+
flash('The book ID is not in the database.')
81+
return redirect(url_for('index'))
82+
83+
# Updated route for CRUD operations
84+
@app.route('/crud/<string:operation>/<string:book_id>', methods=['GET', 'POST', 'PUT', 'DELETE'])
85+
def crud(operation, book_id):
86+
book = collection.find_one({"_id": ObjectId(book_id)})
87+
88+
if operation == 'view':
89+
return render_template('view.html', book=book)
90+
91+
form = EditBookForm()
92+
93+
if request.method == 'GET':
94+
# Handle GET request
95+
if operation == 'edit':
96+
form.title.data = book['title']
97+
return render_template('edit.html', form=form, book_id=book_id)
98+
elif operation == 'delete':
99+
return render_template('delete.html', form=form, book_id=book_id, title=book['title'])
100+
else:
101+
flash('Invalid operation.')
102+
return redirect(url_for('index'))
103+
104+
elif request.method == 'POST':
105+
# Handle POST request
106+
if operation == 'edit' and form.validate_on_submit():
107+
title = form.title.data
108+
date = datetime.utcnow()
109+
collection.update_one({"_id": ObjectId(book_id)}, {"$set": {"title": title, "date": date}})
110+
flash('The book in the database was updated.')
111+
return redirect(url_for('index'))
112+
elif operation == 'delete' and form.validate_on_submit():
113+
collection.delete_one({"_id": ObjectId(book_id)})
114+
flash('The book in the database was deleted.')
115+
return redirect(url_for('index'))
116+
else:
117+
flash('Invalid operation.')
118+
return redirect(url_for('index'))
119+
120+
elif request.method == 'PUT':
121+
# Handle PUT request (using JSON for simplicity)
122+
data = request.get_json()
123+
title = data.get('title')
124+
date = datetime.utcnow()
125+
collection.update_one({"_id": ObjectId(book_id)}, {"$set": {"title": title, "date": date}})
126+
return jsonify({"message": "Book updated successfully"})
127+
128+
elif request.method == 'DELETE':
129+
# Handle DELETE request (using JSON for simplicity)
130+
collection.delete_one({"_id": ObjectId(book_id)})
131+
return jsonify({"message": "Book deleted successfully"})
132+
133+
else:
134+
flash('Invalid method.')
135+
return redirect(url_for('index'))

static/style.css

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/* static/style.css */
2+
3+
body {
4+
background-color: #f8f9fa;
5+
}
6+
7+
.container {
8+
margin-top: 20px;
9+
}
10+
11+
.card {
12+
width: 100%;
13+
border: 1px solid #dee2e6;
14+
border-radius: 10px;
15+
margin-bottom: 20px;
16+
}
17+
18+
.card-body {
19+
padding: 20px;
20+
}
21+
22+
.btn-group {
23+
margin-top: 10px;
24+
}
25+
26+
/* Optional: Add hover effect to buttons */
27+
.btn:hover {
28+
filter: brightness(90%);
29+
}
30+

templates/add.html

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<!-- add.html -->
2+
3+
{% extends "base.html" %}
4+
5+
{% block main %}
6+
<div class="container">
7+
<form action="{{ url_for('add') }}" method="post">
8+
{{ form.csrf_token }}
9+
<h2 class="mt-4 mb-4">Add Book</h2>
10+
<div class="form-row">
11+
<div class="col-md-6">
12+
{{ form.isbn(class="form-control", placeholder="Enter ISBN") }}
13+
{{ form.title(class="form-control", placeholder="Enter book title") }}
14+
{{ form.year(class="form-control", placeholder="Enter publication year") }}
15+
{{ form.price(class="form-control", placeholder="Enter price") }}
16+
{{ form.page(class="form-control", placeholder="Enter number of pages") }}
17+
{{ form.category(class="form-control", placeholder="Enter category") }}
18+
{{ form.coverPhoto(class="form-control", placeholder="Enter cover photo URL") }}
19+
{{ form.publisher(class="form-control", placeholder="Enter publisher") }}
20+
{{ form.author(class="form-control", placeholder="Enter author") }}
21+
</div>
22+
<div class="col-md-6">
23+
{{ form.submit(class="btn btn-primary mt-4") }}
24+
</div>
25+
</div>
26+
</form>
27+
</div>
28+
{% endblock %}

0 commit comments

Comments
 (0)