Namespaces comprehension - python

I'm building django application and i encounter som import problems. My file structure:
project/
my_app/
models/
__init__.py
Article.py
StockMovementProduct.py
tools/
__init__.py
Synchronizer.py
project/my_app/models/_init_.py:
from Article import *
from StockMovementProduct import *
project/my_app/models/Article.py:
from django.db import models
class Article(models.Model):
[...]
project/my_app/models/StockMovementProduct.py:
from django.db import models
from my_app.tools import Synchronizer
class StockMovementProduct(models.Model):
def sync_articles(self):
sync = Synchronizer(self)
[...]
project/my_app/tools/_init_.py is empty
project/my_app/tools/Synchronizer.py:
from my_app.models import Article
from my_app.models import StockMovementProduct
class Synchronizer():
[...]
When i run my code this error is raise:
File "/home/bux/Projets/project/my_app/models/__init__.py", line 7, in <module>
from StockMovementProduct import *
File "/home/bux/Projets/project/my_app/models/StockMovementProduct.py", line 5, in <module>
from my_app.tools import Synchronizer
File "/home/bux/Projets/project/my_app/tools/Synchronizer.py", line 2, in <module>
from my_app.models import StockMovementProduct
ImportError: cannot import name StockMovementProduct
I don't understand why (in Synchronizer.py) Article import work and StockMovementProduct import don't.
In Synchronizer.py i also try:
from my_app.models import Article
from ..models import StockMovementProduct
But without success. What i'm missing with import methodology ?

You have a circular import in your code, namely your StockMovementProduct.py imports Synchronizer.py and yet Synchronizer.py imports StockMovementProduct.py. This is a pretty common problem and there are already a lot of help on that: Circular dependency in Python.

You have a circular import. StockMovementProduct imports Synchronizer, and Synchronizer imports StockMovementProduct.
You need to re structure and maybe move the common dependancies into a 3rd file. It's difficult to suggest a solution though without knowing the content

Related

Mypy complaining about Name "Optional" is not defined without the use of Optional

