Difference between models and Model in django - django

What exactly is the difference between models and Model.while writing a model in django.
from django.db import models
class Teacher(models.Model):

In your example, Model is the class from which you are inheriting, and models is where that Model class is located.

The models import is a folder, which implicitly runs the directory:
django/db/models/__init__.py
models.Model is a class found in the models folder within base.py. This is because __init__.py in the models folder imports base.py as well.

Related

How to register Django models that are only used in tests

I'm writing an app that has a custom model field. I want to test that field, using a model that is only used within tests, but I'm struggling to get the model working in tests.
Some of my app structure is like this:
myapp/
fields.py
models.py
tests/
fields/
models.py
tests.py
settings.py
test_models.py
test_views.py
tests/fields/models.py is like this:
from django.db import models
from myapp.fields import MyCustomField
class MyTestModel(models.Model):
custom_field = MyCustomField()
I then import MyTestModel and try to use it in tests/fields/tests.py.
Things I've tried...
1. Initially I got:
RuntimeError: Model class tests.fields.models.MyTestModel doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.
2. So I added "tests", to INSTALLED_APPS in tests/settings.py. But then I get:
django.db.utils.OperationalError: no such table: tests_mytestmodel
3. I've seen this in the docs about isolating model registration in tests. So I've tried moving the models into tests/fields/tests.py:
from django.db import models
from django.test import TestCase
from django.test.utils import isolate_apps
from myapp.fields import MyCustomField
#isolate_apps('tests')
class MyTestCase(TestCase):
def test_things_work(self):
class MyTestModel(models.Model):
custom_field = MyCustomField()
obj = MyTestModel.objects.create(custom_field='foo')
self.assertEqual(...)
But that still gets me:
django.db.utils.OperationalError: no such table: tests_mytestmodel
I've tried looking through the tests of lots of other Django projects that provide custom fields and can't see what I'm missing that (apparently) makes their tests with models work.
It sounds like, somehow, there need to be migrations for these models that are only used in the tests... is that right? How? Or something else?
Since your test app is in a nested folder you need to specify the whole path to it in INSTALLED_APPS instead of the parent folder, like:
INSTALLED_APPS = [
...,
"tests.fields"
]

Django Admin tables not displaying correctly

Has anyone seen this before? I've tried making new apps, projects, etc.
All thats in my admin.py file is:
from django.contrib import admin
from . models import UserProfile, Tribe, Membership
# Register your models here.
admin.site.register(Tribe)
admin.site.register(Membership)
admin.site.register(UserProfile)
I've not got any static files or css in the app..?
Create a class that inherit admin.ModelAdmin, update the fields to be shown in the list_display tuple, and register TribeAdmin instead of Tribe. Do the same for the rest.
from django.contrib import admin
from . models import UserProfile, Tribe, Membership
# Register your models here.
class TribeAdmin(admin.ModelAdmin):
list_display = ('field_1', 'field_2',)
admin.site.register(Tribe, TribeAdmin)
# admin.site.register(Membership)
# admin.site.register(UserProfile)
For all the available options, have a look at the documentation or an easy to understand beginner tutorial from the DjangoBook (please note its for an outdated Django Version, but fields works with Django 1.8)
With Django 1.8 you can use.
#admin.register(Tribe)
class TribeAdmin(admin.ModelAdmin):
list_display = ('field',)

Using abstract base class in django admin interface with neo4django

I'm trying to use a simple abstract base class in django's admin interface with neo4django.
Example models.py
from neo4django.db import models
class Parent(models.NodeModel):
name = models.StringProperty()
class Meta:
abstract = True
class Child(Parent):
pass
Example admin.py:
from neo4django import admin
from core.models import Child
class ChildAdmin(admin.ModelAdmin):
pass
admin.site.register(Child, ChildAdmin)
The 'name' field doesn't appear in the admin interface.
If I use the same basic structure, but with django.db instead of neo4django.db, it all works fine. Anyone spot where I've gone wrong?
Update from comments:
This has been tried with django 1.5.5 and 1.5.4
The neo4django version is from the github repo
Registering the model with or without a ModelAdmin have both been tried and made no difference
Have you tried just registering the model, without the ModelAdmin?

Django: How to create a model from a definition in another module

Lets say I have this Django setup:
appA - models.py
- views.py
- etc...
global - models.py
What I want is import the models from global.models in appA.models so that they are treated as a normal appA models by syncdb and south.
global.models:
from django.db import models
class Foo(models.Model):
#django model stuff
appA.models:
try 1:
from global.models import *
>>manage.py schemamigration appA --auto
>>does not see Foo
try 2:
from global.models import Foo
class Foo(Foo):
pass
>>manage.py schemamigration appA --auto
>>Error: One or more models did not validate:
>>appA.Foo: 'foo_ptr' has a relation with model <class 'global.models.Foo'>, which has either not been installed or is abstract.
What is the correct way to accomplish this?
from .models import Foo
class Foo(models.Model):
#stuff
class Meta:
abstract = True
global is a python statement, you should not use it to name one of your package. Try using a different name, and don't forget to put a __init__.py file in the directory to turn it into a python package.

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