Проблема импорта Python с помощью команд управления Django - PullRequest
4 голосов
/ 14 сентября 2010

По какой-то причине, когда я был новичком в Python и Django, я написал несколько операторов import, таких как это, в верхней части файла models.py:

from django.contrib import auth

И я бы использовал его вот так:

class MyModel(models.Model):
    user = models.ForeignKey(auth.models.User)
    # ...

Это работало нормально.Спустя долгое время я написал пользовательскую команду управления, и она сделала бы это:

from myapp.models import MyModel

Когда я запустил свою пользовательскую команду (python manage.py my_command), это привело бы к тому, что Python пожаловался, что модуль authне было атрибута models в строке, объявляющей ForeignKey в models.py.

Чтобы обойти эту проблему, я изменил свой models.py на более обычный:

from django.contrib.auth.models import User

class MyModel(models.Model):
    user = models.ForeignKey(User)
    # ...

Может кто-нибудь объяснить мне, что мне не хватает?Есть ли что-то другое в среде, когда вы запускаете команду управления?Или я все время делал неправильно?Спасибо!

Редактировать : Следуя догадке dmitko о циклическом импорте, вот импорт, использованный в моем файле models.py.Я показываю исходный импорт auth с комментариями, а также единственную модель, которая имеет внешний ключ для модели аутентификации пользователя:

import datetime  
from django.db import models 
# from django.contrib import auth
from django.contrib.auth.models import User 

class UserLastVisit(models.Model):
    # user = models.ForeignKey(auth.models.User, unique=True)
    #                          ^^^^^^^^^^^^^^^^
    # after adding mgmt command, error occurred here; change to the line below
    user = models.ForeignKey(User, unique=True)
    last_visit = models.DateTimeField(db_index=True)

А вот импорт команды управления, которая обнаружилапроблема:

import datetime   
from django.core.management.base import NoArgsCommand 
from core.models import UserLastVisit, AnonLastVisit, Statistic

Была ли эта ситуация настроена на циклический тип импорта?

Ответы [ 3 ]

5 голосов
/ 17 сентября 2010

Если какой-либо случайный модуль когда-либо импортирует модуль x.y.z, то более поздний человек, который импортирует только x.y, увидит z в пространстве имен x.y.

Причина, по которой это происходит, заключается в том, что import x.y.z - это фактически три оператора импорта в одном. Это работает примерно так:

x = __internal_import('x')
x.y = __internal_import('x/y')
x.y.z = __internal_import('x/y/z')

В следующий раз, когда кто-то сделает __internal_import('x/y'), он получит один и тот же объект, потому что python достаточно умен, чтобы дважды не импортировать один и тот же. У этого объекта уже есть элемент z, назначенный модулю z.

В вашем полном приложении, вероятно, был модуль, который сделал import django.contrib.auth.models. Но ваша минимальная отдельная программа не импортировала этот модуль, поэтому имя никогда не назначалось.

(Примечание: такого понятия, как __internal_import, не существует. Это просто иллюстрация. У реальной функции есть другое имя, которое вам нужно найти.)

0 голосов
/ 16 сентября 2010

Трудно точно сказать, что происходит, не увидев добавленную вами команду manage.py.Тем не менее, я часто вижу «не имеет атрибута» в случаях с циклическим импортом, и почти всегда это исправляется путем изменения импорта на уровне модуля на импорт на уровне функций или класса, как вы делали здесь.Вы можете проверить, происходит ли что-то подобное здесь.

0 голосов
/ 15 сентября 2010

Я полагаю, что если вы сделаете from django.contrib import auth, это означает, что вы импортируете пакет auth как модуль, и то, что он экспортирует, управляется __init__.py в папке auth:

>>> from django.contrib import auth
>>> dir(auth)
['BACKEND_SESSION_KEY', 'ImproperlyConfigured', 'REDIRECT_FIELD_NAME', 'SESSION_
KEY', '__builtins__', '__doc__', '__file__', '__name__', '__path__', 'authentica
te', 'datetime', 'get_backends', 'get_user', 'import_module', 'load_backend', 'l
ogin', 'logout']

Вы можете проверить__init__.py в django\contrib\auth и увидеть тот же список функций.Когда вы импортируете from django.contrib.auth.models import User, это означает, что вы импортируете подмодуль из пакета auth, и он работает.

Кстати.Я не смог использовать auth.models.User в любом случае - независимо от того, запущен ли я из консоли или из моего приложения django.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...