With following Django models:
class Author(models.Model):
name = models.CharField(max_length=30)
bestbookaccordingtome=models.????(Author,null=True, blank=True, default = None)
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.OnetoOneField(Author)
I want the classic relationship each book has one author (only).
But I also want to be able to assign a chosen book to author (my favourite book of this author for example).
I tried a foreign key but django didn't like it.
Any python clean way to do it?
What you need is ManyToManyField.
class Author(models.Model):
name = models.CharField(max_length=30)
bestbookaccordingtome = models.ManyToManyField('self', symmetrical=False, related_name='best_book_according_to_me')
Also, if you need to specify extra fields in your n-m model, you can use through to indicate the name of the model.
Hope it helps!
Related
I have seen several examples of using select_related to query foriegn key related data in queryset. Including this example. But I want to do it in reverse way as explained below.
class Book(models.Model):
name = models.CharField(max_length=50)
author = models.ForeignKey(Author)
class Author(models.Model):
name = models.CharField(max_length=50)
I have seen queryset to fetch the data while querying the Book because Author is specified in books.Like this
books = Book.objects.all().select_related("author")
But I need to query Author and then get all the books related with it.Is there any way to do that.
You should use related_name in the FK definition:
class Book(models.Model):
author = models.ForeignKey(Author, related_name="books")
An then, from Author you can:
Author.objects.all().prefetch_related("books")
Check the docs for more info.
model.py
class Authors(models.Model):
name = models.CharField(max_length=50)
class Books(models.Model):
date_pub = models.DateField()
name = models.CharField(max_length=50)
author = models.ForeignKey('Authors')
I need to derive the names of authors from a foreign key, but the Books.objects.all().values_list('author', 'name') command infers the id from the Authors model. how to derive author names from the Books model
You can use:
Books.objects.all().values_list('author__name')
It is mentioned clearly in Django documentation: https://docs.djangoproject.com/en/3.0/ref/models/querysets/#values-list
What is the process that you follow to create model in Django? Thanks.
The most important part of a model – and the only required part of a model – is the list of database fields it defines. Fields are specified by class attributes. Be careful not to choose field names that conflict with the models API like clean, save, or delete.
Models.py
from django.db import models
class Musician(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
instrument = models.CharField(max_length=100)
class Album(models.Model):
artist = models.ForeignKey(Musician, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
release_date = models.DateField()
num_stars = models.IntegerField()
You can start here Documentation
See also Django Girls Models
Here's two simple models to use as an example:
class Author(models.Model):
name = models.CharField(blank=True, max_length=50)
age = models.IntegerField(null=True, )
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(Author)
date = models.DateField()
Now what I'd like to do, is create a view for Book that pulls in one of the values from Author using the Django Rest Framework. Here's an example ModelSerializer:
class BookMetaSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ('title','date','author__name',)
The trouble is that one can't access the fields of a foriegn key in the DRF like I gave above author__name. I haven't been able to figure out how to do this based on the documentation. All help is appreciated, thanks!
You can define author_name field with source argument to get the name of an author.
From the DRF docs on source argument:
The name of the attribute that will be used to populate the field. May
be a method that only takes a self argument, such as
URLField('get_absolute_url'), or may use dotted notation to traverse
attributes, such as EmailField(source='user.email').
Final Code:
class BookMetaSerializer(serializers.ModelSerializer):
# use dotted notation to traverse to 'name' attribute
author_name = serializers.CharField(source='author.name', read_only=True)
class Meta:
model = Book
fields = ('title','date','author_name',)
I have declared two of my models this way:
class EmailAddress(models.Model):
customer = models.ForeignKey(Customer)
email_address = models.CharField(max_length=200)
def __unicode__(self):
return self.email_address
class Customer(models.Model):
.
.
.
email_address = models.ForeignKey(EmailAddress)
def __unicode__(self):
name = ''+str(self.title)+" "+str(self.first_name)+" "+str(self.last_name)
return name
The idea is that one customer can have several email addresses associated to him/her...the problem is how to do this correctly...as you can see from my code above, the customer foreign key field has to be after the customer class, but the email address foreign key field has to be after the EmailAddress class...how do I sort out this issue?
There is a serious logic flaw here - ForeignKey from Customer to Email would mean that each customer has only one email. You would want to skip that foreignkey alltogether:
class Email(models.Model):
customer = models.ForeignKey(Customer, related_name='email_addresses')
then simply do customer.email_addresses to get a list of all emails. You dont need another ForeignKey, django uses relationships defined in one model (unlike RoR and other MVC frameworks)
I don't see why you want to use a ForeignKey in EmailAddress.
Extract from Python web development with Django:
Foreign keys are generally used to
define one-to-many (or many-to-one)
relationships.
In the next example a Book has a single Author and an Author can have many Books.
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(Author)
Just add single-quotes around Customer:
class EmailAddress(models.Model):
customer = models.ForeignKey('Customer')
email_address = models.CharField(max_length=200)
def __unicode__(self):
return self.email_address
Menda's answer is correct. There isn't really an ordering problem because the Customer model doesn't need a ForeignKey field. Just remove that and flip the order in which the classes are defined.
class Customer(models.Model):
pass
class EmailAddress(models.Model):
customer = models.ForeignKey(Customer)
email_address = models.CharField(max_length=200)
There's also a Django email field you can use. See Django EmailField. Just wanted to mention that in case it could add value to you application.