Is there any way to call parent model from base model. my model.py looks like:
models.py
Class A(models.Model):
title = models.CharField(max_length=350)
description = models.TextField()
Class B(models.Model):
reftitle = models.CharField(max_length=100)
inventory = models.IntegerField()
Class C(models.Model):
a = models.ForeignKey('A')
b = models.ForeignKey('B')
notes = models.TextField()
for some reasons I can only retrieve data from Class A is there any possible way I can retrieve Class C by reference to Class A.
To get all C from given A:
a = A()
list_of_c = a.c_set.all()
and get A from given C:
c = C()
a = c.a
The reference has an own section about Many-to-one-relationships.
Related
class A(models.Model):
name = models.CharField()
class B(models.Model):
name = models.CharField()
class C(models.Model):
name = models.CharField()
class D(models.Model):
a = models.ForeignKey(A, related_name='set_of_a')
b = models.ForeignKey(B, related_name='set_of_d')
set_of_c = models.ManyToManyField(C, related_name='set_of_d')
I want to get a queryset that should replace the following function (may be pseudocode in some places):
def get_queryset(name, list_of_c):
result = list(A.objects.filter(name__icontains=name))
for a in result:
a.map_b_to_list_of_d = {} # annotation
for b in B.objects.filter(set_of_d__set_of_c__intersects_with=list_of_d):
a.map_b_to_list_of_d.setdefault(c, []) += list(b.set_of_d.filter(a__name__icontains=name, set_of_c__intersects_with=list_of_c))
return result
I have four models as follows:
class modelA(models.Model):
name = models.CharField(...)
class modelB(models.Model):
date = models.DateTimeField(...)
A = models.ForeignKey(modelA, ...)
class modelC(models.Model):
email = models.CharField(...)
B = models.ForeignKey(modelB, ...)
class modelD(models.Model):
uid = models.CharField(...)
C = models.ForeignKey(modelC)
Given modelA element id, I have to filter modelD elements based on that id. But I am not sure about how to do that.
I appreciate any ideas!
modalD.objects.filter(C__B__A__name ='name')
when you use double underscore you filter the related Inheritance modal
I have 3 models:
class Model1(models.Model):
name = models.CharField(max_length=30)
class Model2(models.Model):
model1 = models.ForeignKey(Model1)
class Model3(models.Model):
model2 = models.OneToOneField(Model2)
value = models.IntegerField()
I want to get the max among Model1#model2_set#model3.value. How can I do that?
class Model1(models.Model):
name = models.CharField(max_length=30)
def model2_max_value(self):
model2_set.
# for each item in model2_set
# get model2_set_item.model3.value
# and find max among them
I thought I could apply aggregate(Max) here but couldn't find the way to do it.
Something like this should work:
max_value = Model3.objects.filter(model2__model1=self).aggregate(Max('value'))
Essentially I have 6 object models, 3 for my regular objects and 3 for the dependencies of those objects. Individually, these objects can be dependent on one or multiple instances of each of the 3 regular objects.
My Question:
Is this best practice? I essentially want to be able to add a new dependency to a regular object when needed. For example:
a = A.objects.get(id=1)
adependency = ADependencies.objects.get(dependentTo=a)
Then, I'd have an object with all of the dependencies for a.
Alternatively, I did think of a way to merge the 3 dependency objects into one; however, I'm unsure whether it's good practice.
class Dependencies(models.Model):
id = models.CharField(max_length=16)
dependentTo = CharField(max_length=16)
a = models.ManyToManyField(A)
b = models.ManyToManyField(B)
c = models.ManyToManyField(C)
In this scenario, I don't use a ForeignKey to map the dependentTo object. Instead, I would use the object id to pull the object - allowing me to be class agnostic; however, this would require unique ids throughout the 3 regular objects.
a = A.objects.get(id=1)
adependency = ADependencies.objects.get(dependentTo=a.id)
One more idea!
Is it possibly to still use ForeignKey's, but pass in a string with the class name instead?
class Dependencies(models.Model):
id = models.CharField(max_length=16)
type = models.CharField(max_length=16)
dependentTo = ForeignKey(type)
a = models.ManyToManyField(A)
b = models.ManyToManyField(B)
c = models.ManyToManyField(C)
Object Models:
class A(models.Model):
id = models.CharField(max_length=16)
title = models.CharField(max_length=32)
summary = models.CharField(max_length=256)
class B(models.Model):
id = models.CharField(max_length=16)
title = models.CharField(max_length=32)
summary = models.CharField(max_length=256)
a = models.ForeignKey(A)
class C(models.Model):
id = models.CharField(max_length=16)
title = models.CharField(max_length=32)
summary = models.CharField(max_length=256)
b = models.ForeignKey(B)
class ADependencies(models.Model):
id = models.CharField(max_length=16)
dependentTo = models.ForeignKey(A)
a = models.ManyToManyField(A)
b = models.ManyToManyField(B)
c = models.ManyToManyField(C)
class BDependencies(models.Model):
id = models.CharField(max_length=16)
dependentTo = models.ForeignKey(B)
a = models.ManyToManyField(A)
b = models.ManyToManyField(B)
c = models.ManyToManyField(C)
class CDependencies(models.Model):
id = models.CharField(max_length=16)
dependentTo = models.ForeignKey(B)
a = models.ManyToManyField(A)
b = models.ManyToManyField(B)
c = models.ManyToManyField(C)
Thanks!
This can be done a lot simpler. Define a Dependency model instead of a Dependencies model. You will need the contenttypes django contribution:
from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
class Dependency(models.Model):
dependent_contenttype = models.ForeignKey(ContentType)
dependent_id = models.PositiveIntegerField()
dependent = GenericForeignKey('dependent_contenttype', 'dependent_id')
prerequisite_contenttype = models.ForeignKey(ContentType)
prerequisite_id = models.PositiveIntegerField()
prerequisite = GenericForeignKey('prerequisite_contenttype',
'prerequisite_id')
Then you can make dependencies a reverse generic relation on models A, B and C if you like:
class A:
# ...
dependencies = GenericRelation(
Dependency,
content_type_field='dependent_contenttype',
object_id_field='dependent_id')
I think inheritance may simplify your data structures a lot.
Let's leave model A as-is:
class A(models.Model):
id = models.CharField(max_length=16)
title = models.CharField(max_length=32)
summary = models.CharField(max_length=256)
Your classes B and C has those fields of A plus one additional, so we may rewrite that as
class B(A):
a = models.ForeignKey(A)
class C(A):
b = models.ForeignKey(B)
Now as we have one base class, we only need one dependency class:
class ADependencies(models.Model):
id = models.CharField(max_length=16)
dependentTo = models.ForeignKey(A)
dependents = models.ManyToManyField(A)
Now you can set any of A, B and C objects to dependentTo and dependents. If you only need the main object from dependency, the object of type A will have either attribute b, attribute c or none of them. You may also query on those attributes:
ADependencies.objects.filter(dependentTo__b__isnull=False)
This structure is more scalable and more easily maintainable because if you need to add one more model, you only need to write the unique code for it and don't have to deal with dependency classes.
One more way to simplify your models is to just have one model:
class A(models.Model):
id = models.CharField(max_length=16)
title = models.CharField(max_length=32)
summary = models.CharField(max_length=256)
a = models.ForeignKey(A, null=True)
This way you only have model A and you may leave field a empty (indication that it is just a simple A instance) or set the value of a (it will mean the object of type B or C). Then your dependency class is the same as in previous example, but you don't need to deal with those backwards relations to test for true object type.
If you really need to disinguish between B and C objects you may write your A class like this:
class A(models.Model):
A = 0
B = 1
C = 2
TYPE_CHOICES = (
(A, "A"),
(B, "B"),
(C, "C")
)
id = models.CharField(max_length=16)
title = models.CharField(max_length=32)
summary = models.CharField(max_length=256)
a = models.ForeignKey(A, null=True)
obj_type = models.IntegerField(choices=TYPE_CHOICES)
This way you have just one model class and one dependency class and can tell what type the object is by checking obj_type. Also you should implement some check to prevent cases where a is not null and obj_type is A and similar.
Let me know if this solution is what you need.
I have these models in my app models.py:
class A(models.Model):
#some details
pass
class B(models.Model):
a = models.ForeignKey(A, null=True, blank=True)
c = models.ForeignKey(C, null=True, blank=True)
class C(models.Model):
pass
def method(self):
b_list = B.objects.filter(c=self)
a_list = []
for b in b_list:
a_list.append(b.a)
return a_list
this gives me an error when i launch the webserver because in B it declares that C is not defined.
then if i put these models in order A C B django tells me that B is not defined in C's method().
How can i resolve this "not defined" issue in this situation? it seems circular!
You can always use a string in such cases:
class A(models.Model):
#some details
pass
class B(models.Model):
a = models.ForeignKey("A", null=True, blank=True) # note the quotes
c = models.ForeignKey("C", null=True, blank=True) # note the quotes
class C(models.Model):
pass
If this was a more "extreme" case and you couldn't use this trick, declaring C first, then A and B, and after that C.method (def C_method [...] C.method = C_method) would have been the way to follow.