first commit
This commit is contained in:
commit
d6fa621e8e
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
venv
|
||||||
|
__pycache__
|
||||||
12
README.md
Normal file
12
README.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Projet API
|
||||||
|
|
||||||
|
### Description
|
||||||
|
|
||||||
|
Ce projet a été réaliser dans le cadre du cours de python en formation DEVOPS au CNAM.
|
||||||
|
|
||||||
|
### Prérequis
|
||||||
|
|
||||||
|
- Python 3.11.2
|
||||||
|
- flask : 3.0.2
|
||||||
|
- requests : 2.31.0
|
||||||
|
- bootstrap : 4.3.1
|
||||||
18
app.py
Normal file
18
app.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import requests
|
||||||
|
from flask import Flask, render_template
|
||||||
|
from fonctions import *
|
||||||
|
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
@app.route("/")
|
||||||
|
def index():
|
||||||
|
return render_template("index.html")
|
||||||
|
|
||||||
|
@app.route("/livres", methods=("GET", "POST"))
|
||||||
|
def livres():
|
||||||
|
datas = get_books()
|
||||||
|
return render_template("livres.html", datas=datas)
|
||||||
|
|
||||||
|
if __name__ == " __main__":
|
||||||
|
app.run()
|
||||||
55
fonctions.py
Normal file
55
fonctions.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import requests, json, ipaddress, random
|
||||||
|
from flask import request
|
||||||
|
|
||||||
|
def get_headers():
|
||||||
|
|
||||||
|
ip = []
|
||||||
|
|
||||||
|
for i in range(0, 4):
|
||||||
|
ip.append(random.randint(0, 254))
|
||||||
|
|
||||||
|
random_ip = ''
|
||||||
|
for i in range(0, 3):
|
||||||
|
random_ip += str(ip[i]) + '.'
|
||||||
|
|
||||||
|
random_ip += str(ip[3])
|
||||||
|
|
||||||
|
headers = {"X-Forwarded-For": random_ip}
|
||||||
|
|
||||||
|
return headers
|
||||||
|
|
||||||
|
class Livre:
|
||||||
|
def __init__(self, title, author, publish, isbn, img_url):
|
||||||
|
self.title = title
|
||||||
|
self.author = author
|
||||||
|
self.publish = publish
|
||||||
|
self.isbn = isbn
|
||||||
|
self.img_url = img_url
|
||||||
|
|
||||||
|
def get_books():
|
||||||
|
|
||||||
|
livres = []
|
||||||
|
headers = get_headers()
|
||||||
|
|
||||||
|
# La condition if permet de n'afficher du contenue de l'API que lorsqu'il y a une requête qui est effectué.
|
||||||
|
if request.method == "POST":
|
||||||
|
choix = request.form["choix"]
|
||||||
|
|
||||||
|
# Concaténations a l'url de l'API du choix de l'utilisateur reçu via request.form et on choisi les informations que nous souhaitons récuperer.
|
||||||
|
url = "https://openlibrary.org/search.json?q=" + choix + "&fields=title,author_name,first_publish_year,isbn"
|
||||||
|
response = requests.get(url, headers)
|
||||||
|
|
||||||
|
# Transformation des données reçu de l'API en objet JSON pour les avoir sous forme clé/valeur.
|
||||||
|
datas = json.loads(response.text)
|
||||||
|
|
||||||
|
for e in datas["docs"]:
|
||||||
|
# A l'aide du constructeur de la classe Livre on affine les données reçu et on concaténe isbn a l'url images.
|
||||||
|
livre = Livre(e["title"], e["author_name"][0], e["first_publish_year"], e["isbn"][0], "https://covers.openlibrary.org/b/isbn/" + e["isbn"][0] + "-L.jpg")
|
||||||
|
|
||||||
|
# Informations ajouté au dictionnaire livres definit plus haut.
|
||||||
|
livres.append(livre)
|
||||||
|
else:
|
||||||
|
print("Pas de requête effectué")
|
||||||
|
livres.append("No datas")
|
||||||
|
|
||||||
|
return livres
|
||||||
4
requirements.txt
Normal file
4
requirements.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
gunicorn==22.0.0
|
||||||
|
packaging==24.0
|
||||||
|
requests==2.31.0
|
||||||
|
flask==3.0.2
|
||||||
49
templates/base.html
Normal file
49
templates/base.html
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta>
|
||||||
|
<title>Projet API</title>
|
||||||
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
|
||||||
|
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
||||||
|
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
|
||||||
|
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.14.7/dist/umd/popper.min.js"
|
||||||
|
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/js/bootstrap.min.js"
|
||||||
|
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||||
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
|
||||||
|
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||||
|
<ul class="navbar-nav m-auto">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" style="font-size: 24px; padding-left: 40px;"
|
||||||
|
href="{{url_for('index')}}">Home</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" style="font-size: 24px; padding-left: 40px;"
|
||||||
|
href="{{url_for('livres')}}">Books</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<div class="text-center jumbotron">
|
||||||
|
{% block content %}
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
|
<footer class="text-center">
|
||||||
|
<img src="https://git.legaragenumerique.fr/assets/img/logo.svg" alt="Logo garage numerique">
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
34
templates/index.html
Normal file
34
templates/index.html
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<div class="text-center">
|
||||||
|
<h1 class="display-3 m-5">💻 Welcome!</h1>
|
||||||
|
</div>
|
||||||
|
<div class="text-center p-5" style="background-color: white; margin-top: 100px;">
|
||||||
|
<p class="mt-2" style="font-size: 2em;"> 💡 Find your new favorite book among several provided categories. 💡</p>
|
||||||
|
<hr style="margin: 60px 0;">
|
||||||
|
|
||||||
|
<div class="mt-5 p-4 d-flex justify-content-center">
|
||||||
|
<div class="col-6" style="border-right: 1px solid grey;">
|
||||||
|
<ul style="list-style: none;">
|
||||||
|
<li style="font-size: 1.5em;" class="mt-4"></li>
|
||||||
|
<li style="font-size: 1.5em;" class="mt-4">★ Horror </li>
|
||||||
|
<li style="font-size: 1.5em;" class="mt-4">★ Thriller </li>
|
||||||
|
<li style="font-size: 1.5em;" class="mt-4">★ Science Fisction </li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<ul style="list-style: none;">
|
||||||
|
<li style="font-size: 1.5em;" class="mt-4">★ Fiction </li>
|
||||||
|
<li style="font-size: 1.5em;" class="mt-4">★ Romance </li>
|
||||||
|
<li style="font-size: 1.5em;" class="mt-4">★ Fantasy </li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
47
templates/livres.html
Normal file
47
templates/livres.html
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<h1 class="mt-4" style="font-size: 44px">Books 📚</h1>
|
||||||
|
<p class="mt-4" style="font-size: 20px">Choose a category and see our selection</p>
|
||||||
|
</div>
|
||||||
|
<!-- Formulaire d'affichage des buttons et envoi de l'information selectionné par l'utilisateur. -->
|
||||||
|
<form action="/livres" method="POST" class="m-5 text-center">
|
||||||
|
<button type="submit" name="choix" value="horror" class="btn btn-outline-primary m-3">Horror</button>
|
||||||
|
<button type="submit" name="choix" value="fantasy" class="btn btn-outline-primary m-3">Fantasy</button>
|
||||||
|
<button type="submit" name="choix" value="thriller" class="btn btn-outline-primary m-3">Thriller</button>
|
||||||
|
<button type="submit" name="choix" value="poetry" class="btn btn-outline-primary m-3">Poetry</button>
|
||||||
|
<button type="submit" name="choix" value="fiction" class="btn btn-outline-primary m-3">Fiction</button>
|
||||||
|
<button type="submit" name="choix" value="romance" class="btn btn-outline-primary m-3">Romance</button>
|
||||||
|
<button type="submit" name="choix" value="sf" class="btn btn-outline-primary m-3">Science Fisction</button>
|
||||||
|
<button type="submit" name="choix" value="historical_fiction" class="btn btn-outline-primary m-3">Historical Fiction</button>
|
||||||
|
<button type="submit" name="choix" value="humor" class="btn btn-outline-primary m-3">Humor</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% if datas[0] != "No datas" %}
|
||||||
|
<div class="container">
|
||||||
|
<div class=" row">
|
||||||
|
<!-- cette boucle me permet d'afficher chaque element de datas dans une card -->
|
||||||
|
{% for elem in datas %}
|
||||||
|
<div class="col-12 col-md-4">
|
||||||
|
<div class="card mb-3" style="max-width: 440px;">
|
||||||
|
<div class="row no-gutters">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<img src={{elem.img_url}} class="card-img" alt="There is no available image for this book!">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">{{ elem.title }}</h5>
|
||||||
|
<p class="card-text">{{ elem.author }}</p>
|
||||||
|
<p class="card-text"><small class="text-muted">{{ elem.publish }}</small></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
Loading…
x
Reference in New Issue
Block a user