import error when organizing django models in sperate files - django

Following the django docu I wanted to seperate my models into different files model1.py and model2.py. I also imported both of them in the __init__.py. But because they have a relationship, I need to import each of them in the other file. Now I get an error for from .model1 import Model1 that says
ImportError: cannot import name 'Model1'
is there a problem because I want to import within model2.py a class from model1.py that itself is importing from model2.py?
You might say, separating each model in a different file is normally not done in django. But I think it would be much better arranged when you have one file for one model.

This caused because of circular imports. from a import b and from b import a!. Please remove that by splitting the models properly.

Related

How do I import multiple classes in another django app correctly

I am using python 3.5 + django 1.11 and I have two apps hr and payroll in my project called ERP.
On payroll app model.py I'm importing classes from hr as below:
# Imports from your apps
from hr.models import (
# Employee,
Job,
JobHistory,
Department,
Section,
Region,
Country,
Location,
)
I think this is cumbersome for me considering if in the future I will add more classes to hr I will have to add the same classes as imports above.
Is there a simpler way to import them at once without adding them one by one ?
If you only use the models in foreign keys/many-to-many/one-to-one fields, then you may not need to import the models at all. Just use a string instead:
class MyModel(models.Model):
job = models.ForeignKey('hr.Job', ...)
Another option is to import the models directory:
import hr.models as hr_models
Then change the code to use hr_models e.g. hr_models.Job, hr_models.JobHistory.
Finally, you could do a star import, but this is discouraged because it makes it harder to see where models have been imported from.
from hr.models import *
Note that code is written once but read many times, so it's probably worth the extra time to update the imports instead of a star import.

Test failure because model couldn't be imported

Application I am working on is proprietary and thus I will try to provide as much information as possible.
When running python manage.py test, which runs all the tests, only one application among many others fails. Too many hours have been burned on this.
The output is:
ImportError: Failed to import test module: app.aom.apps.forum.tests
after this, tracing is listed and then one line which says that the problem occurs when importing models into tests.py file, that is:
from .models import ForumSectionGroup, ForumSection, ForumThread, ForumPost
and the last line of the output is:
RuntimeError: Model class app.aom.apps.forum.models.ForumSectionGroup doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.
I have Googled and researched what could cause this problem, and the conclusion: either I am importing module before application is loaded or I don't have the application listed in INSTALLED_APPS. But none of these seems to be the problem. Maybe testing mechanism somehow skips few steps and renders the model unloaded before importing it.
Explicitly assigning app_label as part of class Meta in the model results in conflict, because the model ends up registered twice, when I force it. I was driven to this conclusion by looking at the code at line 111, https://github.com/django/django/blob/master/django/db/models/base.py
I ran into this same issue. For me what fixed it was changing
from .models import Model1, Model2
to
from app.models import Model1, Model2
The from .model import syntax works fine in view.py, etc. but in the tests it was not working. This only seems to be the case when using a non-standard structure as pointed out in a comment above.
In my specific case I was using Django 1.11.

Extending imagestore models

I'm trying to install imagestore app in my project. Default models are created succefully, and all other parts working properly.
But, it have a feature to extend base (abstract) models and create your own by some complicated mechanism. This is mine model:
from django.db import models
from imagestore.models.bases.album import BaseAlbum
class Newalbum(BaseAlbum):
title = models.CharField("title", max_length=128)
class Meta(BaseAlbum.Meta):
app_label = "imagestore"
abstract = False
Also I have a string IMAGESTORE_ALBUM_MODEL = 'art.models.Newalbum' in my settings.
When I run syncdb it tells me Backend module "art.models" does not define a "Newalbum" class. ('module' object has no attribute 'Newalbum').
But of course it defined.
And the strangeness is only begins. When I put debug statement in the place where imagestore trying to get my model it prints proper module (already imported) and proper class name (string). But! dir(mod) prints only variables appeared before "from imagestore.models.bases.album import BaseAlbum" .In above example only "models" and default underscored attributes. Why? What I don't know about importing modules?
I already tried to install it in many awkward combinations of settings properties, versions of django (and required apps), app_label and so on. It creates tables, when I doesn't add IMAGESTORE_ALBUM_MODEL in my settings, but this models hasn't any BaseClass' behaviour.
So, what I'm doing wrong?
Solved it! While stepping through the import process (I added the following to imagestore.utils.load_class)
import pdb
pdb.set_trace()
I found that there is a circular import. Here's the order of things (slightly simplified):
load_class(IMAGESTORE_ALBUM_MODEL)
from imagestore.models.bases.album import BaseAlbum
BaseAlbum has an FK to IMAGESTORE_IMAGE_MODEL (head), so it gets imported with load_class
load_class(IMAGESTORE_IMAGE_MODEL)
from imagestore.models.bases.image import BaseImage
BaseImage has an FK to IMAGESTORE_ALBUM_MODEL (album), so it gets imported with load_class
When this calls __import__ IMAGESTORE_ALBUM_MODEL is already in sys.modules, though incomplete because it's still being built. And thus the module doesn't have an "Album" attribute yet.
The quick solution is to move the head field to models.album.Album and remove it from BaseAlbum. After doing this I was able to get the site running again. You must use the models package in your new app (not a simple models.py), with Image and Album in separate files.
If this isn't clear enough, drop me a line and I'll try to do better.

Use models outside a view

To send emails and stuff, I use code outside the views.py file (too much code there). I created a file named "tools.py" in the app folder where I start with
from django.shortcuts import render_to_response
from django.core.mail import send_mail
from mysite.myapp.models import MyModel
With runserver, I have an error ImportError: cannot import name MyModel
This is strange as I use the same import in the views.py file and there is no problem...
Any idea ? Thanks
Most likely, you have a circular import. Are you importing this tools.py file in your myapp/models.py?
A couple of things:
Make sure you have your init.py file in the folder where your
"tools.py" file is located, this is a common reason why something might not be found.
I'm working on setting up something that requires something very similar to your requirements.
If you are trying to have this as a on/off process eg.) cronjob, worker etc. Do the following.
#!/usr/bin/env python
#########################################################################
# Required DO NOT REMOVE
#########################################################################
import os
import sys
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "appname.settings")
#########################################################################
# Import My Models, or Run an Include to Handle Processing.
from app.models.model import *
# Do Stuff to Test ( I suggest a simple insert into the model or pull and return content )
Save this file in the same folder that your "manage.py" is saved in, you can call this directly and it should process, you can setup a cronjob for it to run, etc. This allows you
to have a little less code as it doesn't run some of the processes that django runs prior to rendering a view from the urls.py file.
If this is unclear please feel free to comment and I will edit with correction or further details.
All the best

django refactoring models

I've been doing a little clean up on my django project and so I decided to rename some models remove some unnecessary fields etc. I dropped all the tables from the dbase and reran "syncdb". However, now I'm getting and error
Could not import pollsite.polls.views. Error was: cannot import name OldTableName
Its a template error from base.html
OldTableName doesn't exist anymore (I've renamed it). Is there something else I need to run to get the admin site to work properly with the new schema?
You need to check your imports in your pollsite.polls.views. Most likely you still have an import of the old model name in that file.