hi,
I didn’t found a similar post so I’ve created this one.
I have a project using Django with DRF as well. There are differents apps in this project :
- mapping
- log
- modulesconf
- etc
They are using the files reproduced below.
My question is : while everything is working properly, how can I change the views_v1.py to use generic calls. Currently it’s relied only on CpuConf class. But this code from the view needs to be adapted to use all the classes from the model. Moreover, the user may create many instances of the differents classes (3 CANAx, 2 CANEx, etc) from the front or the API as well.
I don’t see how to avoid reproducing as much as methods as there are classes . A scenario like this should be possible :
the user creates an instance of CANEx and this class is passed to the “generic” functions generic_list(CANEx)
(instead of the cpuconf_list) .
Same for generic_detail (CANEx)
instead of cpuconf_detail.
The main difficulty for me is that methods can be generic but serializer is specific to each class because they don’t share the same informations.
from api/urls.py:
urlpatterns = [
# path('', CpuAPIView.as_view()),
url(r'^mapping$', mapping.views.mapping_list),
url(r'^mapping/(?P<pk>[0-9]+)$', mapping.views.mapping_detail),
url(r'^mapping/enabled$', mapping.views.mapping_list_enabled),
url(r'^cpuconf/v1$', modulesconf.views_v1.cpuconf_list),
url(r'^cpuconf/v1/(?P<pk>[0-9]+)$', modulesconf.views_v1.cpuconf_detail),
url(r'^cpuconf/v1/enabled$', modulesconf.views_v1.cpuconf_list_enabled),
url(r'^cpuconf/v2$', modulesconf.views_v2.cpuconf_list),
url(r'^cpuconf/v2/(?P<pk>[0-9]+)$', modulesconf.views_v2.cpuconf_detail),
url(r'^cpuconf/v2/enabled$', modulesconf.views_v2.cpuconf_list_enabled)
from modulesconf/models.py:
class CommonData(models.Model):
eui = models.CharField(unique=True, null=False, max_length=30)
ip_address = models.GenericIPAddressField(max_length=30,validators=[validate_hostname])
subnet = models.GenericIPAddressField(max_length=30,validators=[validate_hostname])
mac= models.CharField(max_length=30)
bauds = models.PositiveIntegerField()
data_bits = models.PositiveSmallIntegerField()
stop_bits = models.PositiveSmallIntegerField()
parity = models.PositiveSmallIntegerField()
class Meta:
abstract = True
# CPU settings
class CpuConf(models.Model):
eui = models.CharField(unique=True, null=False, max_length=30)
hostname = models.CharField(max_length=30,validators=[validate_hostname])
ip_address = models.GenericIPAddressField(validators=[validate_ipv4])
subnet = models.GenericIPAddressField(validators=[validate_ipv4])
dns = models.GenericIPAddressField(validators=[validate_ipv4])
ntp_address = models.GenericIPAddressField(validators=[validate_ipv4])
def __str__(self):
return str(self.ip_address)
class CANAx(models.Model):
eui = models.CharField(unique=True, null=False, max_length=30)
......etc)
class CANEx(models.Model):
eui = models.CharField(unique=True, null=False, max_length=30)
......etc)
class CANCx(models.Model):
eui = models.CharField(unique=True, null=False, max_length=30)
......etc)
class ModuleRA(CommonData):
pass
class ModuleRE(CommonData):
pass
class ModuleRC(CommonData):
acq_network = models.PositiveSmallIntegerField()
network_type = models.CharField(max_length=30)
enabled = models.BooleanField()
from modulesconf/views_v1.py:
api = NinjaAPI(version='1.0.0')
# Create a view for web
class CpuConfListView(ListView):
model = CpuConf
template_name = 'cpuconf_list.html'
# === Create dedicated methods for API calls ===
# GET list of cpuconfs, POST a new cpuconf, DELETE all cpuconfs
@api_view(['GET', 'POST', 'DELETE'])
def cpuconf_list(request):
if request.method == 'GET':
cpuconfs = CpuConf.objects.all()
# Check if the UID exists
eui_value = request.query_params.get('eui',None)
if eui_value is not None:
cpuconfs = cpuconfs.filter(eui__contains = eui_value)
cpuconfs_serializer = CpuConfSerializer(cpuconfs, many=True)
return JsonResponse( cpuconfs_serializer.data, safe=False)
elif request.method == 'POST':
cpuconf_data = JSONParser().parse(request)
cpuconf_serializer = CpuConfSerializer(data=cpuconf_data)
if cpuconf_serializer.is_valid():
cpuconf_serializer.save()
return JsonResponse(cpuconf_serializer.data, status=status.HTTP_201_CREATED)
return JsonResponse(cpuconf_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
count = CpuConf.objects.all().delete()
return JsonResponse({'message': '{} the cpu configurations have been deleted successfully!'.format(count[0])}, status=status.HTTP_204_NO_CONT
ENT)
# GET / PUT / DELETE cpuconf by its ‘id’
@api_view(['GET', 'PUT', 'DELETE'])
def cpuconf_detail(request, pk):
try:
single_cpuconf = CpuConf.objects.get(pk=pk)
except CpuConf.DoesNotExist:
return JsonResponse({'message': 'The CPU configuration does not exist'}, status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
cpuconf_serializer = CpuConfSerializer(single_cpuconf)
return JsonResponse(cpuconf_serializer.data)
elif request.method == 'PUT':
cpuconf_data = JSONParser().parse(request)
cpuconf_serializer = CpuConfSerializer(single_cpuconf, data=cpuconf_data)
if cpuconf_serializer.is_valid():
cpuconf_serializer.save()
return JsonResponse(cpuconf_serializer.data)
return JsonResponse(cpuconf_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
single_cpuconf.delete()
return JsonResponse({'message': 'The CPU configuration was deleted successfully!'}, status=status.HTTP_204_NO_CONTENT)
from api/serializers.py:
from rest_framework import serializers
from modulesconf.models import CpuConf
class CpuConfSerializer(serializers.ModelSerializer):
class Meta :
model = CpuConf
fields= ('id',
'eui',
'hostname',
'ip_address',
'subnet',
'dns',
'ntp_address' )