Django model reference when using AbstractBaseUser model - django

I 'm following a tutorial of how to use AbstractBaseUser model in Django project. Now I would like to go one step further by creating other models for example address_book and product.
When using defaulter user model, we put like this:
class User(models.Model):
....
class AddressBook(models.Model):
....
class Product(models.Model):
....
Now when I use like
class MyUser(AbstractBaseUser):
Which reference should I use in the AddressBook and Product class? (The user in the Address book is a foreign key from Class MyUser).
class AddressBook(AbstractBaseUser) and class Product(AbstractBaseUser) or
class AddressBook(models.Model) and class Product (models.model)?
Thanks for your help in advance!

In Python if you define a class like that
class ClassName(SuperClassName):
...
You are extending one or more existing classes. This is inheritance, not a reference.
If you want a reference you might want something like this:
class AddressBook(models.Model):
user = models.ForeignKey('MyUser', on_delete=models.CASCADE)
...
For more detailed information I recommend looking at this page in the documentation.

Related

Django inheriting from multiple model classes

So I have a base abstract model class
class AbstractBase(models.Model):
category = models.CharField()
// Some fields
class Meta:
abstract = True
Now many classes inherit from this Base. Each category has its own fields
class Category1(AbstractBase):
//some code
class Category2(AbstractBase):
//some code
.
.
.
class CategoryN(AbstractBase):
//some code
Now I do not wish to create separate inlines etc for each of these models.
This is because in the admin only one of these models need to be displayed depending on which category it is.
class CategoryAdminInLine(nested.NestedTabularInline):
model = Category
fields = //some common fields
Is there any easy way to do it?
Try the package django-polymorphic https://github.com/django-polymorphic/django-polymorphic
It adds transparent admin and QuerySet integration for inherited models.
Another solution is to simply remove the abstract=True from the base class.
However, I'm afraid this may not be the right way to do it as it may be copying and duplicating the tables and stuff but works great if the tables won't get too big!..
According to how it's done here.. https://godjango.com/blog/django-abstract-base-class-multi-table-inheritance/

Django: add index to meta field

I have the following model:
from model_utils.models import TimeStampedModel
class MyModel(TimeStampedModel):
....
name = models.CharField(max_length=100)
....
This model is based on Django Utils (https://django-model-utils.readthedocs.org/en/latest/models.html#timestampedmodel) which adds created and modified fields to my model.
What I need know is way to add a db_index to the modified field of my model. But I can't modify the TimeStampedModel file because it is part of an external dependency.
Do you know any easy solution for this kind of issue?
Thank you.
Yes you can using model Meta.
if you don't need to inherit meta from the TimeStampedModel just use this:
class Meta:
...
otherwise you need to explicitly tell django to look into the parent's meta first like this:
class Meta(TimeStampedModel.Meta):
this might be a hackish solution but maybe you can try using index_together to make django create an index for your model:
like this:
class Meta(TimeStampedModel.Meta):
index_together = [
["modified",],
]
try it out and tell me if it worked
EDIT:
Another solution coming from: How to override the default value of a Model Field from an Abstract Base Class:
try adding this to your MyModel class
MyModel._meta.get_field('modified').db_index = True

Choosing the right user inheritance method for django 1.5

I have a situation where I need to subclass a custom user model for a django 1.5 project (related question/background here: Subclassing AbstractUser in Django for two types of users )
I need an abstract user class SchoolPerson and a number of subclasses (Student, Teacher, etc) based on this. I think I've resolved that I need to have the user model in a separate DB table to the subclasses as other apps rely on AUTH_USER_MODEL, of which there can only be one.
So the way I see it, I have to options to do this: add one-to-one to the standard user model in my abstract SchoolPerson class:
class SchoolPerson(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
...
class Meta:
abstract = True
class Student(SchoolPerson):
year_level = models.CharField(max_length=3)
...
class Teacher(SchoolPerson):
govt_id = models.CharField(max_length=10)
...
Or I can make my SchoolPerson model inherit AbstractUser, but keep this class non-abstract:
class SchoolPerson(AbstractUser):
...
#no Meta abstract here
class Student(SchoolPerson):
year_level = models.CharField(max_length=3)
...
class Teacher(SchoolPerson):
govt_id = models.CharField(max_length=10)
...
Are there any advantages to one of these over the other?
I haven't tested this but what I expect is for your first suggestion to create two db tables:
one for Student and one for Teacher each with a foreign key to the AUTH_USER_MODEL.
For the second one I expect Django to create three db tables:
One for the SchoolPerson(which will be exact as the default Users table with the additional fields) and two for Student and Teacher with foreign keys to SchoolPerson.
So I think the answer depends on your requirements.

Can I make a model know about its ModelForm?

I have a standard Model and ModelForm set-up. I want to be able to return the ModelForm object from my Model. This involves an impossible circular reference. I thought that since Django allows foreign key models to be expressed as strings, perhaps it's possible to do something similar. At the moment I'm doing this:
class Thing(models.Model):
stuff = models.TextField()
def get_form(self):
return getattr(sys.modules[__name__], "ThingForm")(self)
class ThingForm(ModelForm):
class Meta:
model = Thing
It works. But I feel that in doing this I bring shame upon myself and my family. There must be a more honourable way.
By the way, I want do to this because I'm using ContentTypes to create generic foreign keys, so my view code doesn't know what class the model is in the static context.
That's... not an impossible circular reference. Names are only looked up when the code that references them is run.
class Thing(models.Model):
stuff = models.TextField()
def get_form(self):
return ThingForm(self)
class ThingForm(ModelForm):
class Meta:
model = Thing

Django - how to determine if model class is abstract

If a django model is made abstract, like below, is there a way to inspect the class to determine that it is abstract?
class MyModel(models.Model):
class Meta:
abstract = True
I would expect that I could examine MyModel.Meta.abstract, but according to Django docs:
Django does make one adjustment to the Meta class of an abstract base class: before installing the Meta attribute, it sets abstract=False. This means that children of abstract base classes don't automatically become abstract classes themselves.
Any ideas? Thanks!
You can instantiate MyModel and then check ._meta.abstract.
So in code:
m = MyModel()
print m._meta.abstract
I'd like to point out that you don't need to instantiate a model to check if it's abstract - Django models inherit an actual metaclass that adds _meta on class instantiation.
So, similarly to #sheats's code, try
from django.db.models import Model
class MyModel(Model):
pass
print MyModel._meta.abstract
Or, for a positive example
from django.db.models import Model
class MyModel(Model):
class Meta(object):
abstract = True
print MyModel._meta.abstract
Of course, this also works for built-in models and anything inheriting from Django's Model.
from django.contrib.auth.models import User
print User._meta.abstract