1+ """
2+ views.py includes the main business logic of the application.
3+ Its role is to manage file upload, deletion and predictions.
4+ """
5+
16import os
7+ from os import listdir
8+ from os .path import join
9+ from os .path import isfile
10+
211import keras
312import librosa
413import numpy as np
5- from os import listdir
614import tensorflow as tf
7- from App .models import FileModel
8- from rest_framework import views
915from django .conf import settings
10- from os .path import isfile , join
11- from rest_framework import status
12- from App .serialize import FileSerializer
13- from rest_framework .response import Response
1416from django .views .generic import TemplateView
1517from django .views .generic .edit import CreateView
18+ from rest_framework import views
19+ from rest_framework import status
20+ from rest_framework import generics
21+ from rest_framework .parsers import FormParser
22+ from rest_framework .parsers import MultiPartParser
23+ from rest_framework .response import Response
1624from rest_framework .renderers import TemplateHTMLRenderer
17- from rest_framework .parsers import MultiPartParser , FormParser
25+
26+ from App .models import FileModel
27+ from App .serialize import FileSerializer
1828
1929
2030class IndexView (TemplateView ):
@@ -48,7 +58,29 @@ class SelectPredFileView(TemplateView):
4858 The server will return the predictions.
4959 """
5060
51- template_name = "select_file_predictions.html"
61+ template_name = 'select_file_predictions.html'
62+ parser_classes = FormParser
63+ queryset = FileModel .objects .all ()
64+
65+ def get_context_data (self , ** kwargs ):
66+ """
67+ This function is used to render the list of file in the MEDIA_ROOT in the html template.
68+ """
69+ context = super ().get_context_data (** kwargs )
70+ media_path = settings .MEDIA_ROOT
71+ myfiles = [f for f in listdir (media_path ) if isfile (join (media_path , f ))]
72+ context ['filename' ] = myfiles
73+ return context
74+
75+
76+ class SelectFileDelView (TemplateView ):
77+ """
78+ This view is used to select a file from the list of files in the server.
79+ After the selection, it will send the file to the server.
80+ The server will delete the file.
81+ """
82+ template_name = 'select_file_deletion.html'
83+
5284 parser_classes = FormParser
5385 queryset = FileModel .objects .all ()
5486
@@ -65,8 +97,8 @@ def get_context_data(self, **kwargs):
6597
6698class FileView (views .APIView ):
6799 """
68- This class contains the method to upload and delete a file interacting directly with the API.
69- POST and DELETE request are accepted.
100+ This class contains the method to upload a file interacting directly with the API.
101+ POST requests are accepted.
70102 """
71103 parser_classes = (MultiPartParser , FormParser )
72104 queryset = FileModel .objects .all ()
@@ -79,34 +111,52 @@ def upload(self, request):
79111 if file_serializer .is_valid ():
80112 # TODO: implement a check to see if the file is already on the server
81113 file_serializer .save ()
82- return Response (file_serializer .data , status = status .HTTP_201_CREATED )
114+ response = Response (file_serializer .data , status = status .HTTP_201_CREATED )
83115 else :
84- return Response (file_serializer .errors , status = status .HTTP_400_BAD_REQUEST )
116+ response = Response (file_serializer .errors , status = status .HTTP_400_BAD_REQUEST )
85117
86- def delete (self , request ):
87- # TODO: Implement
88- raise NotImplementedError
118+ return response
119+
120+
121+ class FileDeleteView (generics .RetrieveDestroyAPIView ):
122+ """
123+ This class contains the method to delete a file interacting directly with the API.
124+ DELETE requests are accepted.
125+ """
126+
127+ parser_classes = FormParser
128+ queryset = FileModel .objects .all ()
129+
130+ def post (self , request ):
131+ """
132+ This method will be used to delete files from the server.
133+ """
134+ # TODO: complete, not working (error: type "object" is not iterable)
135+ filename = request .POST .getlist ('file_name' ).pop ()
136+ getfile = FileModel .objects .filter (name__in = filename )
137+ getfile .file .delete ()
138+ return getfile
89139
90140
91141class Predict (views .APIView ):
92142 """
93143 This class is used to making predictions.
94144
95145 Example of input:
96- {" filename": " 01-01-01-01-01-01-01.wav" }
146+ {' filename': ' 01-01-01-01-01-01-01.wav' }
97147
98148 Example of output:
99- [[" neutral" ]]
149+ [[' neutral' ]]
100150 """
101151
102152 template_name = 'index.html'
153+ # Removing this shows the API view to the user instead of the template.
103154 renderer_classes = [TemplateHTMLRenderer ]
104155
105156 def __init__ (self , ** kwargs ):
106157 super ().__init__ (** kwargs )
107158 modelname = 'Emotion_Voice_Detection_Model.h5'
108- global graph
109- graph = tf .get_default_graph ()
159+ self .graph = tf .get_default_graph ()
110160 self .loaded_model = keras .models .load_model (os .path .join (settings .MODEL_ROOT , modelname ))
111161 self .predictions = []
112162
@@ -118,26 +168,28 @@ def file_elaboration(self, filepath):
118168 """
119169 data , sampling_rate = librosa .load (filepath )
120170 try :
121- mfccs = np .mean (librosa .feature .mfcc (y = data , sr = sampling_rate , n_mfcc = 40 ).T , axis = 0 )
122- x = np .expand_dims (mfccs , axis = 2 )
123- x = np .expand_dims (x , axis = 0 )
124- numpred = self .loaded_model .predict_classes (x )
171+ mfccs = np .mean (librosa .feature .mfcc (y = data , sr = sampling_rate ,
172+ n_mfcc = 40 ).T , axis = 0 )
173+ training_data = np .expand_dims (mfccs , axis = 2 )
174+ training_data_expanded = np .expand_dims (training_data , axis = 0 )
175+ numpred = self .loaded_model .predict_classes (training_data_expanded )
125176 self .predictions .append ([self .classtoemotion (numpred )])
126177 return self .predictions
127- except Exception as err :
178+ except ValueError as err :
128179 return Response (str (err ), status = status .HTTP_400_BAD_REQUEST )
129180
130181 def post (self , request ):
131182 """
132- This method is used to making predictions on audio files previously loaded with FileView.post
183+ This method is used to making predictions on audio files
184+ loaded with FileView.post
133185 """
134- with graph .as_default ():
186+ with self . graph .as_default ():
135187 filename = request .POST .getlist ('file_name' ).pop ()
136188 filepath = str (os .path .join (settings .MEDIA_ROOT , filename ))
137189 predictions = self .file_elaboration (filepath )
138190 try :
139191 return Response ({'predictions' : predictions .pop ()})
140- except Exception as err :
192+ except ValueError as err :
141193 return Response (str (err ), status = status .HTTP_400_BAD_REQUEST )
142194
143195 return Response (predictions , status = status .HTTP_200_OK )
@@ -150,20 +202,20 @@ def classtoemotion(pred):
150202 ::output:: A string label
151203
152204 Example:
153- >>> classtoemotion(0) == neutral
205+ classtoemotion(0) == neutral
154206 """
155207
156- label_conversion = {"0" : " neutral" ,
157- "1" : " calm" ,
158- "2" : " happy" ,
159- "3" : " sad" ,
160- "4" : " angry" ,
161- "5" : " fearful" ,
162- "6" : " disgust" ,
163- "7" : " surprised" }
208+ label_conversion = {'0' : ' neutral' ,
209+ '1' : ' calm' ,
210+ '2' : ' happy' ,
211+ '3' : ' sad' ,
212+ '4' : ' angry' ,
213+ '5' : ' fearful' ,
214+ '6' : ' disgust' ,
215+ '7' : ' surprised' }
164216
165- for key in label_conversion .keys ():
217+ for key , value in label_conversion .items ():
166218 if int (key ) == pred :
167- return label_conversion [ key ]
168- else :
169- continue
219+ label = value
220+
221+ return label
0 commit comments