Django Model/Manager Dependency - django

When using a Custom Model Manager the way it is shown in the documentation and examples that I have found, the Custom Managers are placed in the same source file as the Model.
My models.py file has a base class with four sub-classes and the base class has several static methods to provide some common queries. I will need to add quite a few custom queries. I would prefer to put these in a Custom Model Manager that is a Base class for each of the subclasses Model Managers. I would also like to be able to separate the Model Managers into a separate source file called managers.py to make the code less messy.
The problem is that there is a cyclic dependency between the Models and Managers.
Is there a way to set the Manager to the "objects" variable by name instead of the actual Model Manager class? Or perhaps some other way to be able to put the code into the two separate files?
models.py
class MyBaseModelClass(models.Model): (abstract)
list_of_values (Many to Many Field)
class class SubclassA(MyBaseModelClass):
objects = SubclassAManager()
# list_of_values pulled from external system
class class SubclassB(MyBaseModelClass):
objects = SubclassBManager()
# list_of_values manually added by the user in the UI and stored in the DB
class class SubclassC(MyBaseModelClass):
objects = SubclassCManager()
# list_of_values derived from subclass fields and not stored in the DB
class class SubclassD(MyBaseModelClass):
objects = SubclassDManager()
# list_of_values derived from subclass fields and not stored in the DB
managers.py
class MyCustomBaseManager(models.Manager):
# Does custom queries that do calculations and other data manipulations that are common to all of the
# Subclasses. Note that MyBaseModelClass can't have a Manager because it is Abstract.
class SubclassAManager(MyCustomBaseManager):
class SubclassBManager(MyCustomBaseManager):
class SubclassCManager(MyCustomBaseManager):
class SubclassDManager(MyCustomBaseManager):

Related

Why Abstract=True dosen't inherit in Meta class of django model

I we have this models in django:
class FotherModel(models.Model):
# Some fields goes here!
class Meta:
# Some fields goes here!
abstract = True
class ChildModel(FotherModel):
# Some fields goes here!
class Meta(FotherModel.Meta):
#s Some fields goes here!
When we inherit a field from the meta class of Django models, that field appears in child meta class, But this rule does not apply to abstract=True.
I know that if this happens, no table in database will be created, But I don't know how this inheritance didn't happen. Please explain this process for me.
The Model metaclass resets abstract in a model's Meta class. In this document you can see:
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.
Also, you can see the source code of this process in this link:
if abstract:
# Abstract base models can't be instantiated and don't appear in
# the list of models for an app. We do the final setup for them a
# little differently from normal models.
attr_meta.abstract = False
new_class.Meta = attr_meta
return new_class
Because of the concept and effect of some fields in meta section in many cases it doesn't make sense that the field is inherited by chidren.
It has been described here

Django - Selecting from multiple tables/models

I have a model set up that is
class BasePage(Page):
class Meta:
abstract = True
class PageTypeA(BasePage):
...
class PageTypeB(BasePage):
...
class PageTypeC(BasePage):
...
etc..
How do I create a query to list all of the pages that inherit from BasePage?
If i am understand you properly you need a parent model that have some generic information and other child models need some extra additional information. You can try third-party django-polymorphic link for that. One of important feature that it support Django-Rest-Framework serializer too.

Transient use of Django Model instances

I have a use case where a particular class can either be transient or persistent. Transient instances are build from a JSON payload on a PUT call, and may either be persisted to the database or used during the server call and then either returned or discarded. What is best practice for this case? My options seem to be:
Write two classes, one of which is a models.Model subclass, and the other of which isn't, and make them implement the same API, or
Use the Model subclass, but be careful not to call save().
Is either of these preferable, according to conventional use of Django models?
You'll need both:
abstract = True is useful if inheritants still should be concrete models, so that no table should be created just for the parent class. It allows you to opt out of multi-table inheritance, and instead have the shared attributes duplicated to inheritants tables instead (abstract base inheritance).
managed = False is useful if the inheriting class should never be persisted at all. Django migrations and fixtures won't generate any database table for this.
class TransientModel(models.Model):
"""Inherit from this class to use django constructors and serialization but no database management"""
def save(*args, **kwargs):
pass # avoid exceptions if called
class Meta:
abstract = True # no table for this class
managed = False # no database management
class Brutto(TransientModel):
"""This is not persisted. No table app_brutto"""
#do more things here
pass
In order to remain as DRY as possible, you could have an abstract mock class deriving your model:
class A(models.Model):
# fields'n'stuff
class TransientA(A):
def save(*args, **kwargs):
pass # avoid exceptions if called
class Meta:
abstract = True # no table created
Now, even if you call save on it anywhere (even in methods inherited from A), you'll be shooting blanks.

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: multiple table inheritance doesnt allow me to access derived class from base class

I want to get a derived modelclass instance from an instanciated base modelclass.
I have the following model class hierarchy:
class AlfrescoPFCModel(models.Model):
#some fields and methods
class Meta:
abstract = True
class Contenido(AlfrescoPFCModel):
#some fields and methods
class Proyecto(Contenido):
#some fields and methods
class ProyectoCalificado(Proyecto):
#some fields and methods
class ProyectoArchivado(ProyectoCalificado):
#some fields and methods
And I instantiate a Proyecto class in this way:
proyecto = proyecto_form.save(commit=False)
#do some stuff with some fields that dont appear on the form
proyecto.save
In another view I try to access the derived class ProyectoCalificado from the base class Proyecto previously instanciated and saved in the database doing:
pc = ProyectoCalificado.objects.get(pk=id)
and i get: ProyectoCalificado matching query does not exist.
I also tried:
p = get_object_or_404(Proyecto, id=id)
pc = p.proyectocalificado
but it get the same error in the second line.
Reading the documentation i should be allowed to do that:
#multi-table-inheritance
What i want to do is to incrementally complete the data associated to a Proyecto (project) following this workflow: Proyecto -> ProyectoCalificado -> ProyectoArchivado.
I have 3 different forms for each step. I need 3 different models because I need to save them in the database without filling all the mandatory fields at once.
Thanks!
Use Form Wizards (https://docs.djangoproject.com/en/dev/ref/contrib/formtools/form-wizard/).
UPDATE
If you can't use Form Wizards because of the situation you describe, then you should make the models fields blank or nullable at the database level and then only enforce field requirements on each individual form. Creating three levels of inheritance solely for the purpose of the single-time set of forms required to create it is absolutely the wrong approach. It only fragments your data across additional tables and makes querying more complicated with no long-term benefit.
So, for example. Set the model itself up as though nothing (or only the items in the first form) are required. Then, in your first form, only make the fields necessary for that particular stage required. You can do this easily by overriding the __init__:
class FirstForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(FirstForm, self).__init__(*args, **kwargs)
self.fields['some_required_field'].required = True
# rinse and repeat
Do the same in your second and third forms, again making on the actual fields that are required for that particular form, required.
Then, call it day and have a drink.
If you have the child instance, it should have a <base class name>_ptr member which points to the instance of its superclass. You can use this as the basis of a filter query to retrieve the child.
You can also just assume that instances of the base and derived class will have the same id if you haven't done anything to affect how ids are allocated.