django query multiple tables with foreign key pointing on self - sql

lets say I have a model named User, and other models representing actions done by the a user, like "User_clicked", "User_left", "User_ate_cookie" etc. etc.
the User_* models have different fields and inherit from a single abstract class (User_do_something)
my question is this:
what's the django-way of querying ALL the models, from all the relevant tables, that point on a specific user?
eg. I want to do User.get_all_actions() and get a list with mixed type of models in them, containing all the objects that inherit from User_do_something and point on the specific user.
Note: performance is critical. I don't want to make multiple db queries and combine the list, if possible, I want to do it with a single sql select.
some code to be clear:
class User(models.Model):
uuid = models.UUIDField(unique=True, default=uuid.uuid4)
creation_time = models.DateTimeField(auto_now_add=True)
def get_all_actions(self):
'''
return a list with ALL the actions this player did.
'''
??????? how do I do this query ???????
class User_do_action(models.Model):
user = models.ForeignKey(User)
creation_time = models.DateTimeField(auto_now_add=True)
class Meta:
abstract = True
class User_click(User_do_action):
... some fields
class User_left(User_do_action):
... some fields
class User_ate_cookie(User_do_action):
... some fields
etc. etc.
thanks!

Related

multiple models required for serialisation, django

I am having a very specific issue here, and am not sure how to navigate through it. So, I have a couple of serializers here, the code to which is attached below. Starting with three models, Cluster, Family and Individual, where a Cluster is a group of families, a Family is a group of individuals and an Individual is the lowest information holder.
With the help of through models(foreign keys between two models), I need to serialize and output families with their individuals containing integer fields representing a certain order defined by the through relations. As you can see, I have to use bots, Individual and Family as arguments in the returns_order function, and that's creating problems. Is there a better way that I am not aware of?
class IndividualSerializer(serializers.ModelSerializer):
order = serializers.SerializerMethodField('returns_order')
def returns_order(self, Individual, Family):
through = IndividualThroughFamily.objects.get(family=Family.id, topics=Topic.id)
order = through.order
return order
class Meta:
model = Individual
fields = ['order', 'individualName']
class FamilySerializer(serializers.ModelSerializer):
order = serializers.SerializerMethodField('returns_order')
def returns_order(self, Family):
through = FamilyThroughCluster.objects.get(family=Family.id)
order = through.order
return order
relatedIndividuals = IndividualSerializer(many=True)
class Meta:
model = Family
fields = ['order', 'familyName', 'relatedIndividuals']

What is the best way to get all linked instances of a models in Django?

I am trying to create a messaging system in Django, and I came across an issue: How could I efficiently find all messages linked in a thread?
Let's imagine I have two models:
class Conversation(models.Model):
sender = models.ForeignKey(User)
receiver = models.ForeignKey(User)
first_message = models.OneToOneField(Message)
last_message = models.OneToOneField(Message)
class Message(models.Model):
previous = models.OneToOneField(Message)
content = models.TextField()
(code not tested, I'm sure it wouldn't work as is)
Since it is designed as a simple linked list, is it the only way to traverse it recursively?
Should I try to just get the previous of the previous until I find the first, or is there a way to query all of them more efficiently?
I use Rest Framework serializer with depth. So If you have serializer with Depth value to 3. I will fetch the full model of whatever the foreign key available until three parents.
https://www.django-rest-framework.org/api-guide/serializers/#specifying-nested-serialization
class AppliedSerializer(serializers.ModelSerializer):
class Meta:
model = Applied
fields = ("__all__")
depth = 3

How to Annotate Specific Related Field Value

