It’s quite easy to run into import problems with Django and apps which interact with each other. My question is simple:
What is the accepted process for minimizing circular imports or has anyone come up with an accepted coding standard to reduce these which they are willing to share.?
I’m looking for good principles that can be standardized on.
Models
class Program(models.Model):
group = models.ForeignKey(Group, related_name="%(app_label)s_%(class)s_related")
vs
class Program(models.Model):
group = models.ForeignKey('auth.Group', related_name="%(app_label)s_%(class)s_related")
Views:
class ProgramDetailView(DetailView):
"""Detail view of the EEP Program"""
def get_queryset(self):
"""Narrow this based on your company"""
from apps.company.models import Company
company = Company.objects.get(name="foo")
return Program.objects.filter(company = company)
vs (which tends to cause the issues..
from apps.company.models import Company
class ProgramDetailView(DetailView):
"""Detail view of the EEP Program"""
def get_queryset(self):
"""Narrow this based on your company"""
company = Company.objects.get(name="foo")
return Program.objects.filter(company = company)
The problem with this is that you tend to do a lot of imports all over the place..
Over the years I standardized on some patterns, based on my observations on
how I develop web apps.
I don’t know what are your standards about modularity and code re-use but the
following simple rules/patterns have helped me greatly with some fairly large
projects.
I have noticed that many of my models share some common attributes. For example
I prefer to use UUID’s instead of simple auto increment integers, as primary keys.
So I have this abstract model.
Many of my models need the the concept of
activation. So I have another abstract model,similar to this:
There are many other abstract models I use for tracking creation time and modification, or
if something is
finalizedand can’t be further modified, etc.All these abstract models live in the
coreapp. This is how I call it.Apart from the
coreapp, I have atasksapp. Thetasksapp offers abstractmodels that augments any interfacing I have to do with celery which I use a lot.
The
tasksapp can import models from thecoreapp, but not the other way around.I have also an
mmsapp, which handles Multimedia creation and transformations(thumbnails, etc). Themmscan import models from the previous apps. So the import relationship we have right now is this: core -> tasks -> mms.Every other app I create is specific to the current project I am working on and builds upon
the previous apps. So basically I try to have “one way imports” if you can call it that.
And I end up with models that look similar to this:
If an app grows too big I “micromanage” the app by breaking the
models.pymodule intosmaller modules following the above mentioned rules. I have found out that this covers
most of my needs.
I can’t comment on class based views, because honestly I don’t like them and it almost
always make me write more code instead of less. To each his own. I prefer to use helper
utility functions and make good use of things like context processors, inside
my view functions.
I hope my answer was within the context of your question.
EDIT: I just noticed your usage of
related_namewhich I think misses the point of that option. See the following example:With the above model we can do this, which is very readable:
… and it depicts the functional purpose of this relationship. So
related_nameis notonly used for having related names which are unique.