How to use foreignkey with different models in DJango - django

I'm stack with this problem, and looking for some solution before asking this question here. Lets say I have a one Model that shares same field in different Models how can I achieve this that when I get the objects of those Models I can include that Model foreign key, I did try to achieve this using Generic Relation in DJango yet it didn't solve my issue.
here is the sample what I'm trying to achieve using Generic Relation:
Model1(models.Model):
.. objects_on_this_model ..
Model2(models.Model):
.. objects_on_this_model ...
# Now this is where the model I could save different models with same field shared
SameObjectModel(models.Model):
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntengerField()
content_object = GenericForeignKey('content_type', 'object_id')
.. objects_on_this_model .. # which is the field that has same field to use in different models
So when I try to get the objects from Model(n) how can I achieve or get the SameObjectModel?
I have this on my mind that I could do this:
Model(n).objects.prefetch_related('fk').all()
Seems it is not a good idea, since I do not know where I should put the related_name since the foreign key is the content_type which is the model and there is the object_id represent the field primary_key.

On your Model(n)'s you can add a GenericRelation to SameObjectModel:
from django.contrib.contenttypes.fields import GenericRelation
class Model1(models.Model):
sameobject = GenericRelation(SameObjectModel)
With this, it should be possible to use prefetch_related:
Model1.objects.prefetch_related('sameobject').all()

Related

Is there a way to create a django model foreignkey field with variable choices?

