'In Python how can I overwrite the class attribute of an inherited class, where that attribute is itself an instance of a model?
As in the title, I have a base class ListView, with a Serializer attribute that needs overwriting. For each of my django models I create a child ListView class and a Serializer. So for example for the django model Event we have a corresponding view class EventListView(ListView), and we have a corresponding Serializer class EventSerializer(Serializer).
The Serializer child class is specified within the ListViewClass, as in my code below. Is it possible to have the serializer overwritten automatically based on the value supplied to model, and how may I mark model and Serializer as attributes that are to be overwritten and therefore do not need values specified in the base class?
class EventSerializer(serializers.ModelSerializer):
class Meta:
model = Event
fields = '__all__'
class ListView(APIView):
model = <Model to be overwritten> # Event is set as the default.
Serializer = <Model Serializer to be overwritten>
queryset = model.objects.all()
def get(self,request):
# !!! Get filter conditions from request
queryset = ListView.queryset.filter() # !!! Filter conditions
serializer = ListView.Serializer(queryset,many=True)
return Response(serializer.data)
def post(self,request):
data = JSONParser.parse(request)
serializer = ListView.Serializer(data = data)
if serializer.is_valid():
return Response(serializer.data, status = 201)
else:
return Response(serializer.errors, status = 400)
class EventListView(ListView):
model = Event
Solution 1:[1]
I think you need to use self.queryset, self.model and self.Serializer instead of ListView.queryset and ListView.Serializer. Then, in each subclass it will use the queryset, model, and serializer of the subclass, rather than of the base ListView.
In each subclass you will need to redefine model, queryset and Serializer.
class ListView(APIView):
model = <Model to be overwritten> # Event is set as the default.
Serializer = <Model Serializer to be overwritten>
queryset = model.objects.all()
def get(self,request):
# !!! Get filter conditions from request
queryset = self.queryset.filter() # !!! Filter conditions
serializer = self.Serializer(queryset,many=True)
return Response(serializer.data)
def post(self,request):
data = JSONParser.parse(request)
serializer = self.Serializer(data = data)
if serializer.is_valid():
return Response(serializer.data, status = 201)
else:
return Response(serializer.errors, status = 400)
class EventListView(ListView):
model = Event
Serializer = EventSerializer
queryset = Event.objects.all()
If you don't want to define queryset on all subclasses, you probably want to add a method to get the queryset using the model, like this
class ListView(APIView):
model = <Model to be overwritten> # Event is set as the default.
Serializer = <Model Serializer to be overwritten>
def get_queryset():
return self.model.objects.all()
def get(self,request):
# !!! Get filter conditions from request
queryset = self.get_queryset().filter() # !!! Filter conditions
serializer = self.Serializer(queryset,many=True)
return Response(serializer.data)
def post(self,request):
data = JSONParser.parse(request)
serializer = self.Serializer(data = data)
if serializer.is_valid():
return Response(serializer.data, status = 201)
else:
return Response(serializer.errors, status = 400)
In fact, a lot of this is implemented directly in DRF, which will save you a lot of custom coding. Check out the GenericAPIView (https://www.django-rest-framework.org/api-guide/generic-views/#genericapiview) and ListAPIView (https://www.django-rest-framework.org/api-guide/generic-views/#listapiview)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | mikicz |
