简体   繁体   中英

Nested Serializers Django Rest Framework

I have two models Stage and Application. I am getting an error like this:

Exception Type: ImportError

Exception Value: cannot import name ApplicationSerializer

Exception Location: /Users/jojjen/workspace/indusaction/vms/stages/serializers.py in , line 7

I am guessing that this error is due to cyclic imports in the serializers. But I have no clue how to resolve this.

If I remove the ApplicationSerializer import from StageSerializer , it works. But I need to access certain properties of stage's application in the template that I am building.

Following is the code:

stages/models.py:

from django.db import models

from core.models import TimeStampedModel

from applications.models import Application

from authentication.models import Account


class Stage(TimeStampedModel):
    name = models.CharField(max_length=20)

    application = models.ForeignKey(Application, null=True, related_name='stages')

    assignee = models.ForeignKey(Account, null=True)

    def __unicode__(self):
        return self.name

applications/models.py:

from django.db import models

from core.models import TimeStampedModel

from organizations.models import Organization
from authentication.models import Account


class Application(TimeStampedModel):
    title = models.CharField(max_length=30, unique=True)
    details = models.TextField()
    archived = models.BooleanField(default=False)

    organization = models.ForeignKey(Organization, null=True)

    users = models.ManyToManyField(Account, related_name='applications')

    creator = models.ForeignKey(Account, null=True)

    def __unicode__(self):
        return self.title

stages/serializers.py

from rest_framework import serializers

from stages.models import Stage

from authentication.serializers import AccountSerializer

from applications.serializers import ApplicationSerializer


class StageSerializer(serializers.ModelSerializer):
    assignee = AccountSerializer(read_only=True, required=False)
    application = ApplicationSerializer(read_only=True, required=False)

    class Meta:
        model = Stage
        fields = ('id', 'name', 'assignee', 'created_at', 'updated_at',
                  'application',)
        read_only_fields = ('created_at', 'updated_at', 'assignee',
                            'application',)

        def get_validation_exclusions(self, *args, **kwargs):
            exclusions = super(StageSerializer,
                               self).get_validation_exclusions()

            return exclusions + ['assignee', 'application']

applications/serializers.py:

from rest_framework import serializers

from applications.models import Application

from organizations.serializers import OrganizationSerializer
from authentication.serializers import AccountSerializer
from stages.serializers import StageSerializer
from applicants.serializers import ApplicantSerializer


class ApplicationSerializer(serializers.ModelSerializer):
    organization = OrganizationSerializer(read_only=True, required=False)
    creator = AccountSerializer(read_only=True, required=False)
    users = AccountSerializer(read_only=True, required=False, many=True)
    stages = StageSerializer(read_only=True, required=False, many=True)
    applicant_set = ApplicantSerializer(read_only=True, required=False, many=True)

    class Meta:
        model = Application

        fields = ('id', 'title', 'details', 'organization', 'stages',
                  'creator', 'archived', 'users', 'applicant_set')
        read_only_fields = ('id', 'organization', 'users', 'applicant_set',
                            'created_at', 'updated_at', 'stages')

    def get_validation_exclusions(self, *args, **kwargs):
        exclusions = super(ApplicatiionSerializer,
                           self).get_validation_exclusions()

        return exclusions + ['organization', 'users', 'creator', 'stage_set', 'applicant_set']

This code is not valid, you cannot have cyclic imports and dependencies. This is not even true for Django Rest Framework by Python in general. You have to change your design to remove this cyclic dependency.

A circular dependency in any language, is an infinite recursion.

Look at this library - https://github.com/heywbj/django-rest-framework-recursive/tree/master/rest_framework_recursive . This can be used to emulate circular dependency like in a tree or linked list.

But I would still suggest you to re consider your design. Read why circular dependency is a sign of poor design. If that is not possible, put interdependent components into the same module.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM