Как вызвать два поля из одной модели в Django View
У меня есть модель, и я хочу отобразить два поля из нее в одном представлении. Затем отобразить их в шаблоне деталей. Но результат возвращает пустоту в шаблоне. Каков лучший способ сделать это?
моя модель:
class Book(models.Model):
class Meta :
verbose_name_plural = 'Books'
category = models.ForeignKey(Categorie,on_delete=models.CASCADE,null=True,
related_name="apps")
book_slug = models.SlugField(blank=True,allow_unicode=True,editable=True)
book_title = models.CharField(max_length=50 , null=True)
book_picture = models.ImageField(upload_to='imgs' , null=True)
book_description = RichTextUploadingField(null=True,blank=True)
book_size = models.CharField(max_length=20 , null=True)
book_created_at = models.DateField(auto_now_add=True)
book_updated_at = models.DateField(auto_now=True)
book_auther = models.CharField(max_length=100 , null=True)
мои взгляды:
def book_details(requset ,book_slug):
book = get_object_or_404 (Book, book_slug = book_slug)
try :
book = Book.objects.filter(book_slug = book_slug)
except :
raise Http404
similar_books = Book.objects.filter(book_auther = book_slug) ------ >>> Here is my query
context ={
'book' :book,
'similar_books':similar_books,
}
return render( requset,'book.html',context)
мой шаблон:
<div class="row">
{% for b in book %}
<div>
<img src="{{ b.book_picture.url }}" class="Rounded circle Image" height="150"
width="150" alt="">
<a href="{{b.get_absolute_url}}">{{b.book_title}}</a>
</div>
{% endfor %}
</div>
<div class="row">
{% for sb in similar_books%}
<div>
<img src="{{ sb.book_picture.url }}" class="Rounded circle Image" height="150"
width="150" alt="">
<a href="{{sb.get_absolute_url}}">{{sb.book_title}}</a>
</div>
{% endfor %}
</div>
Прежде всего
book = get_object_or_404 (Book, book_slug = book_slug)
это метод get, который возвращает единственный экземпляр book, если он найден (не Queryset)
Тогда вы повторяете одно и то же, и, на мой взгляд, этот кусок кода можно отбросить, поскольку он дублирует строку выше
try :
book = Book.objects.filter(book_slug = book_slug)
except :
raise Http404
Тогда в шаблоне не нужно циклиться на book: это единичный объект, а не перечислимый - queryset, поэтому следует написать
<div class="row">
<div>
<img src="{{ book.book_picture.url }}" class="Rounded circle Image" height="150"
width="150" alt="">
<a href="{{book.get_absolute_url}}">{{book.book_title}}</a>
</div>
</div>
Что касается вашего второго запроса, то на основе данных вашего примера вы не можете извлечь данные с помощью фильтра, а должны обработать их таким образом:
similar_books = []
for sb in Book.objects.all():
if sb.book_author in book_slug:
similar_books.append(sb)
Вместо использования filter(book_slug = book_slug) используйте __icontains с объектом Q (используйте каждое слово в book_slug, чтобы получить максимум похожих записей). например: -
slugs = book_slug.split() # which will give list of slugs
condition = Q(book_slug__icontains=slugs[0])
for slug in slugs[1:]:
condition &= Q(book_slug__icontains=slug)
Book.objects.filter(condition).all()
если вы хотите устранить явный цикл, как описано выше, вы можете использовать оператор для этого.
import operator
slug_conditions = reduce(operator.and_, [Q(book_slug__icontains=slug) for slug in book_slug])
queryset = Profile.objects.filter(slug_conditions).all()
Попробуйте получить список книг с одним автором по первому запросу и во втором запросе отфильтровать все книги с теми же авторами
book = Book.objects.filter(book_slug=book_slug)
authors = book.values_list('book_auther').distinct()
similar_books = Book.objects.filter(book_auther__in=authors)
Если вы хотите исключить книгу из аналогичных книг
book = Book.objects.filter(book_slug=book_slug)
authors = book.values_list('book_auther').distinct()
book_ids = book.values_list('id', flat=True)
similar_books = Book.objects.filter(book_auther__in=authors).exclude('id__in'=book_ids)