Let's say I have three models device, mechanical and digital. In the device model I have a field type. The type field needs to be in a foreign key relationship with either mechanical or digital model which will be determined by the data. Is there any way to create the type field in such a way that the model in which the foreign key relationship is to be done can be chosen manually.
Something like:
type = models.ForeignKey(to=Choices)
where the Choices could be digital and mechanical.
I have tried implementing generic foreign keys but my database schema is a bit complex so that would be very difficult to maintain. Is there any other way in django that I can do the above?
A generic way that you can manage this would be to use your own models.
Create a ChoiceItemGroup model, slug, name, description.
Create another model ChoiceItem, with slug, name, description, and FK to ChoiceItemGroup.
Then you can do:
type=models.ForeignKey(ChoiceItem, on_delete=models.CASCADE)
Then you can create generic choices and generic choice groups by registering the models in the admin panel
Adding a foreign key from one of your own models to ContentType allows your model to effectively tie itself to another model class, But it’s possible to go one step further and use ContentType to enable truly generic (sometimes called “polymorphic”) relationships between models.
For example, it could be used for a tagging system like so:
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models
class TaggedItem(models.Model):
tag = models.SlugField()
content_type = models.ForeignKey(ContentType,
on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
def __str__(self):
return self.tag
Django generic relations

Add a unique "intermediary" model to all my Django ManyToManyField()

Hello Awesome People!
Such a question that I have made a lot of searches for it. I am done building a website two(2) months ago, but today The team decides to track every time an instance has been added to a Model in ManyToManyField() fields.
I was thinking using the through argument to point to the model that will act as an intermediary may work but not at all in my case (70%). Just Because I want to have a unique intermediary model that will record for all ManyToManyField()
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
date_joined = models.DateTimeField(auto_now_add=True)
Ah! Something is required. I need to explicitly specify foreign keys to the models that are involved in the many-to-many relationship.
Django ContentType may anticipate for all my models, but it's not working, I wonder why? it also contains ForeignKey (the one required by an intermediary model).
Do I really need to edit all my ManyToManyField fields and create Model as much as ManytoManyField? is there a way to record date_joined without creating an intermediary model for each?
Are you perhaps looking for something like django admin's LogEntry model?
LogEntry contains the ContentType of the model instance that has changed, the id of the instance, the type of change and an abstract change message. With all of that you can retrace changes made to instances.
In django admin, the views take care of adding records to LogEntry via three methods log_change/addition/deletion: click.

Add a GenericRelation in a Proxy Model

I have a group of models in django 1.5.2 that all use GenericForeignKey and GenericRelation. The problem is that I also use proxy inheritance. A generic relation is a Field, but not a DB field, but when validating the model, django sees a Field in a proxy inherited model and raises an error.
Below is a simplified version of my problem. Is there a simple solution that would allow me to access simply the tags from TaggableArticle ?
from django.db import models
from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType
class Tag(models.Model):
tag = models.SlugField()
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
class Article(models.Model):
text = models.TextField()
class TaggableArticle(Article):
tags = generic.GenericRelation(Tag)
class Meta:
proxy = True
The result is :
python manage.py validate
FieldError: Proxy model 'TaggableArticle' contains model fields.
[1] 15784 exit 1 python manage.py validate
My thoughts so far :
django 1.6 introduces a for_concrete_model flag in generic relations, but I haven't been able to see if this could solve my problem. I just understood that it could help if the relation was in Article, and if I wanted to be able to tag an object with the proper content type (Article vs TaggedArticle).
I could remove the relation and just access it from the other endpoint (i.e. `Tag.objects.filter(content_object=myTaggedArticle) or manually add a method to this) but part of the implementation I have integrates the fact I'm using a RelatedManager and not just a normal Manager, and I would not be getting a related manager if I came from the whole TaggedArticle class.
Tkank you !

I don't know when to use class GenericForeignKey in django.contrib.contenttypes module

I don't know when to use class GenericForeignKey in django.contrib.contenttypes module
https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#django.contrib.contenttypes.generic.GenericForeignKey
I just read above link, but I don't know.
When I use that class??
When are that class useful?
Please give me some examples~
The name says allot, it is a foreign key that can link to any content type i.e it can have a relation to any model. A nice example would be for a voting model where you could vote on a number of different objects and the vote instance in the vote model would just link to the model that you voted for.
class Article(models.Model):
.......
class Video(models.Model):
......
class Like(models.Model):
user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
obj = generic.GenericForeignKey()
Say you have these models above, The user can like an article and a video but you don't want to create a model for article likes and video likes separately because it creates unnecessary tables in you database and this can be painful especially if you have allot of models that can be liked. To solve this you create one Like model which can store all the likes of your website in one model. So when a user likes an article the like instance would have a relation to the user and to an article even though there is no explicit foreign key to the Article model, this would be done by setting the content type of the like model to the content type of the model you liked, which would be 'article' in this case (not you can use this :ContentType.objects.get_for_model(Article) to get the content type of a model) and then assign the id of the article to the object id.
article = Article.objects.get(pk=1)
article_ct = ContentType.objects.get_for_model(Article)
user = User.objects.get(username='admin')
Like.objects.create(user=user, content_type=article_ct, object_id=article.id)

Show related inlines in the admin on form of model with GenericForeignKey

I have simple models with generic relations from this example at the Django Project:
class Image(models.Model):
image = models.ImageField(upload_to="images")
class ImageLink(models.Model):
image = models.ForeignKey(Image)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey("content_type", "object_id")
class Product(models.Model):
name = models.CharField(max_length=100)
It's very simple to show inline ImageLink objects on the admin form of Product. It is demonstrated in the Django docs.
Can anyone suggest how have related ImageLinks inline on the admin form of an Image model?
IMPORTANT UPDATE: Updated example of model, becourse with previous, as Daniel sayd, it's not need to show objects inline.
It's neccessary use generic.GenericTabularInline for showing ImageLink objects inline on the Product form, as demonstrated in the Django docs.
But if we need to show related ImageLink inline on the Image form, it can be done with simple child of admin.TabularInline class.
It's very simple solution. I think I'm stupid not to guess it right away.
You don't have any related Products to show inline. Generic foreign keys, like normal ones, are one-to-many, with the 'one' side of the relation being the one containing the foreign key field. So in your case you still only have one Product for each Image, so there is no inline set to show.