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')
Related
I am trying to access the Item model through the Thing queryset, and keep getting the error:
django.core.exceptions.FieldError: Field 'content_object' does not generate an automatic reverse relation and therefore cannot be used for reverse querying. If it is a GenericForeignKey, consider adding a GenericRelation.
class ThingContent(models.Model):
content_id = models.AutoField(primary_key=True, null=False)
thing = models.ForeignKey('Thing', on_delete=models.SET_NULL, null=True)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
I have tried updating the fields on Item by adding a related_query_name to no success.
self.queryset.filter(items__item_date=exact_item_date))
class Item(models.Model):
id = models.AutoField(primary_key=True, null=False)
item_date = models.DateField(**options)
thing_content = GenericRelation('ThingContent', related_query_name='items')
content_object is generic. You must filter by object_id and content_type for know what object you FK generic.
You try again with query like this:
ThingContent.objects.filter(
items__item_date=item_date,
content_type=ContentType.objects.get_for_model(Item)
)
this query mean: find all ThingContent have mapping with Item, and have item_date like what you want filter.
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
I am trying to retrieve a field from a GenericForeignKey and cannot make it work in the model.py - it works in the admin.py though.
models.py:
class Run(models.Model):
name = models.CharField(max_length=100)
class TaskRunRelation(models.Model):
limit = models.Q(app_label = 'thisapp', model = 'run') | models.Q(app_label = 'thisapp', model = 'runb')
content_type = models.ForeignKey(ContentType, limit_choices_to = limit)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
def modeltestname(self):
self.content_object.name
admin.py:
class TaskRelationAdmin(admin.ModelAdmin):
list_display = ['modeltestname','mytestname']
def mytestname(self,obj):
return obj.content_object.name
So mytestname shows the correct value in the Admin whereas modeltestname shows "(None)". Why is this not working in the model.py? Am I missing something how Genericforeignkey works or is there any other mistake in there?
That is because you are not returning anything from modeltestname. If a function or method does not return anything explictly, it would return None by default. Hence the result
So change the class method to
def modeltestname(self):
return self.content_object.name
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()
I want the a counterpart of Tag (BlogPost) to have at least 1 instance of Tag or it shouldn't be created. (same effect like null=False). I tried a lot but couldn't figure out to apply these contrains. Any ideas?
class Tag(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
text = models.CharField("text", max_length=255)
class Meta:
unique_together = ('content_type', 'object_id', 'text',)
class BlogPost(models.Model):
title = models.CharField("title", max_length=255)
tags = generic.GenericRelation(Tag, verbose_name="tags")
class TagInline(generic.GenericTabularInline):
model = Tag
extra = 1
class BlogPostAdmin(admin.ModelAdmin):
inlines = (TagInline,)
If you want this in the form of a Database constraint, then I'm not sure that such a thing exists.
Otherwise I would go with overriding the clean( self ) function on your model.
This can be used for custom validation.
def clean( self ):
# validate that this model has one or more tag