I am attempting to optimize some code. I have model with many related models, and I want to annotate and filter by the value of a field of a specific type of these related models, as they are designed to be generic. I can find all instances of the type of related model I want, or all of the models related to the parent, but not the related model of the specific type related to the parent. Can anyone advise?
I initially tried
parents = parent.objects.all()
parents.annotate(field_value=Subquery(related_model.objects.get(
field__type='specific',
parent_id=OuterRef('id'),
).value)))
But get the error This queryset contains a reference to an outer query and may only be used in a subquery. When I tried
parents = parent.objects.all()
parents.annotate(field_value=Q(related_model.objects.get(
field__type='specific',
parent_id=F('id'),
).value)))
I get DoesNotExist: related_field matching query does not exist. which seems closer but still does not work.
Model structure:
class parent(models.Model):
id = models.IntegerField(null=False, primary_key=True)
class field(models.Model):
id = models.IntegerField(null=False, primary_key=True)
type = models.CharField(max_length=60)
class related_model(models.Model):
parent = models.ForeignKey(parent, on_delete=models.CASCADE, related_name='related_models')
field = models.ForeignKey(field, on_delete=models.CASCADE, related_name='fields')
Is what I want to do even possible?
Never mind I decided to do a reverse lookup, kinda like
parent_ids = related_model.objects.filter(field__type='specific', parent_id__in=list_of_parents).values_list('parent_id')
parents.objects.filter(id__in=parents_id)

How should I model a schema in which models can be related to entities of different types in Django

Schema Option 1: https://gist.github.com/guyjacks/6ec4c1b0fa41b3f666f5c6adf2dfaf89
Schema Option 2: https://gist.github.com/guyjacks/4838cd76b2f924629d2a3f2ba316a504
I guess this is really two questions:
Which schema is recommended from a relational db perspective?
Is there an idiomatic way to model either schema in Django?
Cheers!
One way to do this would be to use Generic Relations:
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
And in the model you want to relate to various models:
class SomeModel(models.Model):
...
# Below the mandatory fields for generic relation
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey()
And in the models you want related:
from django.contrib.contenttypes.fields import GenericRelation
class SomeOtherModel(models.Model):
...
# The relation
your_field = GenericRelation(SomeModel)
If you want to be able to use reverse queries see this from the docs:
related_query_name
The relation on the related object back to this object doesn’t exist
by default. Setting related_query_name creates a relation from the
related object back to this one. This allows querying and filtering
from the related object.
You should be careful when using them as they can quickly add complexity.
Links for more info:
https://docs.djangoproject.com/en/1.11/ref/contrib/contenttypes/#generic-relations
https://simpleisbetterthancomplex.com/tutorial/2016/10/13/how-to-use-generic-relations.html

How to code a superclass field that accepts multiple subclasses?

I want to have a superclass that will be inherited by subclasses.
Let's say I want the superclass mother to be inherited by child.a and child.b.
So I make these classes
mother:
class mother(osv.osv):
_name = "mother"
mother()
child.a:
class child_a(osv.osv):
_name = "child.a"
_inherit = "mother"
child_a()
child.b:
class child_b(osv.osv):
_name = "child.b"
_inherit = "mother"
child_b()
now let's say I have a class a that have a many2one connection to mother
class a(osv.osv):
_name = "a"
_columns = {
'mother' : fields.many2one('mother', 'Mother'),
}
a()
Does mother field accept both class child.a and child.b. If yes how to code the create and write methods. If not how do I achieve this in any other way? (field accepting multiple subclasses)
No, a many2one referencing mother can't address records of class.aor class.b.
The inheritance method used for class.a and class.b actually copies the mother features. They create two new independent tables, copy of mother, containing independent data sets.
This means that the classes are not interchangeable in any way.
Records in child.a are not present in motherand vice-versa.
What you describe can be achieved with delegation inheritance - you can think that as class.x having a mother class "embedded" in it, through a special many2one relation.
This way, when you create a new class.x record, a new mother record is also implicitly created.
But this works one way: creating a new mother record does not create a class.x record.
An example of delegation inheritance in the core modules is res.users: a User "embeds" a Partner. When a new user is created, a new Partner is also created for it.
Many2one relations to Partners will also be able to reference the User embedded Partners. But many2one relations to Users will not be able to reference Partners that are not Users.