barebone app with django and react, sse, jwt token, comport reader, test comport writer, requires com0com, users with groups, sample table vehicles, tokens for access and refresh

This commit is contained in:
2026-01-17 13:03:21 +02:00
commit 7f04566242
81 changed files with 22551 additions and 0 deletions
+194
View File
@@ -0,0 +1,194 @@
from rest_framework import serializers
from django.contrib.auth.password_validation import validate_password
from .models import ComPortReading, User
from vehicles.models import Vehicle, VehicleExtra
from nomenclatures.models import Nomenclature, NomenclatureField
class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True, required=False)
class Meta:
model = User
fields = ['id', 'username', 'email', 'first_name', 'last_name',
'role', 'is_admin', 'is_active', 'date_joined', 'password']
read_only_fields = ['id', 'date_joined']
extra_kwargs = {
'password': {'write_only': True}
}
def create(self, validated_data):
password = validated_data.pop('password', None)
user = User(**validated_data)
if password:
user.set_password(password)
user.save()
return user
def update(self, instance, validated_data):
password = validated_data.pop('password', None)
for attr, value in validated_data.items():
setattr(instance, attr, value)
if password:
instance.set_password(password)
instance.save()
return instance
class UserDetailSerializer(serializers.ModelSerializer):
"""Serializer for current user details (excludes password)"""
class Meta:
model = User
fields = ['id', 'username', 'email', 'first_name', 'last_name',
'role', 'is_admin', 'is_active', 'date_joined']
read_only_fields = ['id', 'date_joined']
class ChangePasswordSerializer(serializers.Serializer):
"""Serializer for password change endpoint"""
old_password = serializers.CharField(required=True, write_only=True)
new_password = serializers.CharField(required=True, write_only=True)
def validate_old_password(self, value):
user = self.context['request'].user
if not user.check_password(value):
raise serializers.ValidationError("Old password is incorrect")
return value
def validate_new_password(self, value):
# Use Django's password validators
validate_password(value, self.context['request'].user)
return value
def save(self, **kwargs):
user = self.context['request'].user
user.set_password(self.validated_data['new_password'])
user.save()
return user
class ComPortReadingSerializer(serializers.ModelSerializer):
class Meta:
model = ComPortReading
fields = ['id', 'port', 'data', 'timestamp', 'source_ip']
read_only_fields = ['id', 'timestamp']
class VehicleExtraSerializer(serializers.ModelSerializer):
class Meta:
model = VehicleExtra
fields = ['id', 'data']
read_only_fields = ['id']
class VehicleSerializer(serializers.ModelSerializer):
extra = VehicleExtraSerializer(required=False, allow_null=True)
class Meta:
model = Vehicle
fields = ['id', 'vehicle_number', 'extra']
read_only_fields = ['id']
def create(self, validated_data):
extra_data = validated_data.pop('extra', None)
vehicle = Vehicle.objects.create(**validated_data)
if extra_data:
VehicleExtra.objects.create(vehicle=vehicle, **extra_data)
return vehicle
def update(self, instance, validated_data):
extra_data = validated_data.pop('extra', None)
# Update Vehicle fields
instance.vehicle_number = validated_data.get('vehicle_number', instance.vehicle_number)
instance.save()
# Handle VehicleExtra update/creation
if extra_data is not None:
if hasattr(instance, 'extra'):
# Update existing VehicleExtra
for attr, value in extra_data.items():
setattr(instance.extra, attr, value)
instance.extra.save()
else:
# Create new VehicleExtra
VehicleExtra.objects.create(vehicle=instance, **extra_data)
return instance
def validate_vehicle_number(self, value):
if not value or not value.strip():
raise serializers.ValidationError("Vehicle number cannot be empty")
return value.strip()
class NomenclatureFieldSerializer(serializers.ModelSerializer):
class Meta:
model = NomenclatureField
fields = ['id', 'key', 'field_type']
read_only_fields = ['id']
def validate_key(self, value):
if not value or not value.strip():
raise serializers.ValidationError("Field key cannot be empty")
return value.strip()
def validate_field_type(self, value):
valid_types = [choice[0] for choice in NomenclatureField.FIELD_TYPES]
if value not in valid_types:
raise serializers.ValidationError(
f"Invalid field type. Must be one of: {', '.join(valid_types)}"
)
return value
class NomenclatureSerializer(serializers.ModelSerializer):
fields = NomenclatureFieldSerializer(many=True, required=False, source='nomenclaturefield_set')
class Meta:
model = Nomenclature
fields = ['id', 'code', 'name', 'applies_to', 'fields']
read_only_fields = ['id']
def create(self, validated_data):
fields_data = validated_data.pop('nomenclaturefield_set', [])
nomenclature = Nomenclature.objects.create(**validated_data)
for field_data in fields_data:
NomenclatureField.objects.create(nomenclature=nomenclature, **field_data)
return nomenclature
def update(self, instance, validated_data):
fields_data = validated_data.pop('nomenclaturefield_set', None)
# Update Nomenclature fields
instance.code = validated_data.get('code', instance.code)
instance.name = validated_data.get('name', instance.name)
instance.applies_to = validated_data.get('applies_to', instance.applies_to)
instance.save()
# Handle fields update - replace all fields
if fields_data is not None:
# Delete existing fields
instance.nomenclaturefield_set.all().delete()
# Create new fields
for field_data in fields_data:
NomenclatureField.objects.create(nomenclature=instance, **field_data)
return instance
def validate_code(self, value):
if not value or not value.strip():
raise serializers.ValidationError("Code cannot be empty")
return value.strip()
def validate_applies_to(self, value):
valid_choices = ['vehicle', 'container']
if value not in valid_choices:
raise serializers.ValidationError(
f"Invalid applies_to value. Must be one of: {', '.join(valid_choices)}"
)
return value