Django - model in multiple apps (multiple tables) - django

I am trying to import a model from one app into another creating a new table etc.
# app1/models.py
class MyModel(models.Model):
myfield = models.CharField(...)
...
# app2/models/__init__.py
from app1.models import MyModel as MyShadowModel
What I would expect: python manage.py makemigrations would see changes in app2 and create the according tables.
Why does it not happen?
What would I have to do to achieve this?
Background
A Django project shall process Data and make changes visible. It consists of two apps:
app1 contains already processed data
app2 processes changes and shall show what data in app1 would look like.
The idea: app2 processes the data into a "shadow" model. Therefore i would like to use the exact same model as app1 in my models in app2

Importing the model doesn't suffice. Imagine you only have to do some logic with MyModel in app2's models.py. It doesn't make sense to create another table.
You have to declare another model that inherits from the parent model in order to replicate it.
from app1.models import MyModel
class MyShadowModel(MyModel):
...

Related

programatically accessing Django models from another app

I have a moderately complicated Django project with a variety of different apps (app1, app2 etc), each with their own models. I am building a MetaApp app to track info about each app, with a MetaApp class in models.py, and fields such as appname and modelname
MetaApp drives an index view that summarizes various aspects of each project. I would like to include a count of the database records for each app. This means that I need to programmatically access models from other apps. If I I know the appname and modelname, how do I programmatically access these models?
projects = MetaApp.objects.all()
projects[0].appname[0].modelname.ojects.all()
This code results in an attribute error, because I am storing the appname and modelname as unicode strings. What is the workaround?
Use the django.db.models.loading.get_model() function:
from django.db.models.loading import get_model
model = get_model(app_name, model_name)
object_list = model.objects.all()

How to separate models in different modules in Django admin's index?

I would like to separate my app's models in the admin index:
I registered all my models in admin.py and I get all of them in the default admin index under the big red 1 shown below.
Now I'd like to have some of my models in another "block", as shown below under the big red 2.
To make it harder, I also need to have some models in both "blocks", but with different queryset.
How can I do that?
I tested my solution and it works.
Do this:
class MyModelTest(models.Model):
# Fields here
class Meta:
app_label = 'My other app namespace'
UPDATE:
To achieve your goal (max flexibility) , you will need to modify the template admin/app_index.html and the view django.contrib.admin.sites.app_index to your own needs.

Already Registered at /admin/ Django 1.2 error

