diff --git a/ras/api/login.py b/ras/api/login.py new file mode 100644 index 0000000..f641604 --- /dev/null +++ b/ras/api/login.py @@ -0,0 +1,101 @@ +import jwt, json +from django.contrib.auth import get_user_model +from rest_framework.decorators import api_view +from sqlalchemy import create_engine, insert +from sqlalchemy.sql import text +from django.http import JsonResponse +import ras.settings + +@api_view(['POST']) +def login(request): + username = request.POST.get('username') + password = request.POST.get('password') + + User = get_user_model() + try: + user = User.objects.get(username=username) + + if user.check_password(password): + payload = {'id': user.id, 'username': user.username} + jwt_token = {'token': jwt.encode(payload, 'secret', algorithm='HS256')} + return JsonResponse(jwt_token) + else: + return JsonResponse({'error': 'Wrong credentials'}) + except User.DoesNotExist: + return JsonResponse({'error': 'User does not exist'}) + +@api_view(['POST']) +def addBook(request): + if(request.headers.get('Authorization')): + token = request.headers.get('Authorization').split(' ')[1] + book = request.POST.get('book') + book = json.loads(book) + + try: + User = get_user_model() + payload = jwt.decode(token, 'secret', algorithms=['HS256']) + user = User.objects.get(id=payload['id']) + + if(user): + engine = create_engine('mysql+mysqldb://' + ras.settings.DATABASES['default']['USER'] + ':' + ras.settings.DATABASES['default']['PASSWORD'] + '@' + ras.settings.DATABASES['default']['HOST'] + ':3306/' + ras.settings.DATABASES['default']['NAME']) + conn = engine.connect() + conn.execute(text("INSERT INTO api_books (name, author, genre, country, country_code, pages, readed, rating) VALUES ('" + str(book['name']) + "', '" + str(book['author']) + "', '" + str(book['genre']) + "', '" + str(book['country']) + "', '" + str(book['country_code']) + "', " + str(book['pages']) + ", '" + str(book['readed']) + "', " + str(book['rating']) + ")")) + return JsonResponse("OK", safe=False) + else: + return JsonResponse({'error': 'No user detected'}, safe=False) + + except (jwt.DecodeError, User.DoesNotExist): + return JsonResponse({'error': 'Token invalid'}, safe=False) + else: + return JsonResponse({'error': 'testing'}, safe=False) + +@api_view(['PUT']) +def updateBook(request): + if(request.headers.get('Authorization')): + token = request.headers.get('Authorization').split(' ')[1] + book = request.POST.get('book') + book = json.loads(book) + bookid = request.headers.get('bookid') + + try: + User = get_user_model() + payload = jwt.decode(token, 'secret', algorithms=['HS256']) + user = User.objects.get(id=payload['id']) + + if(user): + engine = create_engine('mysql+mysqldb://' + ras.settings.DATABASES['default']['USER'] + ':' + ras.settings.DATABASES['default']['PASSWORD'] + '@' + ras.settings.DATABASES['default']['HOST'] + ':3306/' + ras.settings.DATABASES['default']['NAME']) + conn = engine.connect() + conn.execute(text("UPDATE api_books set name='" + str(book['name']) + "', author='" + str(book['author']) + "', genre='" + str(book['genre']) + "', country='" + str(book['country']) + "', country_code='" + str(book['country_code']) + "', pages='" + str(book['pages']) + "', readed='" + str(book['readed']) + "', rating='" + str(book['rating']) + "' WHERE id=" + str(bookid))) + + return JsonResponse("OK", safe=False) + else: + return JsonResponse({'error': 'No user detected'}, safe=False) + + except (jwt.DecodeError, User.DoesNotExist): + return JsonResponse({'error': 'Token invalid'}, safe=False) + else: + return JsonResponse({'error': 'No Token'}, safe=False) + +@api_view(['DELETE']) +def deleteBook(request): + if(request.headers.get('Authorization')): + token = request.headers.get('Authorization').split(' ')[1] + bookid = request.headers.get('bookid') + + try: + User = get_user_model() + payload = jwt.decode(token, 'secret', algorithms=['HS256']) + user = User.objects.get(id=payload['id']) + + if(user): + engine = create_engine('mysql+mysqldb://' + ras.settings.DATABASES['default']['USER'] + ':' + ras.settings.DATABASES['default']['PASSWORD'] + '@' + ras.settings.DATABASES['default']['HOST'] + ':3306/' + ras.settings.DATABASES['default']['NAME']) + conn = engine.connect() + conn.execute(text("DELETE FROM api_books WHERE id = " + str(bookid))) + return JsonResponse("OK", safe=False) + else: + return JsonResponse({'error': 'No user detected'}, safe=False) + + except (jwt.DecodeError, User.DoesNotExist): + return JsonResponse({'error': 'Token invalid'}, safe=False) + else: + return JsonResponse({'error': 'No Token'}, safe=False) \ No newline at end of file diff --git a/ras/api/migrations/0001_initial.py b/ras/api/migrations/0001_initial.py deleted file mode 100644 index cc41a0c..0000000 --- a/ras/api/migrations/0001_initial.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 4.1.1 on 2022-09-05 13:27 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ] - - operations = [ - migrations.CreateModel( - name='Books', - fields=[ - ('id', models.AutoField(primary_key=True, serialize=False)), - ('name', models.TextField(max_length=255)), - ('author', models.TextField(max_length=255)), - ('genre', models.TextField(max_length=100)), - ], - ), - ] diff --git a/ras/api/models.py b/ras/api/models.py index 0c71571..d91dad9 100644 --- a/ras/api/models.py +++ b/ras/api/models.py @@ -1,43 +1,43 @@ -from django.db import models +# from django.db import models -# Create your models here. -class Books(models.Model): - id = models.AutoField( - primary_key=True - ) +# # Create your models here. +# class Books(models.Model): +# id = models.AutoField( +# primary_key=True +# ) - name = models.TextField( - max_length=255, - null=False, - blank=False - ) +# name = models.TextField( +# max_length=255, +# null=False, +# blank=False +# ) - author = models.TextField( - max_length=255, - null=False, - blank=False - ) +# author = models.TextField( +# max_length=255, +# null=False, +# blank=False +# ) - genre = models.TextField( - max_length=100, - null=False, - blank=False - ) +# genre = models.TextField( +# max_length=100, +# null=False, +# blank=False +# ) - pages = models.TextField( - max_length=100, - null=False, - blank=False - ) +# pages = models.TextField( +# max_length=100, +# null=False, +# blank=False +# ) - readed = models.TextField( - max_length=100, - null=False, - blank=False - ) +# readed = models.TextField( +# max_length=100, +# null=False, +# blank=False +# ) - rating = models.TextField( - max_length=100, - null=False, - blank=False - ) \ No newline at end of file +# rating = models.TextField( +# max_length=100, +# null=False, +# blank=False +# ) \ No newline at end of file diff --git a/ras/api/serializers.py b/ras/api/serializers.py index 067fd39..37156b7 100644 --- a/ras/api/serializers.py +++ b/ras/api/serializers.py @@ -1,7 +1,7 @@ -from rest_framework import serializers -from .models import Books +# from rest_framework import serializers +# from .models import Books -class BooksSerializer(serializers.ModelSerializer): - class Meta: - model = Books - fields = ('id', 'name', 'author', 'genre') \ No newline at end of file +# class BooksSerializer(serializers.ModelSerializer): +# class Meta: +# model = Books +# fields = ('id', 'name', 'author', 'genre') \ No newline at end of file diff --git a/ras/api/static/books_data.csv b/ras/api/static/books_data.csv new file mode 100644 index 0000000..a471197 --- /dev/null +++ b/ras/api/static/books_data.csv @@ -0,0 +1,5 @@ +year,books_read +2013,1 +2020,10 +2021,36 +2022,24 \ No newline at end of file diff --git a/ras/api/urls.py b/ras/api/urls.py index 7cdb1aa..cddbd40 100644 --- a/ras/api/urls.py +++ b/ras/api/urls.py @@ -1,11 +1,17 @@ -from django.urls import path +from django.urls import path, include from .views import * +from .login import * urlpatterns = [ path('books', getAllBooks), path('books/challenge', getChallengeOfYear), path('books/years', getYears), path('books/stats', getStats), + path('books/predict', predictAmountBooks), + + path('books/insert', addBook), + path('books/delete', deleteBook), + path('books/update', updateBook), path('books/pages/stats', getStatsPages), path('books/pages', pages_per_month), @@ -14,4 +20,7 @@ urlpatterns = [ path('books/genres/count', countGenres), path('books/authors', books_per_author), path('books/countries', books_per_country), + + path('auth/login', login), + ] \ No newline at end of file diff --git a/ras/api/views.py b/ras/api/views.py index 9e60d71..0924db2 100644 --- a/ras/api/views.py +++ b/ras/api/views.py @@ -1,12 +1,14 @@ from sqlite3 import connect from rest_framework.decorators import api_view from rest_framework.response import Response -from .models import Books import pandas as pd import ras.settings +import math + +from sklearn.linear_model import LinearRegression +from sklearn.metrics import mean_squared_error from sqlalchemy import create_engine -from .serializers import BooksSerializer from django.db.models import Q from django.templatetags.static import static import json @@ -252,4 +254,25 @@ def getYears(request): years = df.groupby('year')['year'].count().reset_index(name="count") - return Response(years['year']) \ No newline at end of file + return Response(years['year']) + +@api_view(['GET']) +def predictAmountBooks(request): + books_data = pd.read_csv("api/static/books_data.csv") + + books_data = books_data.dropna() + + model = LinearRegression() + + X = books_data[['year']] + Y = books_data['books_read'] + model.fit(X.values, Y.values) + + current_year = 2023 + predict_books = model.predict([[current_year]]) + + return Response({ + "year": current_year, + "amount": math.floor(predict_books[0]) + }) + # return Response(f"The amount of books i'm gonna read in {current_year} is {math.floor(predict_books[0])}") \ No newline at end of file diff --git a/ras/ras/urls.py b/ras/ras/urls.py index cc36bb4..a6e3f1c 100644 --- a/ras/ras/urls.py +++ b/ras/ras/urls.py @@ -20,5 +20,5 @@ urlpatterns = [ path('admin/', admin.site.urls), path('api/', include('api.urls')), path('', include('frontend.urls')), - path('booklist/', include('frontend.urls')), + path('booklist/', include('frontend.urls')) ] diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..179f192 Binary files /dev/null and b/requirements.txt differ