ForeignKey to multiple Models or Queryset - django

It is possible to make a ForeignKey to more than one model. I want to choose from different models like Parts and Machines Model.
I read this to combine multiple models into one list: How to combine 2 or more querysets in a Django view?
How can I get foreign key to that list somehow?

I know that you asked this over year ago, but I had a similar problem and I want to share a link to the solution for future readers.
Generally the contenttypes framework solves this problem, and I guess this is what Daniel Roseman was talking about.
How to use dynamic foreignkey in Django?

You need generic relations.
A generic relation allows you to dynamically the target model of the foreign key.

I'll provide a comprehensive answer for this question, I know its quite old, but it's still relevant.
We're gonna be using Generic Relations.
First, in settings.py make sure that django.contrib.contenttypes is included in the INSTALLED_APPS array.
Let's create a new model in models.py:
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
With content_type we can associate Image with any other model class, while object_id will hold the other model instance.
class Image(models.Model):
image = models.ImageField(
upload_to="imgs/products", blank=True)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey()
To refer back to the Image model from a Company instance we need to make a reverse generic relation
class Company(models.Model):
name = models.CharField(max_length=100)
images = GenericRelation(Image)
In schema.py, we can create Images in a Company instance like:
company_instance = Company(name="Apple")
company_instance.save()
for img in imgs:
#Image(image=img, content_object=company_instance)
company_instance.images.create(image=img)
company_instance.images.all() # fetch all images
the company_instance.images field is just a GenericRelatedObjectManager (docs)
This is how the final Image table looks in the database:

The Django-polymorphic library provides a simple solution that should work well with the admin and forms too using formsets.
For example:
from polymorphic.models import PolymorphicModel
class BookOwner(PolymorphicModel):
book = models.ForeignKey(Book, on_delete=models.CASCADE)
class StaffBookOwner(BookOwner):
owner = models.ForeignKey(Staff, on_delete=models.CASCADE)
class StudentBookOwner(BookOwner):
owner = models.ForeignKey(Student, on_delete=models.CASCADE)
With this, you can use the parent model to set the owner to either a Staff or Student instance or use the child models directly.

Related

Django import into many to many relationship with custom through table

I am not sure the proper way to import using django-import-export tsv files into many to many relationship tables. What I have done is create a books table, a genre table and a bookgenre through table which contains the foreignkeys to each of the other tables. So what I have is:
class Book(models.Model):
title = models.CharField(max_length=255)
class Genre(models.Model):
genre = models.CharField(max_length=64)
class BookGenre(models.Model):
book_id = models.ForeignKey('Book', on_delete=models.CASCADE)
genre_id = models.ForeignKey('Genre', on_delete=models.CASCADE)
Then I import all three tables and the relationships are working but I can't figure out a way to make a view or template that works effectively. I am thinking there must be a better way to create a many to many relationship and import data into it. Any Ideas?
You don't need to create a pivot table, use many-to-many relationships.
UPDATE
You do not create a m2m model, but a many-to-many relationship that points to a specific model. Below is the implementation.
class Abc(models.Model):
field = models.TextField()
class Xyz(models.Model):
other_field = models.TextField()
m2m_field = models.ManyToManyField(Abc)
If you want to get related data, you will use:
object_xyz.abcs.all()
or object_abc.xyz_set.all()
As I wrote earlier, you can find more detailed information in the documentation.

How to add custom filed to Django User Model

