South custom models location - django

I have quite a big django project which has a lot of applications and a lot of models.
In order to avoid circular imports several models modules must be used:
app/models.py
app/models_add.py
app/models_aux.py
and so on.
Each time I have to make a migration I have to write
from app.models_add import Model
in the app/models.py in order for South to track the model's changes.
This seems to be quite annoying because there are a lot of changes in models.
The question is: is there a way to point South which modules/files to track?

You could try setting the app_label on the Meta class of your model.
class Meta:
app_label = "app"
Also try setting your directory structure to:
app/models/__init__.py
app/models/add.py
That should tell everything to initialize properly. This is what I recently did, but for backwards compatibility in other areas of my project I import everything in models/__init__.py

Related

Django best practice: Should I split non-app specific models into my project folder?

I am going to extend the django user models - is it best practice to create a new models.py in my project directory: I.e:
project
application
migrations
static
models.py (all my application specific models)
project
forms.py
urls.py
views.py
*** project models.py ? ***
I want to add email confirmation to my user sign up. So basically just extend the user model. I am thinking this may not be best practice to do in my application models, but for this case it is only going to be one model so would not really matter. However if I want to extend more non-application specific models then it might be better to do this in a separate file?
Does anyone do anything similar and have any tips? Thanks
I don't think putting model inside the project is a food idea, but its practical possible.
For your case I would create an app called utils and put those models there. In real sense i don't think there is non-app specific model . . . correct me if I am wrong.
Plus you can have as many apps as you want
Also you can check post for more

Django apps with models.py in non-standard location

I've just started working on a codebase that the team I've joined is updating from using Django 1.4 to Django 1.8. Along with that change, it's being restructured into separate apps, and the layout is being changed in various ways.
INSTALLED_APPS has some apps, let's call them foo and bar, but their models.py files have been put into db subdirectories, that is foo/db/models.py.
Those models can be accessed from code (for example views) with from foo.db.models import SomeModel, and that seems to work.
However, from my reading of https://docs.djangoproject.com/en/1.8/ref/applications/#initialization-process, particularly stage 2, models defined in foo/db/models.py rather than foo/models.py won't be found during application loading, which will cause a variety of issues.
Is it possible to support this non-standard location of models.py with a custom AppConfig, or in some other way?
To clarify, I think trying to have models.py in a non-standard location is a bad idea; I'm after confirmation to help make my argument to the rest of the team.
The models submodule name is hardcoded, and it's the only module that is imported by Django during that step of the initialization process.
However, you can easily import your models inside your models.py file to ensure your models are imported at the correct time. If all your app's models are defined or imported in foo.db.models, you can simply use this:
# foo/models.py
from foo.db.models import *

Create model just for testing

I have an abstract User model.
The tests include subclassing this abstract model and setting AUTH_USER_MODEL to the subclassed model.
The problem with AUTH_USER_MODEL is it must be of the form "app-name.model-name" and hence it must
refer to a model in a models.py file . But if it is inside a models.py file, it will get sync'ed to production database, which isn't exactly harmful but it would be nice if it isn't so.
I have seen Django: How to create a model dynamically just for testing but the answers seem hackish (and unreliable?)
Currently what I do is:
in [apps]/models.py:
# this model only gets created during a test
if 'test' in sys.argv:
class AccountTest(AbstractAccount):
pass
in [apps]/tests/init.py:
#override_settings(
AUTH_USER_MODEL = '[apps].AccountTest',
)
class AccountManagerTest(TransactionTestCase):
Does anyone have a better way? This feels rather hackish.
Also, any problem with this approach?
A good approach is to use separate settings file for your testing environment. You could have an application that is listed only in the INSTALLED_APPS of these test settings, and implement your test models there. This approach is also good if for example you want to use nose to run your tests etc... Then you should run your tests like this:
python manage.py test --settings=my_project.test_settings

Get the ORM that is created by Django

From the Django docs:
How are the backward relationships possible?
Other object-relational mappers require you to define relationships on
both sides. The Django developers believe this is a violation of the
DRY (Don’t Repeat Yourself) principle, so Django only requires you to
define the relationship on one end.
But how is this possible, given that a model class doesn’t know which
other model classes are related to it until those other model classes
are loaded?
The answer lies in the INSTALLED_APPS setting. The first time any
model is loaded, Django iterates over every model in INSTALLED_APPS
and creates the backward relationships in memory as needed.
Essentially, one of the functions of INSTALLED_APPS is to tell Django
the entire model domain.
Is there a way to get this ORM model? I am trying to debug some reverse relations that are not automagically created and it would really help to see the whole ORM Django has created.
There is no specific ORM "Model", however there are a few things that may help you.
from django.db.models.loading import get_models
get_models() will return you a list of every registered model, this list is what the mechanism that you are describing loops over.
YourModel._meta.get_all_related_objects_with_model()
This function loops over every field in every registered model and finds and returns any reverse relations to your YourModel.
The Options class from django.db.models.options (YourModel._meta is an Options object) is a good place to look around for this stuff.
Django doesn't "create" an ORM so the question makes no sense. If you want to know what properties the ORM adds to your model classes to support backward relationships then you can
open a django shell, import your models and inspect them
read the source code (hey, it's open source isn't it ?)
if that's not enough, add breakpoints at appropriate places and run the whole thing thru the debugger

Django (South): change model application

I have defined some models within an application, call it "blog".
djangoproject
/blog
models.py
I now want to change the models location, for example put them here:
djangoproject
/blog
xxx
/all_models
models.py
From the code point of view, this is pretty trivial, but the I guess there will be problems on the database since all the tables Django and South created are now called blog_posts blog_comments, Django relies on this naming convention and I don't want to lose the data already present in the database.
How to do this?
The easiest thing is not to bother changing the tables at all, but the code. Inside the Meta class of each of your models, put the declaration db_table = "blog_tablename", and Django will find them without problems.
You can solve this in two ways.
The first and easier one is to provide a db_table in Meta class of each of your models. The other is create a migration to apply the change.
As far as I know south doesn't support table rename, so you should do it as a three way migration:
Move de models, and create migration (now you have both tables old and new)
Create a data migration and iterate over the former table, copying objects to later
Remove the former model, and create a migration for it.
You can read a little bit more about the second way in south docs