I've recently started using mypy, and have run into some weird problems that i cannot for the life of me seem to figure out.
I'm using mypy 0.950, django-stubs 1.11.0, django 4.0.5 and python 3.10.2.
Running mypy through the command line returns this:
project/suppliers/models.py:6: error: Name "Optional" is not defined
project/suppliers/models.py:6: note: Did you forget to import it from "typing"? (Suggestion: "from typing import Optional")
project/users/models.py:6: error: Name "Optional" is not defined
project/users/models.py:6: note: Did you forget to import it from "typing"? (Suggestion: "from typing import Optional")
project/products/models.py:6: error: Name "Optional" is not defined
project/products/models.py:6: note: Did you forget to import it from "typing"? (Suggestion: "from typing import Optional")(Suggestion: "from typing import Optional")
However, line 6 in project/suppliers/models.py is completely empty:
from django.contrib.sites.managers import CurrentSiteManager
from django.contrib.sites.models import Site
from django.db import models
from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _
from django_countries.fields import CountryField
from project.core.models import BaseImageModel, BaseModel
from project.suppliers.managers import SupplierQuerySet
_SupplierManager = models.Manager.from_queryset(SupplierQuerySet)
class Supplier(BaseModel, BaseImageModel):
...
Line 6 in project/users/models.py is a django import from django.contrib.contenttypes.models import ContentType:
import random
from typing import Any
from django.conf import settings
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.contrib.contenttypes.models import ContentType
from django.contrib.sites.managers import CurrentSiteManager
from django.contrib.sites.models import Site
from django.core import signing
from django.core.mail import send_mail
from django.db import models
from django.forms import ValidationError
from django.http import HttpRequest
from django.template.loader import render_to_string
from django.utils import timezone
from django.utils.encoding import force_bytes, force_str
from django.utils.http import (
urlsafe_base64_decode as uid_decoder,
urlsafe_base64_encode as uid_encoder,
)
from django.utils.translation import gettext_lazy as _
import phonenumbers
from project.users.enums import AvatarColors
from project.users.managers import UserQuerySet
from project.users.schemas.records import (
UserAuditLogsRecord,
UserNotesRecord,
UserProfileRecord,
)
_UserManager = models.Manager.from_queryset(UserQuerySet)
class User(AbstractBaseUser, PermissionsMixin):
And line 6 in project/products/models.py is yet another django import from django.utils.text import slugify:
from decimal import Decimal
from django.contrib.sites.managers import CurrentSiteManager
from django.contrib.sites.models import Site
from django.db import models
from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _
from imagekit.models import ImageSpecField
from imagekit.processors import ResizeToFill
from mptt.models import TreeManyToManyField
...
My mypy config is as follows:
[tool.mypy]
plugins = ["mypy_django_plugin.main", "pydantic.mypy"]
follow_imports = "normal"
ignore_missing_imports = true
disallow_untyped_calls = true
disallow_untyped_defs = true
disallow_incomplete_defs = true
warn_unused_configs = true
warn_redundant_casts = true
warn_unused_ignores = true
warn_return_any = true
warn_unreachable = true
no_implicit_optional = true
no_implicit_reexport = true
check_untyped_defs = true
strict_equality = true
[tool.django-stubs]
django_settings_module = "project.settings"
[tool.pydantic-mypy]
init_forbid_extra = true
init_typed = true
warn_required_dynamic_aliases = true
warn_untyped_fields = true
# Admin files uses some patterns that are not easily typed
[[tool.mypy.overrides]]
module = "project.*.admin"
ignore_errors = true
[[tool.mypy.overrides]]
module = "project.*.tests.*"
ignore_errors = true
[[tool.mypy.overrides]]
module = "project.*.migrations.*"
ignore_errors = "true"
[[tool.mypy.overrides]]
module = "project.*.management.*"
disallow_untyped_defs = false
I've tried googling around, but can not seem to find anyone else that has experienced this. Anything obvious that I've missed, or does it look like a bug? Seems to me at least that this would affect quite a lot if it was something wrong with mypy/django stubs.
Fast 1st-party fix
You can add from typing import Optional to files that use CurrentSiteManager. It will resolve this problem (yes, # noqa: F401 is your friend).
One-time fix for package
As a quick workaround, you can modify django-stubs/contrib/sites/managers.pyi to have the following content:
from typing import Optional, TypeVar
from django.db import models
_T = TypeVar('_T', bound=models.Model)
class CurrentSiteManager(models.Manager[_T]):
def __init__(self, field_name: Optional[str] = ...) -> None: ...
Problem root
It is not a real solution and is a bug in mypy_django_plugin. I'm looking for a solution now. The problem is that helpers.copy_method_to_another_class (and consequently transformers.models.AddManagers.create_new_model_parametrized_manager) is using context of model class definition. I don't understand now how to get and pass another context properly without symmetrical issue, and merging is definitely not an option. I'll update this on success and raise a PR to maintainer. It would be great if you file an issue to django-stubs (and attach link to this question) so that I have less to explain (or somebody else could help if I fail).
Better fix #1
here we can add original_module_name=base_manager_info.module_name call argument. It will allow resolving everything inherited from first MRO parent. However, it seems like this should fail for longer inheritance chains. My bad, we're actually iterating here over methods of last ancestor only, so this seems to be the final solution.
(I'm sorry for using this as a changelog, but once started...)
This bug should be fixed by this PR if merged.

Django Import Error: cannot import name "Shift"

I'm pretty sure it's due to a circular import but I'm not too sure how to solve my issue
in mysite/shifts/models.py
from django.db import models
class Shift(models.Model):
# defines a shift`
in mysite/shifts/scrapes.py
from shifts.models import Shift
I can share more code if you need but I believe the issue is here, I've added my apps to settings.py and I get this error when I run scrapes.py as a django-admin command
from shifts.models import Shift
ImportError: No module named 'shifts'
project_structure
Use the following line in mysite/shifts/scrapes.py
from .models import Shift
from mysite.shifts.models import Shift

Model class doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS

I am using sphinx and was trying to generate documentation for my Django project. I decided to first try to document the models so in my .rst file I did this
wdland\.models
==============
.. automodule:: wdland.models
:members:
:undoc-members:
:show-inheritance:
But the get the following errors
WARNING: /home/fabou/wdlandenvpy3/source/docs/wdland.rst:9: (WARNING/2) autodoc: failed to import module 'wdland.models'; the following exception was raised:
Traceback (most recent call last):
File "/home/fabou/wdlandenvpy3/lib/python3.5/site-packages/sphinx/ext/autodoc.py", line 657, in import_object
__import__(self.modname)
File "/home/fabou/wdlandenvpy3/source/wdland/models.py", line 35, in <module>
class Device(models.Model):
File "/home/fabou/wdlandenvpy3/lib/python3.5/site-packages/django/db/models/base.py", line 118, in __new__
"INSTALLED_APPS." % (module, name)
RuntimeError: Model class wdland.models.Device doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.
After some google search I found a solution here Django 1.9 deprecation warnings app_label see comment from Роман Арсеньев on “Jan 11 '16 at 14:54”
I went in my models.py and added “class Meta: app_label” as per above post to every single class I had in models.py. This fixed the problem and I was able to generate the documentation for my models using the sphinx-build script.
Now I wanted to do the same for views.py and did this in my .rst file
wdland\.views
=============
.. automodule:: wdland.views
:members:
:undoc-members:
:show-inheritance:
But on compile I get this new similar error and I have been unable to find a solution for it nor did understand the previous fix for models.
WARNING: /home/fabou/wdlandenvpy3/source/docs/wdland.rst:19: (WARNING/2) autodoc: failed to import module 'wdland.views'; the following exception was raised:
Traceback (most recent call last):
File "/home/fabou/wdlandenvpy3/lib/python3.5/site-packages/sphinx/ext/autodoc.py", line 657, in import_object
__import__(self.modname)
File "/home/fabou/wdlandenvpy3/source/wdland/views.py", line 2, in <module>
from . import views
File "/home/fabou/wdlandenvpy3/source/wdland/views.py", line 19, in <module>
from .forms import TicketForm, TicketAmendForm
File "/home/fabou/wdlandenvpy3/source/wdland/forms.py", line 1, in <module>
from django.contrib.auth.forms import AuthenticationForm
File "/home/fabou/wdlandenvpy3/lib/python3.5/site-packages/django/contrib/auth/forms.py", line 12, in <module>
from django.contrib.auth.models import User
File "/home/fabou/wdlandenvpy3/lib/python3.5/site-packages/django/contrib/auth/models.py", line 6, in <module>
from django.contrib.contenttypes.models import ContentType
File "/home/fabou/wdlandenvpy3/lib/python3.5/site-packages/django/contrib/contenttypes/models.py", line 139, in <module>
class ContentType(models.Model):
File "/home/fabou/wdlandenvpy3/lib/python3.5/site-packages/django/db/models/base.py", line 118, in __new__
"INSTALLED_APPS." % (module, name)
RuntimeError: Model class django.contrib.contenttypes.models.ContentType doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.
Here the relevant sphinx configuration
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import django
import os
import sphinx_rtd_theme
import sys
from django.conf import settings
sys.path.insert(0, os.path.abspath('../'))
settings.configure()
django.setup()
wdland is a Django app an is listed in my INSTALLED_APPS tuple in the settings file. The sphinx docs folder is at the same level as the wdland folder.
Reading similar threads on the topic seem to point to modules that are not yet loaded when being called. I have no clue how to fix as not experienced in either sphinx and Django. Any idea on how I can fix this?
Trying to document urls.py would yield similar errors.
EDIT:
Here the begining of my view.py
import datetime
from django.core.urlresolvers import reverse
from django.db.models import Q
from django.http import Http404, HttpResponse
from django.template.loader import render_to_string
from django.shortcuts import render, HttpResponseRedirect
from django.views import generic
from random import randint
from script.serversnmp import get_ubuntu_snmp, get_esxi_snmp
from script.wdlandtools import get_monthly_sess_hour_stats,\
get_monthly_sess_nb_stats,\
get_monthly_ticket_stats,\
get_ticket_category_stats,\
clean_usersession_tbl, update_usertotals_tbl,\
send_email_notification, get_adsl_usage
from wdland.models import Device, UserSession, SupportTicket, News, UserTotals,\
SavedUsrSess
from .forms import TicketForm, TicketAmendForm
from jchart import Chart
from jchart.config import Axes, DataSet, rgba
My solution was to create a BaseModel abstract class on your models.py within your app, on your error this may be:
class BaseModel(models.Model):
class Meta:
abstract = True # specify this model as an Abstract Model
app_label = 'wdland'
And made all models inherit from this instead of the usual models.Model.
To solve it, I went to the basics of trying to figure out the error message, which states:
Model class wdland.models.Device doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.
I also had the same error with a different app. Adding the requested "app_label" solved the issue.
I think you don't have django.contrib.contenttypes this in INSTALLED_APPS of django settings.So add it in INSTALLED_APPS of django settings

ImportError when importing from a lower module

I'm trying to import an object named db (SQLAlchemy object) in in a module of my Flask Project in order to use the SQLAlchemy in my models (models.py). Assuming my package is named Foo and contains the db object in his __init__.py file , when i try to do a from Foo import db, i get the following error:
ImportError: cannot import name db
I'm using Flask Blueprint to dispatch my project into two applications (dashboard and frontend) and each of them contains an __init__.pyfile. Only the models.py is throwing this error, i got some imports in my views file (as importing the login manager) and everything goes well.
Any idea of what it could be ?
UPDATE : The traceback
Traceback (most recent call last):
File "run.py", line 4, in <module>
from kuchiyose import app
File "/path_to_project/kuchiyose/kuchiyose/__init__.py", line 60, in <module>
from kuchiyose import dashboard, frontend
File "/path_to_project/kuchiyose/kuchiyose/dashboard/__init__.py", line 10, in <module>
from dashboard import views
File "/path_to_project/kuchiyose/kuchiyose/dashboard/__init__.py", line 10, in <module>
from dashboard import views
File "/path_to_project/kuchiyose/kuchiyose/dashboard/views.py", line 8, in <module>
from kuchiyose.dashboard.models import User
File "/path_to_project/kuchiyose/kuchiyose/dashboard/models.py", line 3, in <module>
from kuchiyose import db
ImportError: cannot import name db
First, thanks for the help. Concerning my second question : "How to import Flask models into views without having a circular import issue (when using SQLAlchemy)", i found a solution. It consists to setup the SQLAlchemy object not into the application __init__.pyfile but into the models.pyfile itself. With that, you can import it in your views.pyfile without problem.
My models.py file, now:
from kuchiyose import app
from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy(app)
And my views.py
from kuchiyose.dashboard import models
This is an old one but showed up as a top result in my search.
I have a project that has model declarations in a few different places rather than a consolidated models.py file so this solution wouldn't be ideal. I found importing your views AFTER establishing the db object works as well.
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config.from_object('config')
db = SQLAlchemy(app)
# Now Register routes
# db is now defined so app import db will now work)
from routes.user import user as user_routes
app.register_blueprint(user_routes)
there appears to be circular imports:
kuchiyose/__init__.py imports from kuchiyose.dashboard.views
kuchiyose/dashboard/views.py imports from kuchiyose.dashboard.models
kuchiyose/dashboard/models.py imports from kuchiyose
see e.g. Circular (or cyclic) imports in Python for more info...

Django ImportError looks like a loop

In my django project I have the following:
apps1/models.py: Post (model)
apps2/models.py: Blogs (model)
apps2/functions.py: get_blogs (method)
The apps1/models.py file imports the Blogs model from apps2/models.py.
The apps2/models.py file imports the get_blogs method from apps2/functions.py.
The apps2/functions.py file import the Post model from apps1/models.py.
I am getting the following error:
ImportError at /
cannot import name Post
Traceback
admin.autodiscover()
<in file apps1/models.py>
from apps2.models import Blogs
<in file apps2/models.py>
from apps2.functions import get_blogs
<in file apps2/functions.py>
from apps1.models import Post
I thought it might be that the admin.autodiscover is importing the Post model first and then through an import loop, it is trying to import it again. Although I tried changing it to:
from apps1.models import Post as OtherPost
but that didn't help. Any idea why this is happening? Is it because there is a loop now?
If the only reason you import Blogs in apps1.models is that you have a relationship field in Post, how about using a lazy relationship instead? As far as I understand, those were designed specifically to deal with import loops like the one you're experiencing.
It is quite easy, instead of
from apps2.models import Blogs
...
class Post(models.Model):
...
my_blog = models.ForeignKey(Blogs)
you use something like this:
class Post(models.Model):
...
my_blog = models.ForeignKey("apps2.Blogs")

Categories

Resources