Django-views Custom filter - django

If having different books stored in django database, each book has a date in which it was added to the database. Is their a way of filtering books written by a certain author that was within a date range only using django views?

Not sure what you mean by only django views, I assume you want to use querysets. Your question is poorly written - read this.
class Book(models.Model):
title = models.CharField(max_length=200)
date = models.DateTimeField()
author = models.ForeignKey(Author)
class Author(models.Model):
name = models.CharField(max_length=200)
And Queryset would be something like this.
books = Book.objects.filter(author__name=authors_name,
date__range=["2011-01-01", "2011-01-31"])

Related

Django ManyToMany model: unable to access one relation from the other

My models.py:
class Author(models.Model):
name = models.CharField(max_length=100)
books = models.ManyToManyField(
"Book", related_name="books", blank=True
)
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ManyToManyField(Author)
In Django admin I first created an instance of Author, without assigning him any Book:
Then I created a new Book and assigned Leo Tolstoy as theAuthor:
In Django shell, I am able to access the Book's Author:
>>> Book.objects.filter(title="War and Peace").first().author.first()
<Author: Leo Tolstoy>
But I'm unable to access the Author's Books:
>>> Author.objects.filter(name="Leo Tolstoy").first().books.all()
<QuerySet []>
The book isn't assigned in the Admin view either:
I would like to access the Author's Books as well as for the Books
to show in the Author's Admin view.
You only need one ManyToManyField. You should also pass "books" as the related_name on Book.authors as this is the name Django will use for the many-to-many manager attribute it automatically adds to Author instances.
See the example in the Django docs for more info.
When a ManyToManyField is created on both sides of a relation, Django is creating two associative tables between the book and author tables under the hood. Changes to one table don't affect the other.
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(
Author, related_name="books", blank=True
)
I suggest you do this:
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ManyToManyField(Author, related_name="books",blank=True)
You need one ManyToManyField, then django will create two associative tables between the book and author tables. Changes to one table will not affect the other. You can see in the django documentation about many to many relationships. I have removed your books field in my answer because you have created an instance of your Author but you did not assign his 'book' and you have created a Book instance with giving title and author in your Book model. So so that any of your data won't be deleted. I also added related_name to your author field in your Book model because when you try to get the books related to the author (for example "Loe Tolstoy") you can get by this:
Author.objects.get(name="Leo Tolstoy").books.all()

How to Query Django ManyToMany Relationship

Please I need help with getting the result of querying my ManyToMany fields.
Basically I have the following models:
class Book(models.Model):
title = models.CharField(max_length=50)
authors = models.ManyToManyField(Author)
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
How should I query my book model to show all the authors of each book, based on the book_id and without the book_id, and how to query all the books that were written by one author?
I have tried to follow the Docs where Pizza and Topping but I'm not getting it, so thanks in advance friends and have a good day.
To get all the authors given a book you just do:
my_book.authors.all()
The second query is much more complicated: you need to use annotations to get the count of authors for each book, and filter on those whose count is one:
from django.db.models import Count
Book.objects.annotate(author_count=Count('authors')).filter(author_count=1)
For getting all the authors of a book using ManyToManyField you should use related_name attribute of your Book. authors field. ex: authors = models.ManyToManyField(Author, related_name="Books").
And then the query is my_author.books.all() which is syntactic sugar of my_author.book_set.all()

Django QuerySet to return unique objects in ManyToMany fields

Given the following models:
class Author(models.Model):
name = models.CharField()
class Book(models.Model):
title = models.CharField()
published_year = models.PositiveIntegerField()
authors = models.ManyToManyField(Author)
Let's say I want to get all of the authors who have authored a book published in the year 2008. I can do the following:
Book.objects.filter(published_year=2008).values_list('authors__name').distinct()
That'll get me a list of authors - almost exactly what I want, except that instead of just the names, I want the Author objects. I can achieve that somewhat by doing this:
authors = []
for b in Book.objects.filter(published_year=2008):
for a in b.authors.all():
if a not in authors:
authors.append(a)
But that seems totally unnecessary. Is it possible to get the QuerySet to do that work for me? Thanks!
Just use backward relationship
Author.objects.filter(book__published_year=2008).all()
From Django docs
Reverse m2m queries are supported (i.e., starting at the table that
doesn’t have a ManyToManyField):

Django: All objects AND all M2M related fields in one query

Let's say I have these:
class Publication(models.Model):
title = models.CharField(max_length=128)
author = models.ManyToManyField(Author, through='Authorship')
class Author(models.Model):
first_name = models.CharField(db_index=True, max_length=64)
last_name = models.CharField(db_index=True, max_length=64)
How can I get ALL the publications AND their author(s) in one query. I want to list each publication and its authors on a page.
But I don't want to hit the authors table for every publication.
The only way I know to do it is with select_related in the view and authorship_set.all() on the template. But that's one query for every publication. I could easily do it with raw sql, but that's yucky.
*BTW, I'm using the through model because I have to keep some extra data in there, like author_display_order.
EDIT:
Turns out authorship_set was doing all the querying.
When I run it this way from console only one query gets fired:
pubs = Publication.objects.all().prefetch_related('author')
for p in pubs:
print p.title
for a in p.author.all():
print a.last_name

Django fetch all relations

I have an app with a similar structure as this snippet
class Blog(models.Model):
name = models.CharField(max_length=25)
class Category(models.Model):
name = models.CharField(max_length=25)
blog = models.ForeignKey(Blog)
class Entry(models.Model):
title = models.CharField(max_length=25)
category = models.ForeignKey(Category)
What is the most generic way, that i will be able to use in other apps to fetch all blogs with their category and entries?
I thought about creating a manager for the Blog model, that can fetch all the Categories for that blog, but it's hardcoding the model names
class BlogManager(models.Manager):
def categories(self):
return Category.objects.filter(blog=self)
Any suggestions?
What you want is a Select Related. It returns a QuerySet that will automatically "follow" foreign-key relationships, selecting that additional related-object data when it executes its query. Your query for Blogs would look something like:
Blog.objects.select_related().filter( something )
or
Blog.objects.select_related().get( something )
Why not use a standard way?
Filter using Blog's PK with FK relation.
Category.objects.filter(blog__pk=self.pk)