Reputation:
Following the tutorial for Django 1.10 with a few small deviations:
polls
app exists in mysite/apps/polls
and is accessed in the project via apps.polls
.models.py
file has been removed and a new module has been added:mysite/ | |- apps/ | |- polls/ | | |- models/ | | | |- __init__.py | | | |- Question.py | | | |- Choice.py
apps/polls/models/__init__.py
is importing both Question
and Choice
, and both models are extending from django.db.models.Model
.
The issue
Running makemigrations
throws an exception:
Traceback (most recent call last): File "/mysite/lib/python3.5/site-packages/django/db/models/fields/related.py", line 742, in __init__ to._meta.model_name AttributeError: module 'apps.polls.models.Question' has no attribute '_meta'
However, the Question
model clearly does have a _meta
attribute, as it is extending from django.db.models.Model
. It is my understanding that as of Django 1.7, defining _meta.app_label
is not necessary (in any case, defining app_label
doesn't work). Any idea what I need to do to be able to use models from a subdirectory without causing additional refactoring throughout my project?
Additional resources
apps/polls/models/__init__.py
apps/polls/models/Choice.py
apps/polls/models/Question.py
Upvotes: 1
Views: 488
Reputation: 53679
You are importing the Question
module instead of the Question
model. You need to change it like this:
from django.db import models
from .Question import Question
class Choice(models.Model):
question = models.ForeignKey(Question,
on_delete=models.CASCADE)
choice_text = models.CharField(max_length=250)
votes = models.IntegerField(default=0)
Here the first .Question
refers to the module, and the second Question
refers to the model. The same holds for the import statements in apps/polls/models/__init__.py
.
It's a good idea to use a naming scheme that differentiates between modules and classes. This avoids confusion about what you are actually importing. The usual convention is to use lowercase for module names, and CamelCase for class names. That would give you questions.py
and class Question(models.Model):
.
mysite/
|
|- apps/
| |- polls/
| | |- models/
| | | |- __init__.py
| | | |- question.py
| | | |- choice.py
And:
# apps/polls/models/choice.py
from django.db import models
from .question import Question
class Choice(models.Model):
question = models.ForeignKey(Question,
on_delete=models.CASCADE)
choice_text = models.CharField(max_length=250)
votes = models.IntegerField(default=0)
By following such a convention, the distinction between the module question
and the model Question
is apparent at first sight.
Upvotes: 1