简体   繁体   中英

Using another model manager's code in a Django custom manager class

I have two models, say, Question and Topic .

I am trying to add methods to the Question model's custom manager, eg some method that filters by Topic .

I can't seem to use the other manager's code for this (cannot import Topic either, so I can't do Topic.objects... )

In class QuestionManager

def my_feed(self, user):
       topics = TopicManager().filter(user=user) # 1st approach
       #topics = Topic.objects.filter(user=user) # 2nd line
       # do something with topics

class TopicManager....

Using 1st approach, I get the following error:

virtualenv/local/lib/python2.7/site-packages/django/db/models/sql/query.pyc in get_meta(self)
    219         by subclasses.
    220         """
--> 221         return self.model._meta
    222 
    223     def clone(self, klass=None, memo=None, **kwargs):

AttributeError: 'NoneType' object has no attribute '_meta'

I can't use the 2nd line since I can't import Topic, since Topic depends on the TopicManager in this file. Is there a workaround for this?

You can't use a manager directly, in any circumstance. You always access it via the model class.

If you can't import the model at the top of the file because of a circular dependency, you can simply import it inside the method.

You should be able to place this at the bottom of the managers.py module:

# Prevent circular import error between models.py and managers.py
from apps.drs import models

In your manager classes you can reference other models using models.<modelname> , and this should work, avoiding the circular import.

For example:

class QuestionManager(Manager):

    def my_feed(self, user):
        topics = models.Topic.objects.filter(user=user)
        # do something with topics

# Prevent circular import error between models.py and managers.py
from apps.drs import models

This works because you are importing the module, not the model classes, which results in a lazy import. By the time the function is run the module will be imported and everything will work.

You could also load models by name using django.apps.get_model() :

from django.apps import apps
apps.get_model('my_app', 'MyModel')

Details here

For example:

from django.apps import apps

class QuestionManager(Manager):

    def my_feed(self, user):
        topics = apps.get_model('my_app', 'Topic').objects.filter(user=user)
        # do something with topics

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