Django: Get objects for which ForeignKey does not exist - django

Given:
class A(models.Model):
...
class B(models.Model):
...
class C(models.Model):
a = models.ForeignKey(A)
b = models.ForeignKey(B)
For a fixed b of class B, I would like to retrieve all those Objects a from A, for which there is no entry (a,b) in C.
I am failing to come up with a correct filter to achieve this.

Start with class A, since that's the type of object you ultimately want. You'll either want to filter those or exclude them. We could try to filter for the objects that don't have a matching entry, but you know what? It'll be easier to exclude the ones that do have a match.
Assuming class A has a related field of c for the C.a foreign key...
A.objects.exclude(c__b=b)

Related

Add a property to class but not store in database, django?

What is the best way to do this:
I have a classes(tables) A,B,C. Classes B and C have a foreign key to class A.
I want to access class B from A but i do not want to access class C from A. How to store that information in A? What is a best way? I do not want a column in db for that..
Just do it like you normally would. The only things that get turned into database fields are the properties that are created from the models.___Field-type constructors.
class A(models.model):
# fields go here like normal
def some_function(self):
print B.SOME_CCNST
for theB in self.myBs.all():
pass # Do whatever
class B(models.Model):
myA = models.ForeignKey(A, related_name="myBs")
SOME_CCNST = "Whatever"
class C(models.Model):
myA = models.ForeignKey(A, related_name="+")
Note that there won't be a reverse manager created in A to go to its Cs, because we set related_name="+". See the docs for more.

Restricted ManyToMany relationships in Django

I'm hoping someone can point me to the most Djangoic way to represent the following general relationship with models, so that Django's existing logic naturally enforces the relationship.
Thing A and Thing B both have one of a number of Types. Thing A can be related to many, one, or no Things Bs and vice-versa (in a symmetric fashion), however Thing A and Thing B can be related if and only if they share the same Type.
My current implementation is to have three models, A, B, and Type, where As and Bs have a foreign key to Type, and A has a m2m with B.
class A(models.Model):
b = models.ForeignKey(B)
typ = models.ManyToManyField(Type)
class B(models.Model):
a = models.ForeignKey(A)
class Type(models.Model):
name = models.CharField()
This lets me do what I want, but doesn't enforce the fact that A can't have a B of another Type. I can use filtering logic in views I control, but where I have less control, like in the Admin, Django lets me map As to Bs of different Types. Is there another way to represent the relationship between As, Bs, and Types in Django?
This would be my approach off the top of my head:
class A(models.Model):
typ = models.ManyToManyField(Type)
#property
def related2B(self)
return list of relationships
def save
check that relationship is still valid if typ field changes
class B(models.Model):
typ = models.ManyToManyField(Type)
#property
def related2A(self)
return list of relationships
def save
check that relationship is still valid if typ field changes
class Type(models.Model):
name = models.CharField()
class Relationship(models.Model):
classA = models.ForeignKey(A)
classB = models.ForeignKey(B)
def save
do check that they share a type before saving
Have you looked at limit_choices_to as a way to control the scope of the M2M?
It can take Q objects for complex queries, but am guessing not F ones (for complex queries including the parent object's current state), but you still might be able to make it deny the save if inappropriate

Django Models - Foreign Key of different objects types that share a common base class

I have the following conceptual design in mind for one of my models.
class A(models.Model):
...
class B(A): #Inherits A
fieldA = ...
fieldB = ...
class C(A): #Inherits A
fieldC = ...
fieldD = ...
class D(models.Model):
field = models.ForeignKey(A) #Here lies the problem, should store B or C
Given the models above, I'd like to store a foreign key to either B or C in D but not both.
I tried setting the Meta class property of A to abstract but that doesn't allow a ForeignKey relationship to A. I do not want to ever have an instance of A that isn't B or C, but if necessary, I can restrict this behavior with the save signal.
Is there an easier design that would allow me to store a foreign key from a list of types where all classes inherit from a common base?
I can think of two options:
Use a generic relation in your D class instead of a foreign key.
If you don't need to filter D using specific fields from B or C you could continue with the approach you have now, but add a method to D that would retrieve the child class of field:
class D(models.Model):
field = models.ForeignKey(A)
def get_field(self):
try:
return self.field.b
except B.DoesNotExist:
pass
try:
return self.field.c
except C.DoesNotExist:
pass
This definitely has some performance implications and as you said in your post, you would have to manually ensure that every instance of A has a B or C subclass. Obviously this approach doesn't scale well if you are going to have n number of subclasses.

Django - Append a related field to a queryset

I have two models:
class A(models.Model):
# fields
class B(models.Model):
a = models.ForeignKey(A)
name = models.CharField(max_length=64)
What I want to do is to get a filtered queryset from A in addition to the related objects from B and append them to the queryset from A, so I would be able to access name field this way: A.B.name
Any idea how to do this?
The problem is that, since the relationship is one-to-many, A doesn't have just one B, but rather a b_set
You could so something like:
for b in a.b_set.all():
b.name
But you can't reference just B because that concept doesn't exist. It would however, if you had used a OneToOneField. Then you could easily do:
a.b.name
Because there's only one B for each A. But, you have to model your object after the actual relationships going on, not how you would prefer the api to work.

how to handle many to many relationships in modelForms

I have a model similar to this one:
class A(models.Model):
name = models.CharField(primary_key=True)
class B(models.Model):
(morefields)
target = models.ManyToManyField(A,through='C')
class C(models.Model):
a_key = models.ForeignKey(A)
b_key = models.ForeignKey(B)
(extra fields)
I am creating a form to edit an item of B using a modelForm. However, I get "Cannot set values on a ManyToManyField which specifies an intermediary model" error. If I exclude the target field it works fine.
Could you suggest any way to workaround this?
You can use inlines. The problem is that Django can't create the relation for you because there's additional fields that must be set on the join table (your "through" model). Try the following:
class CInlineAdmin(admin.TabularInline):
model = C
extra = 1
class BAdmin(admin.ModelAdmin):
inlines = [CInlineAdmin,]
By your own mentioning above, you have (extra fields) in Class C. How is django supposed to populate those extra fields, if by using given A, you want to create more B's.
You should probably create an admin for C, where in you can add each A and B to a given C