Daniel W.
Daniel W.

Reputation: 32290

Django not recognizing I have objects in my Model

Having a Model in file MyApp/models/Artwork.py:

class Artwork(models.Model):
    class Meta:
        verbose_name = _('Artwork')
        verbose_name_plural = _('Artworks')

    def __init__(self, *args, **kwargs):
        super(Artwork, self).__init__(*args, **kwargs)

    objects = ArtworkManager()

And an action in file: MyApp/functions/actions.py

from MyApp.models import Artwork

import pprint;

def lock_artwork(request, id):
    pprint.pprint(Artwork)
    try:
        art = Artwork.objects.get(pk=id)
    except ObjectDoesNotExist:
        raise Http404()

In MyApp/models/__init__.py:

from .Artwork import Artwork

I get the curious error of not having the attribute objects in my model, which is there.

Stacktrace:

web_1  | <module 'MyApp.models.Artwork' from '/app/MyApp/models/Artwork.py'>
web_1  | Internal Server Error: /en/artwork/lock/2/
web_1  | Traceback (most recent call last):
web_1  |   File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
web_1  |     response = get_response(request)
web_1  |   File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 115, in _get_response
web_1  |     response = self.process_exception_by_middleware(e, request)
web_1  |   File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 113, in _get_response
web_1  |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
web_1  |   File "/app/MyApp/functions/actions.py", line 72, in lock_artwork
web_1  |     art = Artwork.objects.get(pk=id)
web_1  | AttributeError: module 'MyApp.models.Artwork' has no attribute 'objects'

Something obvious I'm missing?

Upvotes: 1

Views: 1589

Answers (1)

user2390182
user2390182

Reputation: 73460

For all of Django's automagic (migrations, model loading, ...) to work, models have to live in the namespace of their app's models! It does not matter whether that is a plain module or a package. What we often do to separate models in different modules within an app is the following:

MyApp
    models
        __init__.py
        artwork  # not the name of any model inside it!
        other

And inside the __init__.py, you import all the models from the submodules:

# __init__.py
from .artwork import Artwork
from .other import OtherModel, YetAnotherModel

That way, models.Artwork resolves to the actual model and is picked up by all of django's internal magic. You can now also import the Artwork model straight from MyApp.models anywhere in your code:

# e.g. some views.py
from MyApp.models import Artwork

On a side note: 10 models in a file is not that much. I would only split that if there are clear semantic separations and no circular references (in which case you could argue for separate apps to begin with). If dozens of models and hundreds of lines in a file should are an issue, you might want to look for a better IDE ;-)

Upvotes: 1

Related Questions