0

I have 2 question models extending the base Question model:

class Question(models.Model):
    title = models.CharField(blank=False, max_length=200)
    order = models.PositiveIntegerField(default = 0)
    is_actuve = models.BooleanField(default = False)

class OptionQuestion(Question):
    is_bulletpoint = models.BooleanField(default=False)
    has_others = models.BooleanField(default=False)
    has_context = models.BooleanField(default=False)
    options = ArrayField(models.CharField(max_length=100), verbose_name='گزینه‌ها')


class ItemQuestion(Question):
    pass

I originally had the Question class abstract but i needed a unique id across all questions, and now i am in need of a ListAPIView for both of them. I have 2 serializers for OptionQuestion and ItemQuestion respectively. I just need to implement a view which would handle a request for a list of questions and handling them with the proper serializer each.

class QuestionListView(ListAPIView):
    serializer_class_OptionQuestion = OptionQuestionSerializer
    serializer_class_ItemQuestion = ItemQuestionSerializer

    def get_queryset_OptionQuestion(self):
        #???
dxt
  • 122
  • 1
  • 3
  • 13
AnikiAliz
  • 13
  • 2
  • Sometimes generic class-based views are great, but sometimes you have to resort to building your own. It think that's the case here. The ListAPIView isn't made for two lists, so you should just build your own view that returns the correct JSON. Take a step back, use the the generic `APIView` instead and implement your own `get()` method. – dirkgroten Jan 31 '19 at 11:32
  • Or you may have a look at [django-polymorphic](https://django-polymorphic.readthedocs.io/en/stable/) – Gabriel Pichot Jan 31 '19 at 11:45
  • @dirkgroten thanks i will do that – AnikiAliz Jan 31 '19 at 11:57
  • @gpichot i really like it and would use it, though when i said that to my supervisor yesterday, he disagreed saying it would lower performance probably. – AnikiAliz Jan 31 '19 at 11:58
  • You could use [this trick](https://stackoverflow.com/questions/5175009/fetching-inherited-model-objects-in-django/5177641#5177641) to automatically fetch the related subclasses just when you need them. Or use [InheritanceManager](https://django-model-utils.readthedocs.io/en/latest/managers.html#inheritancemanager) which does exactly the same, when requested, and doesn't change normal behaviour, i.e. no performance issue. You could use that then in the `ListApiView`'s `get_queryset()` method. – dirkgroten Jan 31 '19 at 12:02
  • Take a look at the documentation, one link is https://django-polymorphic.readthedocs.io/en/stable/performance.html – Gabriel Pichot Jan 31 '19 at 12:02
  • @gpichot I also don't believe this is a big performance hit, especially in this particular case (with just 2 types), but it doesn't give you the choice to avoid the related queries. Using `InheritanceManager` adds methods so you use them when you need them, and don't use them otherwise. – dirkgroten Jan 31 '19 at 12:04
  • @dirkgroten can `InheritanceManager` be used on an abstract model? – AnikiAliz Jan 31 '19 at 12:24
  • No it’s basically just doing the trick described in the answer given to the SO question I linked. – dirkgroten Jan 31 '19 at 12:25
  • Why have ItemQuestion and Question as separate models when there is no difference between them?? You could just add a field type to differentiate between them. This will cause duplication of code everywhere in your project and the sort of problem you're currently having – Ken4scholars Jan 31 '19 at 12:41
  • If they are different enough to be treated as separate entities, then you should consider having separate endpoints too as they are separate resources – Ken4scholars Jan 31 '19 at 12:44

1 Answers1

1

You can try this

class QuestionListView(ListAPIView):
   serializer_class_OptionQuestion = OptionQuestionSerializer
   serializer_class_ItemQuestion = ItemQuestionSerializer

   def get(self, request, *args, **kwrgs):
      if request.method == 'GET':
          query1 = Question.objects.all()
          query2 = OptionQuestion.objects.all()

          seralizer1 = self.serializer_class_OptionQuestion(query1)
          seralizer2 = self.serializer_class_ItemQuestion(query2)

          return Response(
             {
               'data1':seralizer1.data,
               'data2':seralizer2.data,
             }
          )

Hope it work for your problem

rahul.m
  • 5,572
  • 3
  • 23
  • 50