Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • kj2-drupisz/desd
1 result
Select Git revision
Show changes
Commits on Source (2)
Showing
with 328 additions and 80 deletions
...@@ -19,6 +19,7 @@ services: ...@@ -19,6 +19,7 @@ services:
volumes: volumes:
- .:/usr/src/app - .:/usr/src/app
- static_volume:/usr/src/app/static - static_volume:/usr/src/app/static
- ./models:/usr/src/app/models
depends_on: depends_on:
- db - db
- tensorflow_serving - tensorflow_serving
......
؋סȭʏ Ԛʘ(Ǜ 2
\ No newline at end of file
No preview for this file type
No preview for this file type
No preview for this file type
# Generated by Django 5.0.1 on 2024-04-30 23:25
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('myapp', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='ModelConfig',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('selected_model_version', models.CharField(default='2', max_length=255)),
],
),
]
# Generated by Django 5.0.1 on 2024-05-01 00:07
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('myapp', '0002_modelconfig'),
]
operations = [
migrations.CreateModel(
name='ModelPerformanceMetrics',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('request_count', models.IntegerField(default=0)),
('request_latency_sum', models.FloatField(default=0)),
('request_latency_count', models.IntegerField(default=0)),
('runtime_latency_sum', models.FloatField(default=0)),
('runtime_latency_count', models.IntegerField(default=0)),
('model_load_latency', models.FloatField(default=0)),
],
),
]
# Generated by Django 5.0.1 on 2024-05-01 00:39
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('myapp', '0003_modelperformancemetrics'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Payment',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('amount', models.DecimalField(decimal_places=2, max_digits=10)),
('payment_id', models.CharField(max_length=255)),
('payer_id', models.CharField(max_length=255)),
('date', models.DateTimeField(auto_now_add=True)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]
...@@ -57,3 +57,43 @@ class Log(models.Model): ...@@ -57,3 +57,43 @@ class Log(models.Model):
log = models.JSONField() log = models.JSONField()
feedback = models.BooleanField(null=True) feedback = models.BooleanField(null=True)
class ModelConfig(models.Model):
selected_model_version = models.CharField(max_length=255, default='2')
def save(self, *args, **kwargs):
# Ensure there's only one instance of ModelConfig
self.pk = 1
super().save(*args, **kwargs)
@classmethod
def load(cls):
obj, _ = cls.objects.get_or_create(pk=1)
return obj
class ModelPerformanceMetrics(models.Model):
request_count = models.IntegerField(default=0)
request_latency_sum = models.FloatField(default=0)
request_latency_count = models.IntegerField(default=0)
runtime_latency_sum = models.FloatField(default=0)
runtime_latency_count = models.IntegerField(default=0)
model_load_latency = models.FloatField(default=0)
def reset_metrics(self):
self.request_count = 0
self.request_latency_sum = 0
self.request_latency_count = 0
self.runtime_latency_sum = 0
self.runtime_latency_count = 0
self.model_load_latency = 0
self.save(force_update=True)
class Payment(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
amount = models.DecimalField(max_digits=10, decimal_places=2)
payment_id = models.CharField(max_length=255)
payer_id = models.CharField(max_length=255)
date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f'Payment by {self.user.username} - Amount: {self.amount}'
...@@ -5,7 +5,7 @@ from django.shortcuts import redirect, render ...@@ -5,7 +5,7 @@ from django.shortcuts import redirect, render
from django.urls import reverse from django.urls import reverse
from django.shortcuts import redirect, render from django.shortcuts import redirect, render
from django.urls import reverse from django.urls import reverse
from .models import Action, UserTokenCount from .models import Action, UserTokenCount, Payment
from .views import get_log_data, create_log from .views import get_log_data, create_log
# Create a payment that can be made via the PayPal API # Create a payment that can be made via the PayPal API
# Create a payment that can be made via the PayPal API # Create a payment that can be made via the PayPal API
...@@ -60,18 +60,61 @@ def create_payment(request): ...@@ -60,18 +60,61 @@ def create_payment(request):
# Execute a successful payment # Execute a successful payment
# def execute_payment(request):
# # Get payment id and payer id
# payment_id = request.GET.get('paymentId')
# payer_id = request.GET.get('PayerID')
# #If neither ID, error, restart
# if not payment_id or not payer_id:
# print("no payment")
# #TODO: Change this to a more appropriate path, maybe a generic error page that takes a string:Error to display in a template
# return redirect('handler404')
# # configure API
# paypalrestsdk.configure({
# "mode": settings.PAYPAL_MODE,
# "client_id": settings.PAYPAL_CLIENT_ID,
# "client_secret": settings.PAYPAL_CLIENT_SECRET
# })
# # Check we've got a successful payment
# payment = paypalrestsdk.Payment.find(payment_id)
# # If it we do an the payer IDs match
# if payment.execute({"payer_id": payer_id}):
# print("Payment executed successfully!")
# # Allocate some tokens
# user = request.user
# tokens_purchased = 1
# # increment user_tokens
# # commit changes
# # TODO: Change something here such that the token amount added depends on a detail of the transaction,
# # i.e. £9.99 payment for one token or £24.99 for
# #
# if request.user.is_authenticated:
# add_tokens(user, tokens_purchased)
# return redirect('success')
# else:
# return redirect('handler404')
# else:
# #TODO: Change this to a more appropriate error message
# print("exiting at the end of execute_payment()")
# return redirect('handler404')
def execute_payment(request): def execute_payment(request):
# Get payment id and payer id # Get payment id and payer id
payment_id = request.GET.get('paymentId') payment_id = request.GET.get('paymentId')
payer_id = request.GET.get('PayerID') payer_id = request.GET.get('PayerID')
#If neither ID, error, restart # If neither ID, error, restart
if not payment_id or not payer_id: if not payment_id or not payer_id:
print("no payment") print("No payment")
#TODO: Change this to a more appropriate path, maybe a generic error page that takes a string:Error to display in a template
return redirect('handler404') return redirect('handler404')
# configure API # Configure API
paypalrestsdk.configure({ paypalrestsdk.configure({
"mode": settings.PAYPAL_MODE, "mode": settings.PAYPAL_MODE,
"client_id": settings.PAYPAL_CLIENT_ID, "client_id": settings.PAYPAL_CLIENT_ID,
...@@ -81,7 +124,7 @@ def execute_payment(request): ...@@ -81,7 +124,7 @@ def execute_payment(request):
# Check we've got a successful payment # Check we've got a successful payment
payment = paypalrestsdk.Payment.find(payment_id) payment = paypalrestsdk.Payment.find(payment_id)
# If it we do an the payer IDs match # If it we do and the payer IDs match
if payment.execute({"payer_id": payer_id}): if payment.execute({"payer_id": payer_id}):
print("Payment executed successfully!") print("Payment executed successfully!")
...@@ -89,22 +132,24 @@ def execute_payment(request): ...@@ -89,22 +132,24 @@ def execute_payment(request):
user = request.user user = request.user
tokens_purchased = 1 tokens_purchased = 1
# increment user_tokens
# commit changes
# TODO: Change something here such that the token amount added depends on a detail of the transaction,
# i.e. £9.99 payment for one token or £24.99 for
#
if request.user.is_authenticated: if request.user.is_authenticated:
add_tokens(user, tokens_purchased) add_tokens(user, tokens_purchased)
# Save payment details to the database
Payment.objects.create(
user=user,
amount=payment.transactions[0].amount.total,
payment_id=payment_id,
payer_id=payer_id
)
return redirect('success') return redirect('success')
else: else:
return redirect('handler404') return redirect('handler404')
else: else:
#TODO: Change this to a more appropriate error message print("Payment execution failed")
print("exiting at the end of execute_payment()")
return redirect('handler404') return redirect('handler404')
def add_tokens(user, tokens): def add_tokens(user, tokens):
token_count_instance, created = UserTokenCount.objects.get_or_create(user=user) token_count_instance, created = UserTokenCount.objects.get_or_create(user=user)
token_count_instance.token_count += tokens token_count_instance.token_count += tokens
......
<!-- model_performance.html -->
{% extends "_base.html" %} {% extends "_base.html" %}
{% block content %} {% block content %}
<div class="container mx-auto px-4"> <div class="container mx-auto px-4">
<h1 class="text-2xl font-bold mb-4">Model Performance</h1> <h1 class="text-2xl font-bold mb-4">Model Performance</h1>
{% if metrics %} {% if metrics %}
<div class="bg-white shadow-md rounded p-6"> <div class="bg-white shadow-md rounded p-6">
<p><strong>Request Count:</strong> {{ metrics.request_count }}</p> <p><strong>Request Count:</strong> {{ metrics.request_count }}</p>
<p><strong>Average Request Latency:</strong> {{ metrics.avg_request_latency|floatformat:6 }} seconds</p> <p><strong>Average Request Latency:</strong> {{ metrics.avg_request_latency|floatformat:6 }} seconds</p>
<p><strong>Average Runtime Latency:</strong> {{ metrics.avg_runtime_latency|floatformat:6 }} seconds</p> <p><strong>Average Runtime Latency:</strong> {{ metrics.avg_runtime_latency|floatformat:6 }} seconds</p>
<p><strong>Model Load Latency:</strong> {{ metrics.model_load_latency|floatformat:6 }} seconds</p> <p><strong>Model Load Latency:</strong> {{ metrics.model_load_latency|floatformat:6 }} seconds</p>
</div> </div>
{% else %} {% else %}
<p>Failed to retrieve model performance metrics.</p> <p>Failed to retrieve model performance metrics.</p>
{% endif %} {% endif %}
<form method="post" action="{% url 'model_performance' %}" class="mt-4">
{% csrf_token %}
<button type="submit" name="reset_metrics" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Reset Metrics
</button>
</form>
</div> </div>
{% endblock content %} {% endblock content %}
\ No newline at end of file
{% extends '_base.html' %}
{% block content %}
<h1>Model Version Selection</h1>
<form method="post">
{% csrf_token %}
<label for="model_version">Select Model Version:</label>
<select name="model_version" id="model_version">
{% for version in model_versions %}
<option value="{{ version }}" {% if selected_model_version == version %}selected{% endif %}>{{ version }}</option>
{% endfor %}
</select>
<button type="submit">Save</button>
</form>
{% endblock %}
\ No newline at end of file
{% extends "_base.html" %} {% block content %} <!-- user_page.html -->
{% extends "_base.html" %}
{% block content %}
<div <div
class="grid grid-cols-1 px-4 pt-6 xl:grid-cols-3 xl:gap-4 dark:bg-grey-300" class="grid grid-cols-1 px-4 pt-6 xl:grid-cols-3 xl:gap-4 dark:bg-grey-300"
> >
...@@ -33,7 +35,13 @@ ...@@ -33,7 +35,13 @@
<h3 class="mb-4 text-xl font-semibold dark:text-white">Change your password</h3> <h3 class="mb-4 text-xl font-semibold dark:text-white">Change your password</h3>
<a href="{% url 'password_change' %}" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">Change Password</a> <a href="{% url 'password_change' %}" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">Change Password</a>
</div> </div>
{% if user_profile.user_type == 2 or user.is_superuser %}
<div class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800">
<h3 class="mb-4 text-xl font-semibold dark:text-white">Model Selection</h3>
<a href="{% url 'model_selection' %}" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">Select Model</a>
</div>
{% endif %}
{% if user_profile.user_type == 3 or user.is_superuser or user_profile.user_type == 1%} {% if user_profile.user_type == 3 or user.is_superuser or user_profile.user_type == 1%}
<div <div
......
from django.urls import path from django.urls import path
from .views import InstrumentDetectionView, ModelPerformanceView, index, log_fileupload, users, maintenance, \ from .views import InstrumentDetectionView, ModelPerformanceView, ModelSelectionView, index, log_fileupload, users, maintenance, \
handler404, handler500, terms_conditions, privacy_policy, pricing, generate_pdf, admin_table,\ handler404, handler500, terms_conditions, privacy_policy, pricing, generate_pdf, admin_table,\
change_user_type, submit_feedback change_user_type, submit_feedback
from .payments import create_payment, execute_payment, payment_cancelled, payment_success from .payments import create_payment, execute_payment, payment_cancelled, payment_success
...@@ -26,6 +26,7 @@ urlpatterns = [ ...@@ -26,6 +26,7 @@ urlpatterns = [
path('generate_pdf/', generate_pdf, name='generate_pdf'), path('generate_pdf/', generate_pdf, name='generate_pdf'),
path('instrument_detection/', InstrumentDetectionView.as_view(), name='instrument_detection'), path('instrument_detection/', InstrumentDetectionView.as_view(), name='instrument_detection'),
path('model_performance/', ModelPerformanceView.as_view(), name='model_performance'), path('model_performance/', ModelPerformanceView.as_view(), name='model_performance'),
path('model_selection/', ModelSelectionView.as_view(), name='model_selection'),
path('password_change/', auth_views.PasswordChangeView.as_view(template_name='password_change_form.html'), name='password_change'), path('password_change/', auth_views.PasswordChangeView.as_view(template_name='password_change_form.html'), name='password_change'),
path('password_change/done/', auth_views.PasswordChangeDoneView.as_view(template_name='password_change_done.html'), name='password_change_done'), path('password_change/done/', auth_views.PasswordChangeDoneView.as_view(template_name='password_change_done.html'), name='password_change_done'),
......
# views.py
import os
from django.contrib.auth import authenticate, login, logout from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User from django.contrib.auth.models import User
...@@ -12,7 +14,7 @@ import json ...@@ -12,7 +14,7 @@ import json
from datetime import datetime from datetime import datetime
from .forms import InstrumentDetectionForm from .forms import InstrumentDetectionForm
from .models import Log, Action, User, UserTokenCount, Profile from .models import Log, Action, User, UserTokenCount, Profile, ModelConfig, ModelPerformanceMetrics
from django.http import JsonResponse from django.http import JsonResponse
from django.db import connection from django.db import connection
...@@ -26,8 +28,8 @@ import requests ...@@ -26,8 +28,8 @@ import requests
# Authentication Imports # Authentication Imports
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.views import generic from django.views import View, generic
from .models import Profile from .models import Profile, ModelConfig
from .forms import UserRegisterForm, LoginAuthenticationForm from .forms import UserRegisterForm, LoginAuthenticationForm
from django.contrib.auth.views import LoginView from django.contrib.auth.views import LoginView
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
...@@ -332,42 +334,50 @@ class InstrumentDetectionView(APIView): ...@@ -332,42 +334,50 @@ class InstrumentDetectionView(APIView):
else: return super().dispatch(request, *args, **kwargs) else: return super().dispatch(request, *args, **kwargs)
def post(self, request): def post(self, request):
# Get the user's token count try:
user_token_count = UserTokenCount.objects.get(user=request.user) model_config = ModelConfig.load()
selected_model_version = model_config.selected_model_version
# Decrease the user's token count by one # Get the user's token count
user_token_count.token_count -= 1 user_token_count = UserTokenCount.objects.get(user=request.user)
user_token_count.save()
# Decrease the user's token count by one
serializer = InstrumentDetectionSerializer(data=request.data) user_token_count.token_count -= 1
if serializer.is_valid(): user_token_count.save()
audio_file = serializer.validated_data['audio_file']
serializer = InstrumentDetectionSerializer(data=request.data)
# Save the uploaded file temporarily if serializer.is_valid():
# with open('temp_audio.wav', 'wb') as f: audio_file = serializer.validated_data['audio_file']
# f.write(audio_file.read())
# Save the uploaded file temporarily
# Preprocess the audio file # with open('temp_audio.wav', 'wb') as f:
preprocessed_data = preprocess_audio_for_inference(audio_file) # f.write(audio_file.read())
# Prepare data for TensorFlow Serving # Preprocess the audio file
data = json.dumps({"signature_name": "serving_default", "instances": [window.tolist() for window in preprocessed_data]}) preprocessed_data = preprocess_audio_for_inference(audio_file)
# Send request to TensorFlow Serving # Prepare data for TensorFlow Serving
url = 'http://tensorflow_serving:8501/v1/models/instrument_model/versions/2:predict' data = json.dumps({"signature_name": "serving_default", "instances": [window.tolist() for window in preprocessed_data]})
headers = {"Content-Type": "application/json"}
response = requests.post(url, data=data, headers=headers) # Send request to TensorFlow Serving
# url = 'http://tensorflow_serving:8501/v1/models/instrument_model/versions/2:predict'
# Process the response url = f'http://tensorflow_serving:8501/v1/models/instrument_model/versions/{selected_model_version}:predict'
if response.status_code == 200: headers = {"Content-Type": "application/json"}
raw_predictions = response.json()['predictions'] response = requests.post(url, data=data, headers=headers)
# Convert raw prediction numbers into percentages
formatted_predictions = self.format_predictions(raw_predictions) # Process the response
return Response({"predictions": formatted_predictions}, status=status.HTTP_200_OK) if response.status_code == 200:
else: print('Predictions received')
return Response({"error": "Failed to get predictions"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) raw_predictions = response.json()['predictions']
# Convert raw prediction numbers into percentages
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) formatted_predictions = self.format_predictions(raw_predictions)
return Response({"predictions": formatted_predictions}, status=status.HTTP_200_OK)
else:
return Response({"error": "Failed to get predictions"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
except Exception as e:
logger.error(f"An error occurred: {e}")
messages.error(request, 'An error occurred: {e}')
return redirect('index')
def format_predictions(self, predictions): def format_predictions(self, predictions):
...@@ -395,10 +405,10 @@ class ModelPerformanceView(UserPassesTestMixin, TemplateView): ...@@ -395,10 +405,10 @@ class ModelPerformanceView(UserPassesTestMixin, TemplateView):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
if request.user.is_anonymous: if request.user.is_anonymous:
messages.info(request, 'Must be logged in as an ML Engineer or Admin to access this page.') messages.info(request, 'Must be logged in as an ML Engineer or Superuser to access this page.')
return redirect('login') return redirect('login')
elif request.user.profile.user_type != 2 and not request.user.is_superuser: elif request.user.profile.user_type != 2 and not request.user.is_superuser:
messages.info(request, 'Must be logged in as an ML Engineer or Admin to access this page.') messages.info(request, 'Must be logged in as an ML Engineer or Superuser to access this page.')
return redirect('users') return redirect('users')
else: else:
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
...@@ -423,21 +433,73 @@ class ModelPerformanceView(UserPassesTestMixin, TemplateView): ...@@ -423,21 +433,73 @@ class ModelPerformanceView(UserPassesTestMixin, TemplateView):
runtime_latency_count = re.search(r':tensorflow:serving:runtime_latency_count{model_name="instrument_model",API="Predict",runtime="TF1"} (\d+)', metrics_data) runtime_latency_count = re.search(r':tensorflow:serving:runtime_latency_count{model_name="instrument_model",API="Predict",runtime="TF1"} (\d+)', metrics_data)
model_load_latency = re.search(r':tensorflow:cc:saved_model:load_latency{model_path="/models/instrument_model/2"} (\d+)', metrics_data) model_load_latency = re.search(r':tensorflow:cc:saved_model:load_latency{model_path="/models/instrument_model/2"} (\d+)', metrics_data)
# Get or create the ModelPerformanceMetrics instance
metrics, _ = ModelPerformanceMetrics.objects.get_or_create(pk=1)
# Update the metrics in the database
metrics.request_count = int(request_count.group(1)) if request_count else 0
metrics.request_latency_sum = float(request_latency_sum.group(1)) if request_latency_sum else 0
metrics.request_latency_count = int(request_latency_count.group(1)) if request_latency_count else 0
metrics.runtime_latency_sum = float(runtime_latency_sum.group(1)) if runtime_latency_sum else 0
metrics.runtime_latency_count = int(runtime_latency_count.group(1)) if runtime_latency_count else 0
metrics.model_load_latency = float(model_load_latency.group(1)) if model_load_latency else 0
metrics.save()
# Calculate average latencies in seconds # Calculate average latencies in seconds
avg_request_latency = float(request_latency_sum.group(1)) / float(request_latency_count.group(1)) / 1e6 if request_latency_sum and request_latency_count else None avg_request_latency = metrics.request_latency_sum / metrics.request_latency_count / 1e6 if metrics.request_latency_count else None
avg_runtime_latency = float(runtime_latency_sum.group(1)) / float(runtime_latency_count.group(1)) / 1e6 if runtime_latency_sum and runtime_latency_count else None avg_runtime_latency = metrics.runtime_latency_sum / metrics.runtime_latency_count / 1e6 if metrics.runtime_latency_count else None
model_load_latency_seconds = float(model_load_latency.group(1)) / 1e6 if model_load_latency else None
context['metrics'] = { context['metrics'] = {
'request_count': request_count.group(1) if request_count else None, 'request_count': metrics.request_count,
'avg_request_latency': avg_request_latency, 'avg_request_latency': avg_request_latency,
'avg_runtime_latency': avg_runtime_latency, 'avg_runtime_latency': avg_runtime_latency,
'model_load_latency': model_load_latency_seconds 'model_load_latency': metrics.model_load_latency / 1e6
} }
else: else:
context['metrics'] = None context['metrics'] = None
return context return context
def post(self, request, *args, **kwargs):
if 'reset_metrics' in request.POST:
metrics = ModelPerformanceMetrics.objects.get(pk=1)
metrics.reset_metrics()
metrics.save()
return redirect('users')
else:
messages.error(request, 'Invalid request')
return redirect('users')
class ModelSelectionView(UserPassesTestMixin, View):
def dispatch(self, request, *args, **kwargs):
if request.user.is_anonymous:
messages.info(request, 'Must be logged in as an ML Engineer or Superuser to access this page.')
return redirect('login')
elif request.user.profile.user_type != 2 and not request.user.is_superuser:
messages.info(request, 'Must be logged in as an ML Engineer or Superuser to access this page.')
return redirect('users')
else:
return super().dispatch(request, *args, **kwargs)
def test_func(self):
return self.request.user.is_authenticated and self.request.user.profile.user_type == 2
def get(self, request):
model_versions = os.listdir('models/instrument_model')
model_config = ModelConfig.load()
context = {
'model_versions': model_versions,
'selected_model_version': model_config.selected_model_version,
}
return render(request, 'model_selection.html', context)
def post(self, request):
selected_model_version = request.POST.get('model_version')
model_config = ModelConfig.load()
model_config.selected_model_version = selected_model_version
model_config.save()
return redirect('model_selection')
def change_user_type(request, user_id): def change_user_type(request, user_id):
if request.method == 'POST': if request.method == 'POST':
...@@ -449,7 +511,4 @@ def change_user_type(request, user_id): ...@@ -449,7 +511,4 @@ def change_user_type(request, user_id):
def user_has_credits(): def user_has_credits():
has_credits = False has_credits = False
return has_credits return has_credits