Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Lazy Load a model in a managers to stop circular imports?

In Django you can create managers for your models. I do this by added a new file called managers.py and in my model objects = MyManager().

To stop circular imports I do self.model. However, if I need to reference a different model in my manager i.e.

from models import SecondModel
second= SecondModel(name=test).save()
self.model(second=second)

I get the following error: ImportError: cannot import name SecondModel

So is there a way in Django to lazy load a model?

like image 310
Prometheus Avatar asked Apr 20 '15 09:04

Prometheus


People also ask

How do I stop a circular import?

Changing the name of the Working file different from the module which is imported in the script can avoid the Circular Imports problem. Import the module: Avoid importing objects or functions from a module that can cause Circular Imports. It is good to import the whole module to avoid the Circular Import.

How do I fix circular import error?

If the error occurs due to a circular dependency, it can be resolved by moving the imported classes to a third file and importing them from this file. If the error occurs due to a misspelled name, the name of the class in the Python file should be verified and corrected.

What is most likely due to a circular import?

Generally, the Python Circular Import problem occurs when you accidentally name your working file the same as the module name and those modules depend on each other. This way the python opens the same file which causes a circular loop and eventually throws an error.

What are circular imports?

In simplest terms, a circular import occurs when module A tries to import and use an object from module B, while module B tries to import and use an object from module A. You can see it on on an example with simple modules a.py and b.py: # a.py snippet. print('First line of a.py') from package.


2 Answers

The currently accepted answer is deprecated as of Django 1.7; from this answer, you can adapt your code like this.

from django.apps import apps

class SomeModelManager(...):
    ...

    def some_function(self):
        model = apps.get_model(app_label='your_app', model_name='YourModel')
like image 132
Saturnix Avatar answered Nov 14 '22 20:11

Saturnix


You have a few options:

1. Import by name

Django has a utility function for importing by string name so you don't need to import yourself. There are several methods available for this (see this question: Django: Get model from string?)

from django.db.models.loading import get_model

class SomeModelManager(...):
    ...

    def some_function(self):
        model = get_model('your_app', 'YourModel')
        object = model()

2. Imports at the bottom

Add the import at the bottom of the managers.py file and make sure to simply import the module and not the models themselves.

So...

models.py:

import managers

class SomeModel(models.Model):
    ...
    objects = managers.SomeModelManager()

managers.py

class SomeModelManager(...):
    ...

    def some_function(self):
        object = models.SomeOtherModel()

import models
like image 28
Wolph Avatar answered Nov 14 '22 22:11

Wolph