Extending imagestore models - django

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.

Related

import error when organizing django models in sperate files

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.

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.

Django import error from foreign key in another application model

I followed this post here and sorted out how to set the ForeignKey of one model to a model in another application. However, when I try it a second time I get an error and not sure why.
I have Central app with models for a 'project' and an 'annotation', and a Reports app with a report model. An 'annotation' has a FK to a 'report' in the Reports app, and that seems to work fine with this code:
#models.py for Central app
from GIanno.pt_reports.models import Report
class annotation(models.Model):
...
report=models.ForeignKey(Report)
But, in the Reports app, when I try to set a FK for the 'report' to link it to a 'project' from the 'Central' app using the same format as above, I get an error "cannot import name 'project' from the import line.
Any ideas on why it works one way and not the other. Does order somehow matter? Thanks
My guess is that you have created a circular import condition. This occurs when you import something from one python module which in turns imports from the module which is trying to import it, thus preventing the import from ever resolving.
In general there are three strategies for dealing with circular imports, two of which will work in this case:
Move around your classes and imports so that the imports only go one direction.
Use lazy evaluation. In Django's case this can be accomplished for a ForeignKey by passing a string specifying the app name and model using dot notation: report=models.ForeignKey('central.Report')
Move the import statement out of the global module scope and into the scope of a function within the module. That way the import isn't evaluated immediately and the module can be successfully imported as a whole while still allowing the import within the module to happen when it's called. (Note: this won't work for ForeignKey relationships)
The lazy FK resolution (#2) is probably your best bet here. In general, though the best strategy is to simplify your model/module arrangement to avoid circular imports whenever possible.
Try:
class annotation(models.Model):
...
report=models.ForeignKey('centralapp.Report')
Replace 'centralapp' with name of your central app name without needing to import.
Lazy Relationships
Another scenario where the Lazy Relationships might be useful is with import order. It's not a circular reference (where it can't tell who's first) but a case where one piece of code is loaded before the other can be.
For example, let's say I have a Doc Model and a Log Model. The Log model has a FK for the Doc so I can record changes in the document. This works fine until, let's say, I try to generate a Log record in my save method for my Doc model (to make a save event log entry). There is no Log PK in the Doc object in this case but is a similar issue.
In this case you get an import order problem, where one will try to reference something that has not been loaded into Python yet. It's similar to a Circular Reference but a different cause.
This can be solved other ways but is another example where you will run into this problem.

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.