add config model
This commit is contained in:
parent
9b52184910
commit
a187ad8ee8
@ -1,3 +1,13 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
from api.models import GuiSettings
|
||||
|
||||
|
||||
class GuiSettingsAdmin(admin.ModelAdmin):
|
||||
|
||||
class Meta:
|
||||
model = GuiSettings
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
admin.site.register(GuiSettings, GuiSettingsAdmin)
|
||||
|
@ -1,3 +1,34 @@
|
||||
import psutil
|
||||
|
||||
from django.db import models
|
||||
|
||||
# Create your models here.
|
||||
|
||||
class GuiSettings(models.Model):
|
||||
"""
|
||||
Here we manage the settings for the web GUI:
|
||||
- Player URL
|
||||
- settings for the statistics
|
||||
"""
|
||||
|
||||
addrs = psutil.net_if_addrs()
|
||||
addrs = [(i, i) for i in addrs.keys()]
|
||||
|
||||
player_url = models.CharField(max_length=255)
|
||||
playout_config = models.CharField(max_length=255)
|
||||
net_interface = models.CharField(
|
||||
max_length=20,
|
||||
choices=addrs,
|
||||
default=None,
|
||||
)
|
||||
media_disk = models.CharField(max_length=255)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.pk is not None:
|
||||
super(GuiSettings, self).save(*args, **kwargs)
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
if not self.related_query.all():
|
||||
super(GuiSettings, self).delete(*args, **kwargs)
|
||||
|
||||
class Meta:
|
||||
verbose_name_plural = "guisettings"
|
||||
|
57
ffplayout/api/serializers.py
Normal file
57
ffplayout/api/serializers.py
Normal file
@ -0,0 +1,57 @@
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
from api.models import GuiSettings
|
||||
|
||||
|
||||
class UserSerializer(serializers.ModelSerializer):
|
||||
confirm_password = serializers.CharField(write_only=False, required=False)
|
||||
new_password = serializers.CharField(write_only=True, required=False)
|
||||
old_password = serializers.CharField(write_only=True, required=False)
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['username', 'old_password',
|
||||
'new_password', 'confirm_password', 'email']
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
instance.password = validated_data.get('password', instance.password)
|
||||
|
||||
if not validated_data['new_password']:
|
||||
raise serializers.ValidationError({'new_password': 'not found'})
|
||||
|
||||
if not validated_data['old_password']:
|
||||
raise serializers.ValidationError({'old_password': 'not found'})
|
||||
|
||||
if not instance.check_password(validated_data['old_password']):
|
||||
raise serializers.ValidationError(
|
||||
{'old_password': 'wrong password'})
|
||||
|
||||
if validated_data['new_password'] != \
|
||||
validated_data['confirm_password']:
|
||||
raise serializers.ValidationError(
|
||||
{'passwords': 'passwords do not match'})
|
||||
|
||||
if validated_data['new_password'] == \
|
||||
validated_data['confirm_password'] and \
|
||||
instance.check_password(validated_data['old_password']):
|
||||
# instance.password = validated_data['new_password']
|
||||
instance.set_password(validated_data['new_password'])
|
||||
instance.save()
|
||||
return instance
|
||||
return instance
|
||||
|
||||
|
||||
class GuiSettingsSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = GuiSettings
|
||||
fields = '__all__'
|
||||
|
||||
def get_fields(self, *args, **kwargs):
|
||||
fields = super().get_fields(*args, **kwargs)
|
||||
request = self.context.get('request')
|
||||
if request is not None and not request.parser_context.get('kwargs'):
|
||||
fields.pop('id', None)
|
||||
return fields
|
@ -7,19 +7,24 @@ import psutil
|
||||
import yaml
|
||||
from pymediainfo import MediaInfo
|
||||
|
||||
from django.conf import settings
|
||||
from api.models import GuiSettings
|
||||
|
||||
from natsort import natsorted
|
||||
|
||||
|
||||
def read_yaml():
|
||||
if os.path.isfile(settings.FFPLAYOUT_CONFIG):
|
||||
with open(settings.FFPLAYOUT_CONFIG, 'r') as config_file:
|
||||
config = GuiSettings.objects.filter(id=1).values()[0]
|
||||
|
||||
if os.path.isfile(config['playout_config']):
|
||||
with open(config['playout_config'], 'r') as config_file:
|
||||
return yaml.safe_load(config_file)
|
||||
|
||||
|
||||
def write_yaml(data):
|
||||
if os.path.isfile(settings.FFPLAYOUT_CONFIG):
|
||||
with open(settings.FFPLAYOUT_CONFIG, 'w') as outfile:
|
||||
config = GuiSettings.objects.filter(id=1).values()[0]
|
||||
|
||||
if os.path.isfile(config['playout_config']):
|
||||
with open(config['playoutConfig'], 'w') as outfile:
|
||||
yaml.dump(data, outfile, default_flow_style=False,
|
||||
sort_keys=False, indent=4)
|
||||
|
||||
@ -43,7 +48,7 @@ def sizeof_fmt(num, suffix='B'):
|
||||
|
||||
class SystemStats:
|
||||
def __init__(self):
|
||||
pass
|
||||
self.config = GuiSettings.objects.filter(id=1).values()[0]
|
||||
|
||||
def all(self):
|
||||
return {
|
||||
@ -83,7 +88,7 @@ class SystemStats:
|
||||
}
|
||||
|
||||
def disk(self):
|
||||
root = psutil.disk_usage(settings.MEDIA_DISK)
|
||||
root = psutil.disk_usage(self.config['media_disk'])
|
||||
return {
|
||||
'disk_total': [root.total, sizeof_fmt(root.total)],
|
||||
'disk_used': [root.used, sizeof_fmt(root.used)],
|
||||
@ -102,20 +107,20 @@ class SystemStats:
|
||||
def net_speed(self):
|
||||
net = psutil.net_if_stats()
|
||||
|
||||
if settings.NET_INTERFACE not in net:
|
||||
if self.config['net_interface'] not in net:
|
||||
return {
|
||||
'net_speed_send': 'no network interface set!',
|
||||
'net_speed_recv': 'no network interface set!'
|
||||
}
|
||||
|
||||
net = psutil.net_io_counters(pernic=True)[settings.NET_INTERFACE]
|
||||
net = psutil.net_io_counters(pernic=True)[self.config['net_interface']]
|
||||
|
||||
send_start = net.bytes_sent
|
||||
recv_start = net.bytes_recv
|
||||
|
||||
sleep(1)
|
||||
|
||||
net = psutil.net_io_counters(pernic=True)[settings.NET_INTERFACE]
|
||||
net = psutil.net_io_counters(pernic=True)[self.config['net_interface']]
|
||||
|
||||
send_end = net.bytes_sent
|
||||
recv_end = net.bytes_recv
|
||||
@ -160,7 +165,8 @@ def get_media_path(dir=None):
|
||||
for track in media_info.tracks:
|
||||
if track.track_type == 'General':
|
||||
try:
|
||||
duration = float(track.to_data()["duration"]) / 1000
|
||||
duration = float(
|
||||
track.to_data()["duration"]) / 1000
|
||||
break
|
||||
except KeyError:
|
||||
pass
|
||||
|
@ -1,14 +1,48 @@
|
||||
import os
|
||||
from urllib.parse import unquote
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django_filters import rest_framework as filters
|
||||
from rest_framework import viewsets
|
||||
from rest_framework.parsers import FileUploadParser, JSONParser
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from api.models import GuiSettings
|
||||
from api.serializers import GuiSettingsSerializer, UserSerializer
|
||||
|
||||
from .utils import (SystemStats, get_media_path, read_json, read_yaml,
|
||||
write_yaml)
|
||||
|
||||
|
||||
class CurrentUserView(APIView):
|
||||
def get(self, request):
|
||||
serializer = UserSerializer(request.user)
|
||||
return Response(serializer.data)
|
||||
|
||||
|
||||
class UserFilter(filters.FilterSet):
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['username']
|
||||
|
||||
|
||||
class UserViewSet(viewsets.ModelViewSet):
|
||||
queryset = User.objects.all()
|
||||
serializer_class = UserSerializer
|
||||
filter_backends = (filters.DjangoFilterBackend,)
|
||||
filterset_class = UserFilter
|
||||
|
||||
|
||||
class GuiSettingsViewSet(viewsets.ModelViewSet):
|
||||
"""
|
||||
API endpoint that allows media to be viewed.
|
||||
"""
|
||||
queryset = GuiSettings.objects.all()
|
||||
serializer_class = GuiSettingsSerializer
|
||||
|
||||
|
||||
class Config(APIView):
|
||||
"""
|
||||
read and write config from ffplayout engine
|
||||
@ -17,7 +51,7 @@ class Config(APIView):
|
||||
parser_classes = [JSONParser]
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if 'config' in request.GET.dict():
|
||||
if 'configPlayout' in request.GET.dict():
|
||||
yaml_input = read_yaml()
|
||||
|
||||
if yaml_input:
|
||||
@ -72,10 +106,11 @@ class Statistics(APIView):
|
||||
"""
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
stats = SystemStats()
|
||||
if 'stats' in request.GET.dict() and request.GET.dict()['stats'] \
|
||||
and hasattr(SystemStats(), request.GET.dict()['stats']):
|
||||
and hasattr(stats, request.GET.dict()['stats']):
|
||||
return Response(
|
||||
getattr(SystemStats(), request.GET.dict()['stats'])())
|
||||
getattr(stats, request.GET.dict()['stats'])())
|
||||
else:
|
||||
return Response({"success": False})
|
||||
|
||||
|
Binary file not shown.
@ -38,6 +38,7 @@ INSTALLED_APPS = [
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'django_filters',
|
||||
'rest_framework',
|
||||
'corsheaders',
|
||||
'api'
|
||||
@ -112,11 +113,7 @@ REST_FRAMEWORK = {
|
||||
],
|
||||
'DEFAULT_PERMISSION_CLASSES': (
|
||||
'rest_framework.permissions.IsAuthenticated',
|
||||
),
|
||||
'DEFAULT_PAGINATION_CLASS': (
|
||||
'rest_framework.pagination.LimitOffsetPagination',
|
||||
),
|
||||
'PAGE_SIZE': 50
|
||||
)
|
||||
}
|
||||
|
||||
CORS_ORIGIN_WHITELIST = (
|
||||
|
@ -25,6 +25,8 @@ from rest_framework_simplejwt.views import (
|
||||
)
|
||||
|
||||
router = routers.DefaultRouter()
|
||||
router.register(r'users', views.UserViewSet)
|
||||
router.register(r'guisettings', views.GuiSettingsViewSet, 'guisettings')
|
||||
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
@ -32,6 +34,7 @@ urlpatterns = [
|
||||
path('api/config/', views.Config.as_view()),
|
||||
path('api/playlist/', views.Playlist.as_view()),
|
||||
path('api/stats/', views.Statistics.as_view()),
|
||||
path('api/current/user/', views.CurrentUserView.as_view()),
|
||||
path('api/media/', views.Media.as_view()),
|
||||
path('api-auth/', include(
|
||||
'rest_framework.urls', namespace='rest_framework')),
|
||||
|
Loading…
x
Reference in New Issue
Block a user