I'm experiencing this error in Django 1.2 admin.
Scenario:
I have two applications, say app1 and app2 inside my project.
In both of these apps, I defined their respective admin.py files to hook each apps respective models to django's admin site.
Inside app1 admin.py, I defined three ModelAdmin classes corresponding to three models class in app1 and registered two of them to the admin site.
class App11stModelAdmin (admin.ModelAdmin):
#class definitions here
#This class is an abstract class
#class Meta:
# abstract = True
class App12ndModelAdmin (admin.ModelAdmin):
#class definitions here
class App13rdModelAdmin (admin.ModelAdmin):
#class definitions here
#register to admin site two of them
admin.site.register(App12ndModel, App12ndModelAdmin)
admin.site.register(App13rdModel, App13rdModelAdmin)
Inside app2, I imported app1.App11stModelAdmin to define the admin model of an app2 model.
inside admin.py of app2:
from app1.admin import App11stModelAdmin
class App21stModelAdmin(App11stModelAdmin):
#define some things here
#register App21stModelAdmin to admin site
admin.site.register(App21stModel, App21stModelAdmin)
With this code, I am getting this error message:
AlreadyRegistered at /admin/
The model App12ndModel is already registered
Request Method: GET
Request URL: http://127.0.0.1:8000/admin/
Django Version: 1.2
Exception Type: AlreadyRegistered
Exception Value:
The model App12ndModel is already registered
This strange because I'm sure I'm only registering that model's admin once. When I commented out the register statement for that model, I got the same error, but now for App13rdModel model.
In the meantime, to fix this issue, I removed the registration statements and instead put them inside a 'static' function inside app1 admin.py.
like:
inside app1 admin.py
def register():
admin.site.register(App12ndModel, App12ndModelAdmin)
admin.site.register(App13rdModel, App13rdModelAdmin)
and then in app2 admin.py
I included the register function in the import:
from app1.model import App11stModelAdmin, register
......
......
#register the two admin model in app1 inside app2 admin.py by calling the register function
register()
And this works. I am not getting the Already Registered error anymore.
Question:
What did I do which resulted to that error? I am new to Django and Python.
Thank you very much!
admin.py files are executed by Django during runtime so if you import an admin.py script into another script, you are actually executing the exposed admin.site.register functions again, which thus gives you the Already Registered error.
This is in fact standard Python behavior. Consider the following script (save as sample.py):
def multiplier(x,y):
return x*y
def sample_write(text):
out = open("out.txt","w")
out.write(text)
out.close()
sample_write("hey") # Notice this executed function
When you open your Python interpreter in the same directory and do import sample it will write the out.txt output. The same case when you selectively import the multiplier function like from sample import multiplier, the output file is still written. The only way to avoid the output file being written is to comment out the executed function in the script or wrap it into another function.
The only thing that can cause this is if your admin.py is being imported in two different ways. For example, the following is seen as two different modules and will actually cause the admin.py code to be ran twice:
from foo.admin import FooAdmin
from myproject.foo.admin import FooAdmin

How can i create django models , views , forms with different names

Currently i have my models, views, forms in default file.
But i want to have directory structure like
articles
---------models
---------views
---------forms
Books
---------models
---------views
---------forms
Icecreams
---------models
---------views
---------forms
so that i keep separately but i don't want different app
The directory structure you describe is the individual apps directory structure. If you want it to look like that, you have to make them separate apps. However, you can do something like:
myapp/
__init__.py
models/
__init__.py
articles.py
books.py
icecream.py
Simply add a models directory and delete models.py. Then, create a separate .py file for each model/group of models you want to separate.
Here's the important part: on each of your models you must add the following to their Meta class:
class MyModel(models.Model):
...
class Meta:
...
app_label = 'myapp'
Where 'myapp', is the main app folder all these models are stored in.
Then, edit models/__init__.py and import all your models there, e.g.:
from .articles import Article
from .books import Book
from .icecream import IceCream
However, the models you list as examples are pretty obvious candidates for distinct apps. The approach above is really only for related models. If your models are truly that distinct, they should be individual apps.
... i don't want different app
But they are different apps, and so should be divided that way.

Model in sub-directory via app_label?

In order to place my models in sub-folders I tried to use the app_label Meta field as described here.
My directory structure looks like this:
project
apps
foo
models
__init__.py
bar_model.py
In bar_model.py I define my Model like this:
from django.db import models
class SomeModel(models.Model):
field = models.TextField()
class Meta:
app_label = "foo"
I can successfully import the model like so:
from apps.foo.models.bar_model import SomeModel
However, running:
./manage.py syncdb
does not create the table for the model. In verbose mode I do see, however, that the app "foo" is properly recognized (it's in INSTALLED_APPS in settings.py). Moving the model to models.py under foo does work.
Is there some specific convention not documented with app_label or with the whole mechanism that prevents this model structure from being recognized by syncdb?
See Django ticket #10985: Explain how models can be organised in a directory
It may be that you aren't importing your models into __init__.py?
syncdb will not create tables for models not located in <appname>.models, so import it in there, e.g. from apps.foo.models import SomeModel.
Here is a solution if you have a newer version of Django, supposing you have a subfolder named subfolder :
in apps.py of your folder app:
from django.apps import AppConfig
class MyappConfig(AppConfig):
name = 'myapp'
def ready(self):
from myapp.subfolder import models