Django: Creating a model instance when duplicate model names exist - django

In one of my views I am importing models from two apps:
from mysite.business.models import Location
from mysite.directory.models import Location
As you can see, both Models have the same name. If I want to create an instance of one of these models, how do I define which one I require?

Give them different names.
from mysite.business.models import Location as BusinessLocation
from mysite.directory.models import Location as DirectoryLocation

Related

Creating a custom import statement which accepts variables, used to import django models

I'm creating a simple script used to generate fixture data for a given django model. I cannot figure out how to create an import statement which accepts user input, to allow me to perform the actual logic on the selected model.
I've tried various combinations of imp, importlib.util.spec_from_file_location,
importlib.import_module,
__import__,
Create an import statement using variable "interpolation"
The closest I've gotten is:
def import_function(app, model):
exec(f"from {app}.models import {model}")
exec(f"print({model}.objects.all())") #This works.
import_function("home", "Person")
My thinking is: I create a module called 'fixture.py'. Within that module is a custom import function. I import the module into the environment created by
python manage.py shell so as to obviate the need for modifying the PATH.
Then, I call the function using fixture.import_function(app, model).
I've managed to generate the fixture data this way, but only when I'm hardcoding the import statement, i.e. from home.models import Person.
#fixture generating logic.
This is the wrong approach. There's no need to fiddle with imports or construct names dynamically. Use the functions that Django provides to find the model:
from django.apps import apps
model = apps.get_model(app, model)
print(model.objects.all())

How do I check if a Model name exists in Django?

What Django command(s) must I use to check if model SomeModelName exists?
Django has an django.apps module with an apps class:
from django.apps import apps
this apps class has a get_models() function, that returns the Model classes (these do not include abstract models, and tables as a result of ManyToManyFields).
We can use .__name__ to obtain the classname. So we can check if SomeModelName exists with:
from operator import attrgetter
'SomeModelName' in map(attrgetter('__name__'), apps.get_models())
Note that this will specify the name of the classes, and that in the different applications you have registered, several models can have the same name (but these are not the same model).

How can I add inlines to the ModelAdmin of another app, without a circular dependency?

Let's say I have two models, in different apps. App Two knows about app One, but not the other way around:
# one/models.py
from django.db import models
class One(models.Model):
pass
# two/models.py
from django.db import models
from one.models import One
class Two(models.Model):
one = models.ForeignKey(One)
I also have One registered in the admin site:
# one/admin.py
from django.contrib import admin
from .models import One
admin.site.register(One)
How do I register Two as an Inline on One's admin page, without introducing a circular dependency between the two apps?
You can do this pretty simply, providing you don't mind accessing a 'private' attribute on the ModelAdmin. (Attributes beginning with an underscore are treated as private by convention.)
# two/admin.py
from django.contrib import admin
from one.models import One
from .models import Two
class TwoInline(admin.StackedInline):
model = Two
admin.site._registry[One].inlines.append(TwoInline)
I had the same issue but solved it more gentle way.
# one/admin.py
class OneAdmin(admin.ModelAdmin):
model = One
admin.site.register(One, OneAdmin)
# two/admin.py
class TwoInline(admin.TabularInline):
model = Two
import one.admin
class OneAdmin(one.admin.OneAdmin):
inlines = [TwoInline]
admin.site.unregister(One)
admin.site.register(One, OneAdmin)
As you see I extended the original ModelAdmin from first app and added inlines from second app. Don't forget to unregister the model from first app before registering it again.
It's safe and much better than to access private member of the class as was suggested.
I would try the following:
# one/admin.py
from django.contrib import admin
from one.models import One
from two.models import Two
class TwoInline(admin.StackedInline):
model = Two
class OneAdmin(admin.ModelAdmin):
inlines = [TwoInline,]
admin.site.register(One, OneAdmin)
You can read more at the docs.

having models directory and AUTH_USER_MODEL

I have myApp/models/profiles.py instead of myApp/models.py (to group related models)
How do you set AUTH_USER_MODEL in this case?
Because auth accepts only "foo.bar" pattern.
app_label, model_name = settings.AUTH_USER_MODEL.split('.')
Django expects the models for any given app to be in app.models. If you want to use this kind of file structure, you'll need to still make sure this is the case. The easiest way to do this is too add from profiles import * in myApp/models/__init__.py and then use AUTH_USER_MODEL as normal.
For example, you you had myApp/models/profiles.py and myApp/models/actions.py your myApp/models/__init__.py should read
from profiles import *
from actions import *
Remember to make sure you don't have any name conflicts too, and you may wish to use set your __all__ value in each of your sub-packages.
You can either pass the class directly or the 'app.model'. django only registers classes defined in app.models module, so you'll need to import the class in models init. Since you'll be importing the model in init anyway, you don't need to specify the full path to the class in the foreignkey.

Django / Automatically retrieve models names

I'd like to retrieve automatically, in a loop, the names of the models located in a specific Django app inside my project. Does someone know how to do that ?
Best Regards
Guillaume
from django.db import get_models, get_app
app = get_app('myappname')
models = get_models(app)