On example, i have 2 apps: alpha and beta
in alpha/models.py import of model from beta.models
and in beta/models.py import of model from alpha.models
manage.py validate says that ImportError: cannot import name ModelName
how to solve this problem?
I have had this issue in the past there are two models that refer to one another, i.e. using a ForeignKey field. There is a simple way to deal with it, per the Django documentation:
If you need to create a relationship on a model that has not yet been defined, you can use the name of the model, rather than the model object itself:
So in your beta/models.py model, you would have this:
class BetaModel(models.Model):
alpha = models.ForeignKey('alpha.AlphaModel')
...
At this point, importing from alpha.models is not necessary.
Related
I'm trying to create a simple custom manager with one of my Django models. It causes a cyclic import since I'm trying to import the manager from models.py and the model from managers.py. However, because my manager is creating the model and adding some extra attributes, the type hint for the method is the model instance. I'm having trouble with fixing that type hint since it's not yet imported.
# models.py
from .managers import PublishedBundleManager
class PublishedBundle(models.Model):
data = JSONField()
md5_checksum = models.CharField(max_length=128)
objects = PublishedBundleManager()
The manager has a method to help me create the model instance, but as a convenience, calculates a checksum to fill in during creation. To fix the cyclic imports, I made use of typing.TYPE_CHECKING
# managers.py
import typing as t
from django.apps import apps
from django.db import models
if t.TYPE_CHECKING:
PublishedBundle = apps.get_model(app_label="the_hugh", model_name="PublishedBundle")
class PublishedBundleManager(models.Manager): # Error 1
def create_publish(self, data: t.Dict, description: str) -> PublishedBundle: # Error 2
PublishedBundle = apps.get_model(app_label="my_app", model_name="PublishedBundle")
json_data = json.dumps(data, sort_keys=True)
md5_checksum = hashlib.md5(json_data.encode("utf-8")).hexdigest()
return PublishedBundle.objects.create(data=data, md5_checksum=md5_checksum)
However, I'm getting 2 errors.
Missing type parameters for generic type "Manager" [type-arg]mypy(error)
name 'PublishedBundle' is not defined
I'm fairly new with typed python and never faced this issue before. I understand that 2 is happening because PublishedBundle hasn't yet been defined, but I can't define it because it causes a cyclic import. Can anyone help me out please?
One simple way to work around this is to have the manager and the model in the same file. They are intricately related anyway.
Having a quite large models.py file (which contains several models), I'm trying to refactor, with one model per file.
I'm therefore trying to create a models package, with the following structure:
app/models/__init__.py
app/models/first_model.py
app/models/second_model.py
Unfortunately, I cannot get Django lazy reference mechanism to work well, i.e.:
first_model = models.ForeignKey('app.FirstModel')
returns the error that Django cannot find the model.
Any idea? Thanks!
It should work, make sure that in __init__.py you are importing all the models from first_model.py and second_model.py.
from .first_model import FirstModel
from .second_model import SecondModel
EDIT: If you want to retrieve the models as 'app_label.model_name', then you will have to import them in __init__.py, otherwise you can try the following:
Use https://docs.djangoproject.com/en/2.0/ref/applications/#django.apps.apps.get_model
Or you can use ContentTypes: https://docs.djangoproject.com/en/2.0/ref/contrib/contenttypes/#methods-on-contenttype-instances
The presence of __init__.py tells Python to consider it as a Package, but in order to let Django find your models for Migration and find it well, you should import all your models stuff in __init__.py
Keep the structure like it was:
app/models/__init__.py
app/models/first_model.py
app/models/second_model.py
__init__.py
from .first_models import *
from .second_models import *
In the Cookbook there is an example using only the name of the class (model) and not the app part:
first_model = models.ForeignKey('FirstModel')
I have a Python/Flask app that uses MongoEngine for the database. I have defined my models, and everything was working until the newest models were added. I believe the problem occurs because both models reference each other and it's causing a recursive import loop. I'm not sure what to do to solve it though. This is going to be a large project with lots of models referencing each other. This particular instance is because users are in practices, and practices have users, so it's a many to many relationship.
User Model
from utilities.common import utc_now_ts as now
from mongoengine import *
from models.practice import Practice
class User(Document):
name = StringField()
created = IntField(db_field="cr", default=now)
practices = ListField(ReferenceField(Practice))
And the practice model
from utilities.common import utc_now_ts as now
from mongoengine import *
from models import user
class Practice(Document):
name = StringField()
created = IntField(db_field="cr", default=now)
users = ListField(ReferenceField(user.User))
admins = ListField(ReferenceField(user.User))
The error I get is ImportError: cannot import name 'Practice'
I have two other models that are running into the same issue. The models worked fine until I added in the imports to the other model.
I am by no means an expert on MongoEngine, but it looks like you can reference a model by string as opposed to by class. In that case you can change your Practice model to look like this.
from utilities.common import utc_now_ts as now
from mongoengine import *
class Practice(Document):
name = StringField()
created = IntField(db_field="cr", default=now)
users = ListField(ReferenceField('User'))
admins = ListField(ReferenceField('User'))
I hope this helps.
The short answer is that you can't have circular references. The compiler doesn't trust that you will properly "bottom out" on resolving references, and it's not going to iterate through the graph to find out.
One way to fix this is to use a master class that imports the various classes; your worker classes then import their needs from the master class.
After the models.py in one app grew quite large, I've tried to move some of the classes into subpackages.
The old structure was something like this:
# File: assets/models.py
class Asset(...):
# lots of irrelevant code
# File: widgets/models.py
from assets.models import Asset
class Video(...):
asset = models.ForeignKey(Asset)
This worked without a problem, so I'm not going into further details about the structure.
What I've tried to do now is move the Asset class into a submodule. The structure is now as follows:
# File: assets/models/__init__.py (of course I deleted the old models.py)
from .assets import Asset
# File: assets/models/assets.py
class Asset(...):
# lots of irrelevant code
# File: widgets/models.py
from assets.models.assets import Asset
class Video(...):
asset = models.ForeignKey(Asset)
Somehow this doesn't work, and I can't figure out what actually causes the trouble. The error I'm getting is this:
widgets.video: 'asset' has a relation with model , which has either not been installed or
is abstract
It appears that Django can't reliably detect which app a model belongs to if it's in a nested submodule (ie. not directly inside APPNAME.models).
This is a known problem and can be solved by adding the following lines (in this case to the Asset class), thus defining explicitly which app a model belongs to:
class Asset(models.Model):
...
class Meta:
app_label = 'assets'
...
References:
https://groups.google.com/forum/#!topic/django-users/MmaiKvbDlDc
https://code.djangoproject.com/ticket/14007
You should import from models as before:
from assets.models import Asset
This allows you to always import from models but organise the models separately within the models directory. It also means, conceptually, that Asset is still in models as your ForeignKey refers to a assets.models.Asset object, not assets.models.assets.Asset.
I have a circular dependency in my Django models, such that model A has a foreign key reference to B, while B has a many-to-many reference to A. I've consulted other SO posts and have used the string model names instead of the actual classes, but to no avail. Here are abbreviated versions of my two classes:
User model
import listings.models
class User(models.Model):
...
favorites = models.ManyToManyField('listings.models.Listing')
Listing model
import users.models
class Listing(models.Model):
...
owner = models.ForeignKey('users.models.User')
Every time I attempt to run syncdb, it outputs the following error:
Error: One or more models did not validate: users.user: 'favorites'
has an m2m relation with model listings.models.Listing, which has
either not been installed or is abstract. listings.listing: 'owner'
has a relation with model users.models.User, which has either not
been installed or is abstract.
How do I resolve this without sacrificing the established relationship?
'listings.models.Listing' should be 'listings.Listing'
'users.models.User' should be 'users.User' (or 'auth.User' if you were to use django.contrib.auth.models.User)
Refer to official documentation for more.
You can just delete your imports because, you're not depend on them on code. You use just string with model name - it's not a dependency.
Also you should delete models - from your strings because you can refer to your model as app_name.model_name