CUSTOM MANAGER
class AuthorManager(models.Manager):
def get_authors_by_article_count(self):
return self.annotate(
num_articles=models.Count('articles')
).order_by(
'-num_articles', 'email'
)
QUERIES 1.1 Q
from main_app.models import Author, Article, Review
from django.db.models import Q
def get_authors(search_name=None, search_email=None):
if search_name is None and search_email is None:
return ""
query_name = Q(full_name__icontains=search_name)
query_email = Q(email__icontains=search_email)
if search_name and search_email:
query = query_name & query_email
elif search_name:
query = query_name
else:
query = query_email
authors = Author.objects.filter(query).order_by('-full_name')
if not authors:
return ""
result = []
for author in authors:
result.append(f"Author: {author.full_name}, email: {author.email}, status: {'Banned' if author.is_banned else 'Not Banned'}")
return "\n".join(result)
QUERIES 1.2 AND 1.3
def get_top_publisher():
top_publisher = Author.objects.annotate(
num_articles=Count("articles")
).order_by(
'-num_articles', 'email'
).first()
if top_publisher is None or top_publisher.num_articles == 0:
return ""
return f"Top Author: {top_publisher.full_name} with {top_publisher.num_articles} published articles."
def get_top_reviewer():
top_reviewer = Author.objects.annotate(
num_reviews=Count('reviews')
).order_by(
'-num_reviews', 'email'
).first()
if top_reviewer is None or top_reviewer.num_reviews == 0:
return ''
return f"Top Reviewer: {top_reviewer.full_name} with {top_reviewer.num_reviews} published reviews."
QUERIES 2.1
def get_latest_article():
latest_article = Article.objects.prefetch_related('authors', 'reviews').order_by('-published_on').first()
if latest_article is None:
return ''
author_names = ', '.join(author.full_name for author in latest_article.authors.all().order_by('full_name'))
num_reviews = latest_article.reviews.count()
avg_rating = sum([r.rating for r in latest_article.reviews.all()]) / num_reviews if num_reviews else 0.0
return (f"The latest article is: {latest_article.title}."
f" Authors: {author_names}. Reviewed: {num_reviews} times."
f" Average Rating: {avg_rating:.2f}.")
QUERIES 2.2
def get_top_rated_article():
top_article = Article.objects.annotate(
average_rating=Avg('reviews__rating') # СРЕДИЯ РЕЙТИНГ НА ВСЯКА ЕДНА СТАРИЯ
).order_by(
'-average_rating', 'title' # СОРТИРАМЕ В НИЗХОДЯЩ РЕД ПО СРЕДЕН РЕЙТИНГ И ЗАГЛАВИЕ НА СТАТИЯТА
).first() # ВЗИМАМЕ ПЪРВАТА СТАТИЯ, Т.Е ТАЗИ С НАЙ-ВИСОК СРЕДЕН РЕЙТИНГ
num_reviews = top_article.reviews.count()
if top_article is None or num_reviews == 0:
return ''
avg_rating = top_article.average_rating
return (f"The top-rated article is: {top_article.title},"
f" with an average rating of {avg_rating:.2f},"
f" reviewed {num_reviews} times.")
QUERIES 2.3
def ban_author(email=None):
author_banned = Author.objects.prefetch_related('reviews').filter(email__exact=email).first() # използваме
# prefetch_related защото по надолу ни трябва reviews
if author_banned is None or email is None:
return "No authors banned."
num_reviews = author_banned.reviews.count()
author_banned.is_banned = True
author_banned.save()
author_banned.reviews.all().delete()
return f"Author: {author_banned.full_name} is banned! {num_reviews} reviews deleted."