I am working on the project using django 1.9.
I need to add a field to the user model 'Auth_user' table, the field which i want can be another primary key and act here as foreign key in the 'auth_user'.
I searched a lot but fails. Can any buddy provide me some example how to achieve this like how to to add fields to 'auth_user'
You can substitute the user model entirely as described in doc. Here is an example:
AUTH_USER_MODEL = 'myapp.MyUser'
to your settings.py, and add following to your model:
from django.contrib.auth.models import AbstractUser
class MyUser(AbstractUser):
another_object = models.ForeignKey(OtherModel..
just make a new moel with a user foreign key
class Post (models.Model):
title = models.CharField(max_length=80)
slug= models.SlugField(unique=True)
content = models.TextField()
user_creator = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
there you can use as primary key the id of the post, or the slug (unique), and it can be linked to a user, if you need one to one relationship see this or many to many relationship see this
Maybe you just need to extend de model user
https://docs.djangoproject.com/en/1.11/topics/auth/customizing/#extending-the-existing-user-model

Django: Best practice with Foreignkeys and multiple models

Hi Stackoverflow people,
What is the best way to refer from one model to a choice of ForeignKeys?
I am working on a rental app, which includes a model for the GenericVehicle, Bikes, and Cars.
class GenericVehicle(models.Model):
licence = models.CharField(max_length=128)
...
class Meta:
abstract = True
class Bike(GenericVehicle):
engine_type = models.CharField(max_length=128)
...
class Car(GenericVehicle):
number_of_doors = models.SmallIntegerField()
...
Now I have a model for the rental registration, where I would like to register the rented vehicle. I am unsure about the best practise here. So far, I had two foreignkeys and made sure that at least one is filled. But this solution seems very inefficient and does not scale well for multiple vehicle types.
What is the best way to improve the class structure/definition?
class Rental(models.Model):
rental_bike = models.ForeignKey(Bike)
rental_car = models.ForeignKey(Car)
rental_date = ...
Thank you for your advice. I am trying to find an efficient solution for some time already.
Django offers you a GenericForeignKey. A GenericForeignKey will need to fields on you model, one for saving the referenced model's ContentType and a second one to save the object's id:
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
class Rental(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
rental_vehicle = generic.GenericForeignKey('content_type', 'object_id')
But keep in mind that this not a foreign key on database level, just Django kind of emulating some of the typical behaviour of a foreign key.

Django forms with odd model relationship

I am working with an existing database that I can not modify and having some trouble trying to deal with presenting forms for modifying the database in Django. The structure in question is as follows and all models are unmanaged.
class Persons(models.Model):
personid = models.BigIntegerField(primary_key=True, db_column='PersonID')
....
class Phones(models.Model):
phoneid = models.BigIntegerField(primary_key=True, db_column='PhoneID')
number = models.CharField(max_length=60, db_column='Number', blank=True)
type = models.CharField(max_length=15, db_column='Type', blank=True)
...
class Personsphones(models.Model):
personphoneid = models.BigIntegerField(primary_key=True, db_column='PersonPhoneID')
personid = models.ForeignKey(Persons, db_column='PersonID')
phoneid = models.ForeignKey(Phones, db_column='PhoneID')
...
I want to create a form to display all of the 'Phones' associated with a particular 'Persons' and in addition be able to modify/add/remove 'Phones' belonging to a 'Persons'. Right now the only thing I can think of is to display the 'Phones' in a modelformset and then if one is added or removed manually set the 'Personsphones' relation. Any ideas on how to best deal with this model setup?
For making changes to your models you may want to use django-south http://south.aeracode.org/docs/
As far as displaying your 'Phone' under your forms.py you may want to set up class meta like so. With this any changes made to models will reflect on change
class Meta:
model = Persons
exclude = ('user')
In models you may want to use Foreignkey fore relationships between phones and Persons. Better seen in action here https://docs.djangoproject.com/en/dev/ref/models/fields/#foreignkey

What's the difference between django OneToOneField and ForeignKey?

What's the difference between Django OneToOneField and ForeignKey?
Differences between OneToOneField(SomeModel) and ForeignKey(SomeModel, unique=True) as stated in The Definitive Guide to Django:
OneToOneField
A one-to-one relationship. Conceptually, this is similar to a ForeignKey with unique=True, but the "reverse" side of the relation will directly return a single object.
In contrast to the OneToOneField "reverse" relation, a ForeignKey "reverse" relation returns a QuerySet.
Example
For example, if we have the following two models (full model code below):
Car model uses OneToOneField(Engine)
Car2 model uses ForeignKey(Engine2, unique=True)
From within python manage.py shell execute the following:
OneToOneField Example
>>> from testapp.models import Car, Engine
>>> c = Car.objects.get(name='Audi')
>>> e = Engine.objects.get(name='Diesel')
>>> e.car
<Car: Audi>
ForeignKey with unique=True Example
>>> from testapp.models import Car2, Engine2
>>> c2 = Car2.objects.get(name='Mazda')
>>> e2 = Engine2.objects.get(name='Wankel')
>>> e2.car2_set.all()
[<Car2: Mazda>]
Model Code
from django.db import models
class Engine(models.Model):
name = models.CharField(max_length=25)
def __unicode__(self):
return self.name
class Car(models.Model):
name = models.CharField(max_length=25)
engine = models.OneToOneField(Engine)
def __unicode__(self):
return self.name
class Engine2(models.Model):
name = models.CharField(max_length=25)
def __unicode__(self):
return self.name
class Car2(models.Model):
name = models.CharField(max_length=25)
engine = models.ForeignKey(Engine2, unique=True, on_delete=models.CASCADE)
def __unicode__(self):
return self.name
A ForeignKey is a many-to-one relationship. So, a Car object might have many instances of Wheel. Each Wheel would consequently have a ForeignKey to the Car it belongs to. A OneToOneField would be like an instance of Engine, where a Car object has at most one and only one.
The best and the most effective way to learn new things is to see and study real world practical examples. Suppose for a moment that you want to build a blog in django where reporters can write and publish news articles. The owner of the online newspaper wants to allow each of his reporters to publish as many articles as they want, but does not want different reporters to work on the same article. This means that when readers go and read an article they will se only one author in the article.
For example: Article by John, Article by Harry, Article by Rick. You can not have Article by Harry & Rick because the boss does not want two or more authors to work on the same article.
How can we solve this 'problem' with the help of django? The key to the solution of this problem is the django ForeignKey.
The following is the full code which can be used to implement the idea of our boss.
from django.db import models
# Create your models here.
class Reporter(models.Model):
first_name = models.CharField(max_length=30)
def __unicode__(self):
return self.first_name
class Article(models.Model):
title = models.CharField(max_length=100)
reporter = models.ForeignKey(Reporter)
def __unicode__(self):
return self.title
Run python manage.py syncdb to execute the sql code and build the tables for your app in your database. Then use python manage.py shell to open a python shell.
Create the Reporter object R1.
In [49]: from thepub.models import Reporter, Article
In [50]: R1 = Reporter(first_name='Rick')
In [51]: R1.save()
Create the Article object A1.
In [5]: A1 = Article.objects.create(title='TDD In Django', reporter=R1)
In [6]: A1.save()
Then use the following piece of code to get the name of the reporter.
In [8]: A1.reporter.first_name
Out[8]: 'Rick'
Now create the Reporter object R2 by running the following python code.
In [9]: R2 = Reporter.objects.create(first_name='Harry')
In [10]: R2.save()
Now try to add R2 to the Article object A1.
In [13]: A1.reporter.add(R2)
It does not work and you will get an AttributeError saying 'Reporter' object has no attribute 'add'.
As you can see an Article object can not be related to more than one Reporter object.
What about R1? Can we attach more than one Article objects to it?
In [14]: A2 = Article.objects.create(title='Python News', reporter=R1)
In [15]: R1.article_set.all()
Out[15]: [<Article: Python News>, <Article: TDD In Django>]
This practical example shows us that django ForeignKey is used to define many-to-one relationships.
OneToOneField is used to create one-to-one relationships.
We can use reporter = models.OneToOneField(Reporter) in the above models.py file but it is not going to be useful in our example as an author will not be able to post more than one article.
Each time you want to post a new article you will have to create a new Reporter object. This is time consuming, isn't it?
I highly recommend to try the example with the OneToOneField and realize the difference. I am pretty sure that after this example you will completly know the difference between django OneToOneField and django ForeignKey.
OneToOneField (one-to-one) realizes, in object orientation, the notion of composition, while ForeignKey (one-to-many) relates to agregation.
Also OneToOneField is useful to be used as primary key to avoid key duplication. One may do not have implicit / explicit autofield
models.AutoField(primary_key=True)
but use OneToOneField as primary key instead (imagine UserProfile model for example):
user = models.OneToOneField(
User, null=False, primary_key=True, verbose_name='Member profile')
When you access a OneToOneField you get the value of the field you queried. In this example a book model's 'title' field is a OneToOneField:
>>> from mysite.books.models import Book
>>> b = Book.objects.get(id=50)
>>> b.title
u'The Django Book'
When you access a ForeignKey you get the related model object, which you can then preform further queries against. In this example the same book model's 'publisher' field is a ForeignKey (correlating to the Publisher class model definition):
>>> b = Book.objects.get(id=50)
>>> b.publisher
<Publisher: Apress Publishing>
>>> b.publisher.website
u'http://www.apress.com/'
With ForeignKey fields queries work the other way too, but they're slightly different due to the non-symmetrical nature of the relationship.
>>> p = Publisher.objects.get(name='Apress Publishing')
>>> p.book_set.all()
[<Book: The Django Book>, <Book: Dive Into Python>, ...]
Behind the scenes, book_set is just a QuerySet and can be filtered and sliced like any other QuerySet. The attribute name book_set is generated by appending the lower case model name to _set.
I have also been confused with the usage of both the fields.
Let me give an example for understanding their usage, as I have faced the problem recently and realised the usage of both the fields.
I had a model, like this-
from django.contrib.auth.models import User
from django.db import models
class Attendance(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, default="", null=True)
date = models.CharField(max_length=11)
def __int__(self):
return self.id
Now the problem with this was that I can't make multiple objects with the same user,
i.e. a same user will have attendance on multiple days. Hence, multiple objects with same user.
But the OneToOne field didn't let me do that.
Image for reference
So, I changed my model to-
from django.contrib.auth.models import User
from django.db import models
class Attendance(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, default="", null=True)
date = models.CharField(max_length=11)
def __int__(self):
return self.id
Now it works fine and I can mark attendance for a user on multiple days.
So that's where the difference is, OneToOne field will not allow you to make multiple objects with the same user(as an example) but with ForeignKey it is possible.
OneToOneField: if second table is related with
table2_col1 = models.OneToOneField(table1,on_delete=models.CASCADE, related_name='table1_id')
table2 will contains only one record corresponding to table1's pk value, i.e table2_col1 will have unique value equal to pk of table
table2_col1 == models.ForeignKey(table1, on_delete=models.CASCADE, related_name='table1_id')
table2 may contains more than one record corresponding to table1's pk value.
The easiest way to draw a relationship between items is by understanding them in plain languages. Example
A user can have many cars but then a car can have just one owner. After establishing this, the foreign key should be used on the item with the many relationship. In this case the car. Meaning you'll include user as a foreign key in cars
And a one on one relationship is quite simple. Say a man and a heart. A man has only one heart and a heart can belong to just one man
OneToOneField (Example: one car has one owner)
ForeignKey(OneToMany) (Example: one restaurant has many items)
ForeignKey allows you receive subclasses is it definition of another class but OneToOneFields cannot do this and it is not attachable to multiple variables