generic relation setting content_object with unsaved model - django

Say I have the following model:
class Foo(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
class Bar(models.Model):
baz = models.BooleanField()
then run the following code:
f = Foo(content_object=Bar(baz=False))
print f.content_object
what I would expect to see is something like:
<Bar: Bar object>
but instead it seems as if it's empty... why is this?

Follow the following:
b=Bar(baz=False)
b.save()
f = Foo(content_object=b)
f.content_object
This gives the desired result for you.

Content_object has to be split into content_type and object_id. And until you save the object into the database there is no object_id available. Therefore you have to save it first - like Sandip suggested. You can do it in a shorter form as well: Baz.objects.create(baz=False)

Related

Get the name attribute of a GenericForeign key object

I have the following model in a Django app:
How can I get the "name" attribute of any selected content_object in this model and display it in list_display of the modelAdmin class, instead of just displaying the keys of the GenericForeign Key objects. Please I really need help with this.
class Checkout(models.Model):
checkout_date = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
check_in_complete = models.BooleanField(default=False, editable=False)
content_type = models.ForeignKey(ContentType,
limit_choices_to={"model__in": ('Facilitator', 'Enumerator', 'Tutor')})
object_id = models.PositiveIntegerField(verbose_name='Receiver')
content_object = GenericForeignKey('content_type', 'object_id')
Since GenericForeignKey is not a normal field object, you can not use it in filters:
Checkout.objects.filter(content_object=other_obj) # this will fail
But if you want to access the name property of the object your checkout is associated with using GenericForeignKey you can do it like following:
name = checkout_obj.content_object.name

Django. get union of related querysets

The following is what I'm trying to do.
Of course this will be darn slow, and wonder if there's a better way of doing it.
class Foo(models.Model):
bars = generic.GenericRelation(Bar)
class Meta:
abstract = True
class Bar(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
invitation = generic.GenericForeignKey('content_type', 'object_id')
timestamp = models.DateTimeField(auto_now_add=True, db_index=True)
meat = models.ForeignKey(Jessy)
bars = Bar.objects.none()
for foo in Foo.objects.all():
bars = bars | Q(foo.bars.all())
bars.values('meat').order_by('timestamp'):
You can just use:
Bar.objects.filter(content_type=ContentType.objects.get_for_model(Foo), object_id__isnull=False).values('meat').order_by('timestamp')
That will query all Bar objects that have associated any Foo model.

Django, GenericForeignKey is None when accessing an item of QuerySet result?

Suppose you have a generic foreign key in MyModel.
class MyModel(models.Model):
content_type = models.ForeignKey(ContentType, db_index=True, related_name='+')
object_id = models.PositiveIntegerField(db_index=True)
target = generic.GenericForeignKey()
Is the target supposed to be None when you iterate queryset of this class?
for my_model in MyModel.objects.all():
print my_model.target # <-- this is None
It's supposed to give you the related object if it has one.
If you are sure it has one:
Try instead:
target = GenericForeignKey('content_type', 'object_id')

Django tastypie save reverse GenericForeignKeyField

Django Tastypie can save related objects even with reverse relationship.
But is it able for Django Tastypie to save reverse relationship of GenericForeignKeyField?
My resources (not full, but the important only),
class AreaResource(ModelResource):
tripl3user = fields.ManyToManyField(
'tripl3sales.api.resources.area.Tripl3UserResource',
'tripl3user',
related_name='area',
full=True
)
class Tripl3UserResource(ModelResource):
content_type = fields.ForeignKey(
'tripl3sales.api.resources.contenttype.ContentTypeResource',
'content_type'
)
content_object = GenericForeignKeyField({
Area : AreaResource
}, 'content_object')
My models.py,
class Area(models.Model):
name = models.CharField(max_length=50, unique=True)
tripl3user = generic.GenericRelation('Tripl3User')
class Tripl3User(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
Is it possible to save reverse relationship of generic foreign key? If so, then how to do it? What does the data look like?
Finally I got the answer.
In a resource that has content_type and object_id, there is no need to declare content_type because content_object is enough. And for related_name, instead of using area, we use content_object.
So, my resources.py should be,
class AreaResource(ModelResource):
tripl3user = fields.ManyToManyField(
'tripl3sales.api.resources.area.Tripl3UserResource',
'tripl3user',
related_name='content_object',
full=True
)
class Tripl3UserResource(ModelResource):
content_object = GenericForeignKeyField({
Area : AreaResource
}, 'content_object')
Hope this will help others.

Accessing referring object with GenericForeignKey in django

I have the following models:
Class A(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
thumbnail = models.ImageField(...)
class B(models.Model)
title = models.CharField()
def save(*args, **kwargs):
# Based on the title field I want to fetch some picture and then save the thumbnail in A
I have more classes like B which should be referenced from A (this is why I use GenericForeignKey). The problem I am trying to figure out is how to save the thumbnail field (on A) when I am in the save() method in B. Inserting many if statement in A to check the type of the referenced class and save the thumbnail accordingly is pretty cumbersome.
Looking at the docs, you can add a reverse generic relation from B to A:
If you know which models you’ll be using most often, you can also add a “reverse” generic relationship to enable an additional API
class A_Model(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
thumbnail = models.ImageField(...)
class B_Models(models.Model)
title = models.CharField()
a_models = generic.GenericRelation(A_Model)
and now you can do:
b = B_Model()
a = A_Model(content_object=b, thumbnail=...)
a.save()
b.a_models.all()