0

I have a django app where I want MyModel instances to be saved using an Enum choice, which I process in the save() method, such as:

# app/models.py

from django.db import models
from app.utils import translate_choice
from enum import Enum

class MyEnum(Enum):
  CHOICE_A = 'Choice A'
  CHOICE_B = 'Choice B'

class MyModel(models.Model):
  ...
  choice = models.CharField(
    max_length=10,
    choices=[(tag.name, tag.value) for tag in MyEnum],
  )
  ...
  def save(self, *args, **kwargs):
    self.choice = translate_choice(self.choice)
    super().save(*args, **kwargs)

Whereas on the app/utils.py I have:

from app.models import MyEnum

def translate_choice(value):
   ...
   return MyEnum.CHOICE_A # For example

I keep getting ImportError: cannot import name 'MyEnum' errors on the app/utils.py file when running the application. Is this due to a python circular import error, or am I missing something else? When moving the translate_choice() method to app/models.py it stops happening, but I would like to use this same method in other modules and it is kind of weird having a transforming feature within the models when used in another app.

Thank you in advance

Oscar
  • 27
  • 3
  • 2
    You can break the circular dependency by moving `MyEnum` to `app/utils.py`. then you won't need `from app.models import MyEnum`. – Alasdair Nov 19 '19 at 16:08
  • 1
    You could pass `MyEnum` to `translate_choice`. This might be a good idea because as well as breaking circular dependency, `translate_choice` might become a genuine utility routine, useful elsewhere being passed `SomeOtherEnum`. – nigel222 Nov 19 '19 at 16:45
  • Possible duplicate of [Python circular importing?](https://stackoverflow.com/questions/22187279/python-circular-importing) – dirkgroten Nov 19 '19 at 17:16

1 Answers1

0

It's probably due to the circular import, as you've guessed yourself. You can try putting the import statement not at the top of the file, but inside the function that uses the imported object:

def translate_choice(value):
    from app.models import MyEnum
    ...
    return MyEnum.CHOICE_A # For example

This is, admittedly, not the most elegant solution. See also the answers to this post, where you can find other approaches.

natka_m
  • 1,297
  • 17
  • 22