Data + Graph for books per month per genre
This commit is contained in:
parent
cc371244ef
commit
2318f741a4
|
@ -0,0 +1,65 @@
|
|||
book;author;genre;pages;readed;rating
|
||||
Omnia in Omnibus;Lisa Pennings;Sciencefiction;166;05-2013;4
|
||||
Het leven van Pi;Yann Martel;Roman;317;10-2020;4
|
||||
Ze komt nooit meer terug;Hans Koppel;Thriller;220;10-2020;5
|
||||
Vriendschapsverzoek;Laura Marshall;Thriller;368;10-2020;4
|
||||
De analist;John Katzenbach;Thriller;518;11-2020;4
|
||||
Komt een vrouw bij de hacker;Maria Genova;Thriller;224;11-2020;4
|
||||
Niemand hoort het;Linwood Barclay;Thriller;304;11-2020;5
|
||||
Lift;Linwood Barclay;Thriller;480;11-2020;3
|
||||
Kijk niet weg;Linwood Barclay;Thriller;400;12-2020;5
|
||||
Het duistere net;Carmen Mola;Thriller;415;12-2020;5
|
||||
De 50/50-moorden;Steve Mosby;Thriller;344;12-2020;3
|
||||
Zonder een woord;Linwood Barclay;Thriller;368;01-2021;5
|
||||
Geen veilige plek;Linwood Barclay;Thriller;368;01-2021;3
|
||||
Op slot;Chris McGeorge;Thriller;320;01-2021;5
|
||||
Alles is eventueel / 1408;Stephen King;Thriller;462;02-2021;3
|
||||
Waarom je niet zomaar moet stemmen waar je ouders op stemmen;Titia Hoogendoorn&Nienke Schuitemaker;Non-fictie;125;02-2021;4
|
||||
Geloof je ogen;Linwood Barclay;Thriller;384;02-2021;4
|
||||
Voor ik ga slapen;SJ Watson;Thriller;333;03-2021;5
|
||||
Echo;Tamara Geraeds;Thriller;280;03-2021;5
|
||||
Niemand vertellen;Harlan Coben;Thriller;302;03-2021;4
|
||||
Ik zie je;Michael Berg;Thriller;320;04-2021;4
|
||||
Toevluchtsoord;Jerome Loubry;Thriller;355;04-2021;5
|
||||
In een donker donker bos;Ruth Ware;Thriller;320;04-2021;3
|
||||
Een voor een;Ruth Ware;Thriller;368;04-2021;4
|
||||
Vrees het ergste;Linwood Barclay;Thriller;400;05-2021;4
|
||||
Het poppenhuis;W.R. Dantz;Thriller;270;05-2021;3
|
||||
Malorie;Josh Malerman;Thriller;320;05-2021;4
|
||||
Opgejaagd;Gabriel Bergmoser;Thriller;256;06-2021;4
|
||||
Reset;Blake Crouch;Thriller;352;06-2021;4
|
||||
Wacht maar af;Loes den Hollander;Thriller;300;06-2021;4
|
||||
De Russische connectie;Gerrit Barendrecht;Thriller;320;06-2021;4
|
||||
Wat jij niet ziet;M.J. Arlidge;Thriller;95;07-2021;3
|
||||
Het ongeluk;Linwood Barclay;Thriller;382;07-2021;4
|
||||
Slapen in een zee van sterren;Christopher Paolini;Sciencefiction;880;07-2021;2
|
||||
Tik Tak;Chris McGeorge;Thriller;320;07-2021;4
|
||||
Gegijzeld;Clare Mackintosh;Thriller;397;08-2021;5
|
||||
Eindbestemming;Marjolein van der Gaag&Marcella Kleine;Thriller;158;08-2021;4
|
||||
Een kille rilling;Bernard Minier;Thriller;582;09-2021;4
|
||||
De nachtdienst;Esther Verhoef;Thriller;365;09-2021;5
|
||||
Kiekeboe;Chris McGeorge;Thriller;352;10-2021;3
|
||||
Noorderlicht;Mariska Overman;Thriller;313;10-2021;4
|
||||
De kleine getuige;Jilliane Hoffman;Thriller;368;11-2021;4
|
||||
De marathon;Stephen King;Thriller;261;11-2021;4
|
||||
Het appartement;Tatiana de Rosnay;Roman;215;11-2021;4
|
||||
De intrigant;Patricia Snel;Thriller;189;12-2021;4
|
||||
Een schuldig huis;Robert Goddard;Thriller;384;12-2021;5
|
||||
Te koop;Eva Monte;Thriller;350;12-2021;3
|
||||
Prison Break S1B1;Paul T. Scheuring;Thriller;221;01-2022;5
|
||||
Prison Break S1B2;Ed van Eeden;Thriller;272;01-2022;4
|
||||
Prison Break S1B3;Paul T. Scheuring;Thriller;285;01-2022;4
|
||||
Herfstlied;Simone van der Vlugt;Thriller;277;02-2022;5
|
||||
De gastenlijst;Lucy Foley;Thriller;352;02-2022;2
|
||||
Anomalie;Herve le Tellier;Thriller;302;02-2022;2
|
||||
Prison Break S2B1;Paul T. Scheuring;Thriller;207;03-2022;4
|
||||
Prison Break S2B2;Paul T. Scheuring;Thriller;205;03-2022;4
|
||||
Prison Break S2B3;Paul T. Scheuring;Thriller;245;03-2022;4
|
||||
Ik weet je wachtwoord;Daniel Verlaan;Non-fictie;347;04-2022;5
|
||||
De vrouw die een jaar in bed ging liggen;Sue Townsend;Roman;368;04-2022;3
|
||||
Moord in de bibliotheek;Agatha Christie;Thriller;256;04-2022;3
|
||||
Geestdrift;Daniel Hecht;Thriller;509;05-2022;1
|
||||
Moord in de Orient Expres;Agatha Christie;Thriller;222;05-2022;4
|
||||
Crash;Jack Bowman;Thriller;344;05-2022;3
|
||||
Erken mij;Esther Verhoef;Thriller;91;06-2022;4
|
||||
Gestrand;Sarah Goodwin;Thriller;352;06-2022;5
|
|
|
@ -3,5 +3,5 @@ from .views import *
|
|||
|
||||
urlpatterns = [
|
||||
path('books', api_all_books),
|
||||
path('books/<int:_id>', api_get_book),
|
||||
path('books/genres', books_per_genre_per_month)
|
||||
]
|
|
@ -1,26 +1,55 @@
|
|||
from rest_framework.decorators import api_view
|
||||
from rest_framework.response import Response
|
||||
from .models import Books
|
||||
import pandas as pd
|
||||
|
||||
from .serializers import BooksSerializer
|
||||
from django.db.models import Q
|
||||
|
||||
from django.templatetags.static import static
|
||||
import json
|
||||
|
||||
@api_view(['GET'])
|
||||
def api_all_books(request):
|
||||
all_books = Books.objects.all()
|
||||
if all_books:
|
||||
serializer = BooksSerializer(all_books, many=True)
|
||||
return Response(serializer.data)
|
||||
else:
|
||||
return Response({"Message": 'Books Not Found'})
|
||||
df = pd.read_csv("api/static/books2.csv", encoding = "utf-8")
|
||||
books = []
|
||||
for book in df['Books']:
|
||||
info = book.split(';')
|
||||
books.append({
|
||||
"name": info[0],
|
||||
"author": info[1],
|
||||
"genre": info[2],
|
||||
"pages": info[3],
|
||||
"readed": info[4],
|
||||
"rating": info[5]
|
||||
})
|
||||
return Response(books)
|
||||
|
||||
@api_view(['GET'])
|
||||
def api_get_book(request, _id):
|
||||
def books_per_genre_per_month(request):
|
||||
|
||||
obj = Books.objects.filter(id = _id)[0]
|
||||
if obj:
|
||||
serializer = BooksSerializer(obj)
|
||||
return Response(serializer.data)
|
||||
datayear = request.META.get('HTTP_YEAR')
|
||||
|
||||
if datayear:
|
||||
|
||||
data = []
|
||||
|
||||
# Get CSV file with book data
|
||||
df = pd.read_csv("api/static/books2.csv", encoding = "utf-8", header = 0, sep=';')
|
||||
|
||||
# Filter data on year
|
||||
df = df.where(df['readed'].str.contains(datayear))
|
||||
|
||||
# Filter array on genre and date
|
||||
booksPerMonth = df.groupby(['genre','readed'])['genre'].count().reset_index(name="count")
|
||||
booksPerMonth = booksPerMonth.sort_values(by='readed')
|
||||
|
||||
for index, row in booksPerMonth.iterrows():
|
||||
data.append({
|
||||
"genre": row['genre'],
|
||||
"readed": row['readed'],
|
||||
"count": row['count']
|
||||
})
|
||||
|
||||
return Response(data)
|
||||
else:
|
||||
return Response({"Message": 'Book Not Found'})
|
||||
return Response("No year header included")
|
|
@ -1,15 +1,119 @@
|
|||
import React, { Component } from "react"
|
||||
import {render} from "react-dom"
|
||||
import React, { Component } from "react";
|
||||
|
||||
export default class App extends Component{
|
||||
export default class App extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render(){
|
||||
return <p>Soon here comes the Reading Analytics System!</p>
|
||||
}
|
||||
}
|
||||
initChart(data, year) {
|
||||
|
||||
const appDiv = document.getElementById("app");
|
||||
render(<App />, appDiv);
|
||||
var genres = [];
|
||||
|
||||
var colors = [
|
||||
'#d0b2cf', '#b66f2b', '#003C72', '#ecdb0e'
|
||||
]
|
||||
|
||||
var dataSet = [];
|
||||
|
||||
data.forEach(book => {
|
||||
if (!genres.includes(book.genre)) {
|
||||
genres.push(book.genre)
|
||||
}
|
||||
});
|
||||
|
||||
if (genres && genres.length > 0) {
|
||||
genres.forEach((genre, index) => {
|
||||
var genreData = [];
|
||||
|
||||
for (var i = 0; i < 12; i++) {
|
||||
|
||||
genreData[i] = 0;
|
||||
|
||||
if ((i + 1) < 10) {
|
||||
var month = "0" + (i + 1);
|
||||
} else {
|
||||
month = (i + 1);
|
||||
}
|
||||
|
||||
for (var j = 0; j < data.length; j++) {
|
||||
if (data && data[j] && data[j].readed == month + '-' + year) {
|
||||
if (data[j].genre == genre) {
|
||||
genreData[i] = data[j].count;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dataSet.push({
|
||||
label: genre,
|
||||
data: genreData,
|
||||
backgroundColor: colors[index]
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
new Chart(document.getElementById('chart'), {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: ["Januari", "Februari", "Maart", "April", "Mei", "Juni", "Juli", "Augustus", "September", "Oktober", "November", "December"],
|
||||
datasets: dataSet
|
||||
},
|
||||
options: {
|
||||
legend: {
|
||||
display: true,
|
||||
},
|
||||
tooltips: {
|
||||
mode: 'index',
|
||||
intersect: true,
|
||||
axis: 'y'
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
ticks: {
|
||||
beginAtZero: true,
|
||||
|
||||
},
|
||||
stacked: true,
|
||||
},
|
||||
y: {
|
||||
ticks: {
|
||||
beginAtZero: true,
|
||||
stepSize: 1
|
||||
},
|
||||
stacked: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
||||
var currentyear = new Date().getFullYear()
|
||||
|
||||
console.log(currentyear);
|
||||
|
||||
fetch('/api/books/genres', {
|
||||
"method": "GET",
|
||||
"headers": {
|
||||
"year": currentyear
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
this.initChart(data, currentyear);
|
||||
console.log(data);
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<canvas id="chart"></canvas>
|
||||
<p>Soon here comes the Reading Analytics System! test</p>
|
||||
</React.Fragment>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1 +1,5 @@
|
|||
import App from "./App";
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from "./App";
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById('app'));
|
File diff suppressed because one or more lines are too long
|
@ -26,6 +26,7 @@
|
|||
<div id="app"></div>
|
||||
</div>
|
||||
|
||||
<script src="{% static "frontend/main.js" %}"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="{% static "js/main.js" %}"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/4.1/ref/settings/
|
|||
"""
|
||||
|
||||
from pathlib import Path
|
||||
import os
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
|
@ -131,6 +132,10 @@ USE_TZ = True
|
|||
# https://docs.djangoproject.com/en/4.1/howto/static-files/
|
||||
|
||||
STATIC_URL = 'static/'
|
||||
STATICFILES_DIR = [
|
||||
BASE_DIR / 'static'
|
||||
]
|
||||
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
|
||||
|
||||
# Default primary key field type
|
||||
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field
|
||||
|
|
Loading…
Reference in New Issue