Cyclic import issue on Django

I have two apps in my django project. app_one, app_two

And here’s my situation.

app_one/serializers.py
from app_two.serializers import TwoSerializer

app_two/serializers.py
from app_one.serializers import OneSerializer

I should use each serializer in another app for sure.
But it is giving me the import Error(Cyclic import)

How can I resolve this issue?

The fundamental answer is to restructure your modules.

When I’ve had this happen to me, I’ve generally found it’s because I’ve got something wrong in how I have things structured and organized. If there’s that much in the way of cross-app structure, I’d have the reaction that this is probably one app that shouldn’t have been divided into two - or at least one class that has been structured in the wrong place.

Now there are a couple of “hackish” solutions that I have used short-term to get past an immediate problem to keep work moving forward until a more appropriate solution is found. (I personally dislike them so much I hesitate to even mention them, but in the interest of completeness…)

  1. Import statements don’t have to be at the module level. You can have an import statement in a function, which isn’t executed until the function is called. (No idea how that would work in the context of serializers.)

  2. Break the two files into three, where the cyclic situation is “broken” by splitting the functionality of one of the files into two files, allowing the imports to be completed sequentially.

I am using class based views and I need to use that serializer in another serializer.
I am not sure how I can break two files into three.
Would you please let me know more details, @KenWhitesell ?

It’s very dependent on the context. I’d need to see the files to offer any more details.

Hi, @KenWhitesell

Here are more details.

from auth.serializers import UserProfileSerializer
...
...

class CommUserRoleSerializer(serializers.ModelSerializer):
    user = UserProfileSerializer()

    class Meta:
        ...


class CommSerializer(serializers.ModelSerializer):
    updated = serializers.BooleanField()
    ...
    user_roles = CommUserRoleSerializer(many=True, required=False)

    class Meta:

...


With the above code only, it was fine.

I added two fields which requires CommSerializer down below
auth/serializers.py

from comm.serializers import CommSerializer
...
class UpdateUserProfileSerializer(serializers.ModelSerializer):
    ...
    ...
    retails = CommSerializer(many=True, required=False)
    goals = CommSerializer(many=False, required=False)

    class Meta:
    ...

Hope this helps you to understand the problem.

Thanks

I understand the situation - but what you’ve shown here doesn’t explain why UpdateUserProfileSerializer needs to exist in auth/serializers.py instead of being placed in comm/serializers.py where it would have direct access to CommSerializer.

It exists in auth app since it is part of authentication

Yes, I understand why you might want to put it there. But you haven’t explained why it needs to be there.

So it’s models and the apis(ViewSets) that uses that serializer all reside inside the auth app.
It’s not comfortable for me to move that UserProfileSerializer to other app.
Or maybe I have to do that to get rid of this import error?

Hi, @KenWhitesell

What do you think?

Coming back to the original question:

From what I can see here, moving UserProfileSerializer to the other file would resolve this specific issue.

But this potentially exposes a wider-issue about the overall structure and how the components are divided into apps - and so I want to be very explicit that I’m not commenting on that here. But if you’re “uncomfortable” with some of the concessions that you need to make to make this work, I would use that as an indication that there may be some other sub-optimal architecture decisions that had been made over the course of this project.

So I am thinking of another solution.
The field is ManyToManyField which means a list of pks will be fed into api request.
I am wondering if I can just validate it by using serializers.ListField with IntegerField as child but it’s still giving me errors

Blockquote
“0”: [
“A valid integer is required.”
]

optional: you can use get_model function at one place or both.