Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge front features into main #2

Merged
merged 9 commits into from
Nov 2, 2022
41 changes: 41 additions & 0 deletions api/db/articles.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from django.db import connection
from ..models import Article


def most_negative_articles(year, month, keyword='', results=5):
query, params = prepare_query(keyword, year, month, results)
with connection.cursor() as cursor:
cursor.execute(query, params)
rows = cursor.fetchall()
print('executing query: ', connection.queries)
return transform_qs(rows)


def prepare_query(keyword, year, month, limit):
keyword = f"%{keyword.upper()}%"
year = str(year)
month = month_to_str(month)
params = [year, month, keyword, limit]
query = """
select a.text, a.date, a.sentiment, a.url
from api_article as a
where strftime('%%Y', a.date) = %s
and strftime('%%m', a.date) = %s
and UPPER(a.text) LIKE %s
order by a.sentiment
limit %s;"""
return query, params


# list of (year, mo, sentiment) triples
def transform_qs(queryset):
return list(map(
lambda row: Article(text=row[0], date=row[1], sentiment=row[2], url=row[3]),
queryset
))


def month_to_str(month):
if month < 10:
return '0' + str(month)
return str(month)
56 changes: 56 additions & 0 deletions api/db/sentiment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from datetime import date
from django.db import connection
from ..models import DatePoint, Article


def get_sentiment_list(keyword, start_date=None, end_date=None):
"""
fetches a list of DatePoints which contain month,
year and average sentiment for a given keyword
"""
query, params = prepare_query(keyword, start_date, end_date)
with connection.cursor() as cursor:
cursor.execute(query, params)
rows = cursor.fetchall()
print('executing query: ', connection.queries)
# list of (year, mo, sentiment) triples
return transform_qs(rows)


def prepare_query(keyword, start_date, end_date):
keyword = f"%{keyword.upper()}%"
params = [keyword]
date_stmt, date_params = prepare_date_stmt(start_date, end_date)
params.extend(date_params)
# %% is used for single %
# single quotes are set automatically around parameters
query = f"""select strftime('%%Y', a.date), strftime('%%m', a.date), avg(a.sentiment)
from api_article a
where UPPER(a.text) LIKE %s {date_stmt}
group by strftime('%%Y', a.date), strftime('%%m', a.date)"""
return query, params


# list of (year, mo, sentiment) triples
def transform_qs(queryset):
return list(map(
lambda row: DatePoint(date=date(int(row[0]), int(row[1]), 1), sentiment=row[2]),
queryset
))


def prepare_date_stmt(start_date, end_date):
date_stmt = ''
params = []
if start_date and end_date:
date_stmt = "and a.date between %s and %s"
params.append(start_date)
params.append(end_date)
elif start_date:
date_stmt = "and a.date >= %s"
params.append(start_date)
elif end_date:
date_stmt = "and a.date <= %s"
params.append(end_date)
return date_stmt, params

8 changes: 6 additions & 2 deletions api/serializers.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
from rest_framework import serializers
from .models import DatePoint
from .models import DatePoint, Article


class DatePointSerializer(serializers.ModelSerializer):
class Meta:
model = DatePoint
fields = ["date", "sentiment"]



class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ['text', 'sentiment', 'date', 'url']
6 changes: 4 additions & 2 deletions api/urls.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from django.urls import path
from .views import DatePointView
from .views import DatePointView, MostNegativeArticles
# additional urls.py file to define urls for this api

urlpatterns = [
path('', DatePointView.as_view())
path('', DatePointView.as_view()),
path('/most-negative-articles/<int:year>/<int:month>',
MostNegativeArticles.as_view())
]
81 changes: 20 additions & 61 deletions api/views.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import DatePoint, Article
from .serializers import DatePointSerializer
from datetime import date
from django.db import connection
from django.db.models import Q
from .db.sentiment import get_sentiment_list
from .db.articles import most_negative_articles
from .serializers import DatePointSerializer, ArticleSerializer


class DatePointView(APIView):
"""/api?keyword=keyword&start-date=date&end-date=date"""
def get(self, request, *args, **kwargs):
data = request.GET
queryset = get_sentiment(
queryset = get_sentiment_list(
data.get('keyword'),
data.get('start-date'),
data.get('end-date')
Expand All @@ -21,59 +19,20 @@ def get(self, request, *args, **kwargs):
return Response(serializer.data, status=status.HTTP_200_OK)


def get_sentiment(keyword, start_date=None, end_date=None):
query, params = prepare_query(keyword, start_date, end_date)
with connection.cursor() as cursor:
cursor.execute(query, params)
rows = cursor.fetchall()
print('executing query: ', connection.queries)
# list of (year, mo, sentiment) triples
return transform_qs(rows)


def prepare_query(keyword, start_date, end_date):
keyword = f"%{keyword.upper()}%"
params = [keyword]
date_stmt, date_params = prepare_date_stmt(start_date, end_date)
params.extend(date_params)
# %% is used for single %
# single quotes are set automatically around parameters
query = f"""select strftime('%%Y', a.date), strftime('%%m', a.date), avg(a.sentiment)
from api_article a
where UPPER(a.text) LIKE %s {date_stmt}
group by strftime('%%Y', a.date), strftime('%%m', a.date)"""
return query, params


# list of (year, mo, sentiment) triples
def transform_qs(queryset):
return list(map(
lambda row: DatePoint(date=date(int(row[0]), int(row[1]), 1), sentiment=row[2]),
queryset
))


def prepare_date_stmt(start_date, end_date):
date_stmt = ''
params = []
if start_date and end_date:
date_stmt = "and a.date between %s and %s"
params.append(start_date)
params.append(end_date)
elif start_date:
date_stmt = "and a.date >= %s"
params.append(start_date)
elif end_date:
date_stmt = "and a.date <= %s"
params.append(end_date)
return date_stmt, params
class MostNegativeArticles(APIView):
"""/api/most-negative-articles/year/month?keyword=keyword&results=number"""
def get(self, request, *args, **kwargs):
# todo input validation
results = 5
if request.GET.get('results'):
results = request.GET.get('results')
queryset = most_negative_articles(
kwargs.get('year'),
kwargs.get('month'),
keyword=request.GET.get('keyword'),
results=results
)
serializer = ArticleSerializer(queryset, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)


# def get_sentiment(keyword, start_date=None, end_date=None):
# # case insensitive
# q1 = Q(text__icontains=keyword)
# # date greater than start date
# q2 = Q(date__gte=start_date)
# # date less than end date
# q3 = Q(date_lte=end_date)
# data = Article.objects.filter(q1 & q2 & q3)
Loading