I have two classes: Author and Book. I want class Authors to have an attribute that contains all books written by the said author, as referenced to as foreign key in the class Books. The method I did does not appear to be working, which I assume is because when the database is being created in migrations, no Books objects exist yet. Or so I believe, I'm pretty new at django.
class Author(models.Model): AuthorName = models.CharField(max_length=255, unique=True) books = Book.objects.get(pk=object_instance.pk) class Book(models.Model): BookName = models.CharField(max_length=255) Author = models.ForeignKey('Author')
The error message I get is:
NameError: name 'Book' is not defined
Which I get, is because I'm referencing to another class without actually having and instance of that class. I just can't figure out a proper way to do this.
EDIT: I reformatted it to be like this:
class Author(models.Model): AuthorName = models.CharField(max_length=255, unique=True) books = author.book_set.all() class Book(models.Model): BookName = models.CharField(max_length=255) Author = models.ForeignKey('Author')
which yields error:
NameError: name 'author' is not defined
Maybe I should just query for the datapoints I need later on in views as opposed to creating own field for them in models though..
EDIT 2: solution from answers:
So my mistake all along was to try to add the "books" field in the author table. I guess there's no way to do this then. I can get that method to work in views so I guess this is sort of solved, although not in the way I was originally planning to do it.
doing
class Author(models.Model): AuthorName = models.CharField(max_length=255, unique=True) class Book(models.Model): BookName = models.CharField(max_length=255) Author = models.ForeignKey('Author')
and then later doing this in views:
author = Author.objects.get(pk=1) books = author.book_get.all()
yields the wanted result (which I sort of knew beforehand, but I was trying to implement a books field in the models, which, if i correctly understood, is not possible at least not with this method).
another solution:
class Author(models.Model): AuthorName = models.CharField(max_length=255, unique=True) class Book(models.Model): BookName = models.CharField(max_length=255) Author = models.ForeignKey(Author, related_name = "books")
The __str__ method just tells Django what to print when it needs to print out an instance of the any model.
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 .
Introduction to Django Foreign Key. A foreign key is a process through which the fields of one table can be used in another table flexibly. So, two different tables can be easily linked by means of the foreign key. This linking of the two tables can be easily achieved by means of foreign key processes.
The related_name attribute specifies the name of the reverse relation from the User model back to your model. If you don't specify a related_name, Django automatically creates one using the name of your model with the suffix _set. Explanation: Illustration of related_name=”name” using an Example.
You don't need to create a separate field in Authors
model
class Author(models.Model): AuthorName = models.CharField(max_length=255, unique=True) class Book(models.Model): BookName = models.CharField(max_length=255) Author = models.ForeignKey('Author')
You can get all books of a particular author like:
author = Author.objects.get(id=1) books = author.book_set.all()
Learn more about backward relationships here
Just add related_name
to ForeignKey and you will be able to get all books made by an author.
For example:
class Book(models.Model): ... author = models.ForeignKey('Author', related_name='books') ...
and later...
author = Author.objects.get(pk=1) books = author.books.all()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With