Use two managers in one model - django

I have a Place model with subclasses Restaurant and Bar. I attached InheritanceManager from django-model-utils to Place to use the select_subclasses() method to get instances of the subclass.
from model_utils.managers import InheritanceManager
class Place(models.Model):
# ...
objects = InheritanceManager()
class Restaurant(Place):
# ...
class Bar(Place):
# ...
Everything worked fine. But now I want to set the order of the model Place with django-ordered-model. This package also uses a manager:
...
objects = OrderedModelManager()
...
How to combine them?

Related

Different serializers for different objects in a single queryset

For a ForeignKey relationship, how can I change the serializer used based off some criteria?
# models.py
class Relationship(models.Model):
...
class Item(models.Model):
relationships = ForeignKey(Relationship)
class OddPKSerializer(serializers.Serializer):
...
class EvenPKSerializer(serializers.Serializer):
...
class ItemSerializer(serializer.Serializer):
# relationships = OddPKSerializer and/or EvenPKSerializer(many=True)
# depending on some criteria
class Meta:
model = Item
fields = ["relationships"]
# Where for example, OddPKSerializer is used if
# the specific relationship object has an odd pk
# and EvenPKSerializer is used for even pks
In my actual use case, I'm looking to serialize differently based on the ForeignKey object's class. (I'm using proxy models so a single ForeignKey field can point to different classes.)
I've tried using SerializerMethodField but that only seems to act on the "Item" object and not the "Relationship" objects that I'm looking to serialize.
This works:
class OddPKSerializer(serializers.Serializer):
...
class EvenPKSerializer(serializers.Serializer):
...
class SwitchSerializer():
item = serializers.SerializerMethodField()
def get_item(self, obj):
if obj.pk/2 == 0:
return EvenPKSerializer(obj).data
return OddPKSerializer(obj).data
class ItemSerializer():
item = SwitchSerializer(many=True)

Django models.py

I created an App called order whose models.py (model name create_order) contain fields like order_created_by, cloth_type, clothe colour, size, delivery_date, order_created_date. Now in models.py of warehouse app, I want to see all the field of created_order model. How can I do that? And can do this all using first importing models in views.py of warehouse and the creating function then returning the HttpResponse using models.objects.all(). But I want to see these all fields of create_order in admin.py of warehouse app.
To achieve this you can use Django Model inheritance. For example, in your orders/models.py file you can create an Abstract model that will contain all the common fields. But to make your project clean and structured its a nice idea to create another app with the name of core or utils (most common name in the Django community) and put all common files there.
class CommonFieldModel(models.Model):
order_created_by = ...
cloth_type = ...
clothe = ...
colour = ...
size = ...
delivery_date = ...
order_created_date = ...
class Meta:
abstract = True
# order/models.py
class YourOrderAppModel(CommonFieldModel):
# Will contain all CommonField Model fields + all other field you define here.
...
# warehouse/models.py
class YourWareHouseModel(CommonFieldModel):
# this model will contain all CommonField model fields
# You can also define other fields here.
...
By default abstract is False.

How to always prefetch_related for a specific django model

One of my models has number of related objects in it's __str__. This makes the admin site run very slow.
Is it possible to set up the model in a way that would always do prefetch_related, even if not explicitly requested?
You can implement a manager [Django-doc] that will automatically add a .prefetch_related(..) to the queryset.
For example:
class MyModelManager(models.Manager):
def get_queryset(self):
return super().get_queryset().prefetch_related('related_model')
class MyModel(models.Model):
# …
_base_manager = MyModelManager()
objects = MyModelManager()
Adding as an answer since I cannot add a comment (this answer):
The _base_manager attribute needs to be a class and not an object.
class MyModel(models.Model):
# …
_base_manager = MyModelManager
objects = MyModelManager()

django models to model 'has-a' and 'contains' relationships

I have the following entities:
from django.db import models
class Foo(models.Model):
pass
class Bar(models.Model):
pass
class FooBar(models.Model):
pwned_foo = # Foobar contains one Foo object
bars = # Collection of Bar objects
How do I express the relation between Foo, Bar and FooBar in the FooBar class?
I think you want a OneToOneField and a ForeignKey like this:
from django.db import models
class Foo(models.Model):
pass
class Bar(models.Model):
foobar = models.ForeignKey(FooBar, related_name='bars')
class FooBar(models.Model):
pwned_foo = models.OneToOneField(Foo)
bars = # Collection of Bar objects
# you can access bars via the reverse relationship like
# myfoobar.bars
This assumes you want a 1-N relation with bars. If you want an N-N relation, then use a ManyToManyField.
If you really need to keep Bar clean of any relationship (can you explain why?) you could try something like ArrayField with the caveats that this only works on postgresql, and you would need to reimplement relationships in querysets, etc... And I suspect performance would suffer too...
from django.db import models
class Foo(models.Model):
pass
class Bar(models.Model):
pass
class FooBar(models.Model):
pwned_foo = models.OneToOneField(Foo, on_delete=models.CASCADE)
bars = models.ForeignKey(Bar, on_delete=models.CASCADE)

Find all instances of child models matching query

I have base class Publication, which Book and Magazine inherit from.
class Author(models.Model):
pass
class Publication(models.Model):
author = models.ForeignKey(Author)
class Book(Publication):
pass
class Magazine(Publication):
pass
I want to find all Book and Magazine objects with a certain author. Since the foreign key to Author is on the parent class Publication, my attempts at a query all return Publication objects rather than the child classes:
# Both of these return Publication objects, not Book/Magazine objects
Author.objects.get(pk=1).publication_set
Publication.objects.get(author_pk=1)
Is there a way to get all instances of child classes with a certain author, without manually running the query for all child classes like Book.objects.get(author_pk=1) (in reality I have more than two child classes)?
You might need to use an external package to get this kind of functionality. This looks like what you need: https://django-model-utils.readthedocs.io/en/latest/managers.html#inheritancemanager
Specifically:
from model_utils.managers import InheritanceManager
class Place(models.Model):
# ...
objects = InheritanceManager()
class Restaurant(Place):
# ...
class Bar(Place):
# ...
nearby_places = Place.objects.filter(location='here').select_subclasses()
for place in nearby_places:
# "place" will automatically be an instance of Place, Restaurant, or Bar