Django Rest Framework-抽象基类的HyperlinkedRelatedField

时间:2018-06-22 18:14:50

标签: django-rest-framework

我的问题是,是否有可能在序列化器中添加HyperlinkedRelatedField以仅获取基类的属性。例如:

我想要一个这样的json:

{
  "modules": [
    {
      "moduleName": "M1: Fundamentos Técnicos",
      "moduleDetails": "Bla bla bla.",
      "moduleID": 0,
      "userScore": 3,
      "slides": [
        {
          "slideType": "Content",
          "slideID": 0
        },
        {
          "slideType": "Minigame1",
          "slideID": 1
        },
        {
          "slideType": "Video",
          "slideID": 6
        }
      ]
    }
  ]
}

在这里,Slide是基类,Video和Minigame是子类。 可以吗?是否可以为每张幻灯片的网址添加一个HyperlinkedRelatedField?。

谢谢!

更新!

这是我的模特

   class Module(TimeStampedModel):

       moduleID = models.AutoField(primary_key=True)
       moduleName = models.CharField(
        max_length=100,
        verbose_name='Nombre del modulo')
       moduleDetails = models.TextField(verbose_name='Detalle')
       moduleBullet1 = models.CharField(max_length=100, verbose_name='Punto 1')
       moduleBullet2 = models.CharField(max_length=100, verbose_name='Punto 2')
       moduleBullet3 = models.CharField(max_length=100, verbose_name='Punto 3')
       moduleImageURL = models.ImageField(
        upload_to="modulos", verbose_name='Imagen')
       userScore = models.PositiveSmallIntegerField(
        default=0, verbose_name='Score de usuario')


    class Slide(TimeStampedModel):

        CONTENT = 'Content'
        MINIGAME = 'Minigame'
        VIDEO = 'Video'
        SLIDE_TYPE_CHOICES = (
            (CONTENT, 'Contenido'),
            (MINIGAME, 'Minigame'),
            (VIDEO, 'Video'),
        )
        slideType = models.CharField(
            max_length=20,
            choices=SLIDE_TYPE_CHOICES,
            default=CONTENT,
        )
        slideID = models.AutoField(primary_key=True)
        slideOrder = models.PositiveSmallIntegerField(
            verbose_name='Orden de visualizacion')
        module = models.ForeignKey(Module, on_delete=models.CASCADE, 
            related_name="%(app_label)s_%(class)s_related",
            related_query_name="%(app_label)s_%(class)ss",)

        class Meta:
            abstract = True

    class VideoContent(Slide):

        videoURL = models.URLField(verbose_name='URL de video')


    class Minigame(Slide):

        timeToFail=models.PositiveSmallIntegerField()

在我的serializers.py中,我想要这样的东西:

class SlideSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = Slide
        fields = ('url', 'slideType', 'slideID')

class ModuleSerializer(serializers.ModelSerializer):

     slides = SlideSerializer(many=True, read_only=True)
     class Meta:
         model = Module
         fields = ('moduleID', 'moduleName', 'moduleDetails', 'moduleImageURL', 'userScore', 'slides')

我的view.py

class ModuleViewSet(viewsets.ModelViewSet):

    """
    This viewset automatically provides `list`, `create`, `retrieve`,
    `update` and `destroy` actions.
    """

    queryset = Module.objects.all()
    serializer_class = ModuleSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class SlideViewSet(viewsets.ModelViewSet):

    """
    This viewset automatically provides `list`, `create`, `retrieve`,
    `update` and `destroy` actions.
    """

    queryset = Slide.objects.all()
    serializer_class = SlideSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

Slide.Objects引发错误,AttributeError:类型对象'Slide'没有属性'objects'

1 个答案:

答案 0 :(得分:1)

您不能查询抽象基类。 Slice是一个抽象类,您不能在queryset = Slide.objects.all()中使用SlideViewSet,因为抽象模型不是实际的数据库对象,因此无法查询。

您必须在抽象继承之间进行选择,在这种情况下,两个类之间没有数据库关系,或者在多表继承之间进行选择,这使每个查询的数据库关系都以效率为代价(额外的数据库联接)。

使用多表继承

class Slide(TimeStampedModel):

    CONTENT = 'Content'
    MINIGAME = 'Minigame'
    VIDEO = 'Video'
    SLIDE_TYPE_CHOICES = (
        (CONTENT, 'Contenido'),
        (MINIGAME, 'Minigame'),
        (VIDEO, 'Video'),
    )
    slideType = models.CharField(
        max_length=20,
        choices=SLIDE_TYPE_CHOICES,
        default=CONTENT,
    )
    slideID = models.AutoField(primary_key=True)
    slideOrder = models.PositiveSmallIntegerField(
        verbose_name='Orden de visualizacion')
    module = models.ForeignKey(Module, on_delete=models.CASCADE, 
        related_name="%(app_label)s_%(class)s_related",
        related_query_name="%(app_label)s_%(class)ss",)

class VideoContent(Slide):

    videoURL = models.URLField(verbose_name='URL de video')


class Minigame(Slide):

    timeToFail=models.PositiveSmallIntegerField()

现在,您的视图集:

class SlideViewSet(viewsets.ModelViewSet):
"""
This viewset automatically provides `list`, `create`, `retrieve`,
`update` and `destroy` actions.
"""
queryset = Slide.objects.all()
serializer_class = SlideSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

Documentation on multi-table inheritance

  

多表继承使用隐式的OneToOneField来链接   孩子和父母,可以从父母下移到   孩子

希望这可以清除一切。