如果我有一个项目的单独模型和与该项目相关的图像的单独模型,我如何将它们组合到查询中?
If I have a separate models for an item and a separate model for the images relating to that item, how can I combine these into a query?
我正在尝试在卡片视图中显示我的查询集中的项目。我有一个 Item 模型和一个单独的 ItemImage 模型,以允许为单个项目上传多个图像。每个图像还有一个 属性 is_primary 来确定它是否是将显示在动态生成的卡片中的图像。
我已成功显示来自我的项目模型查询集的项目详细信息。但是,我很难理解如何将 itemimage.url 属性与我传递到模板中的 all_items 上下文结合起来。如何确保我的图像查询集中的图像与分配给它们的项目的 pk 相匹配,并且也是该项目的主要照片?
views.py
from django.shortcuts import render, redirect
# Create your views here.
from django.http import HttpResponse
from django.contrib.auth.forms import UserCreationForm
from django.contrib import messages
from .models import Item, ItemImage
def home(request):
all_items = Item.objects.all()
item_images = ItemImage.objects.all() ItemImage.objects.filter(is_primary=True)
context = {'items': all_items}
return render(request,'items/home.html',context)
models.py
from django.db import models
from django.utils import timezone
from decimal import Decimal
# Create your models here.
class Item(models.Model):
name = models.CharField(max_length=70)
date_added = models.DateTimeField(default=timezone.now)
price = models.DecimalField(max_digits=9, decimal_places=2, default=Decimal('0.00'))
description = models.CharField(max_length=300)
def __str__(self):
return self.name
class ItemImage(models.Model):
url = models.CharField(max_length=2000)
is_primary = models.BooleanField(default=False)
item = models.ForeignKey(Item, on_delete=models.CASCADE)
home.html
{% extends "base.html" %}
{% block content %}
<div class="content-section d-flex flex-row">
{% if items%}
{% for item in items %}
<div class="card" style="width: 18rem;">
<img class="card-img-top" src="{{item.image_ur}}" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">{{item.name}}</h5>
<p class="card-text">{{item.description}}</p>
<a href="#" class="btn btn-primary">Add to cart</a>
</div>
</div>
{% endfor %}
{% else %} <h2> No items available. </h2>
{% endif %}
</div>
{% endblock content %}
您可以使用 Prefetch
object [Django-doc] 为每个 Item
获取主 ItemImage
s,其中:
from django.db.models import Prefetch
def home(request):
all_items = Item.objects.prefetch_related(
Prefetch(
'itemimage_set',
ImageItem.objects.<b>filter(is_primary=True)</b>
to_attr='primary_images'
)
)
context = {'items': all_items}
return render(request,'items/home.html',context)
在您看来,您可以使用 item.primary_images
获取与 item
相关的主要图像,因此:
<div class="content-section d-flex flex-row">
{% for item in items %}
<div class="card" style="width: 18rem;">
{% <b>for img in item.primary_images</b> %}
<img class="card-img-top" src="{{ img.url }}" alt="Card image cap">
{% <b>endfor</b> %}
<div class="card-body">
<h5 class="card-title">{{item.name}}</h5>
<p class="card-text">{{item.description}}</p>
<a href="#" class="btn btn-primary">Add to cart</a>
</div>
</div>
{% empty %}
<h2> No items available. </h2>
{% endfor %}
</div>
Note: Django has a {% for … %} … {% empty %} … {% endfor %}
template tag [Django-doc]
to make rendering a message when a collection is empty more convenient.
预取解决方案对我有用。我尝试的另一种解决方案是进行原始查询。可能有一个更简洁的基于模型的解决方案,但现在原始 SQL 对我来说更具可读性。
def home(request):
all_items = Item.objects.raw("SELECT items_item.id, items_item.name, items_item.description, items_item.price, items_item.date_added, items_itemimage.url AS imgurl FROM items_item LEFT JOIN items_itemimage ON items_item.id = items_itemimage.item_id WHERE items_itemimage.is_primary = true ORDER BY date_added DESC")
context = {'items': all_items}
return render(request,'items/home.html',context)
我正在尝试在卡片视图中显示我的查询集中的项目。我有一个 Item 模型和一个单独的 ItemImage 模型,以允许为单个项目上传多个图像。每个图像还有一个 属性 is_primary 来确定它是否是将显示在动态生成的卡片中的图像。
我已成功显示来自我的项目模型查询集的项目详细信息。但是,我很难理解如何将 itemimage.url 属性与我传递到模板中的 all_items 上下文结合起来。如何确保我的图像查询集中的图像与分配给它们的项目的 pk 相匹配,并且也是该项目的主要照片?
views.py
from django.shortcuts import render, redirect
# Create your views here.
from django.http import HttpResponse
from django.contrib.auth.forms import UserCreationForm
from django.contrib import messages
from .models import Item, ItemImage
def home(request):
all_items = Item.objects.all()
item_images = ItemImage.objects.all() ItemImage.objects.filter(is_primary=True)
context = {'items': all_items}
return render(request,'items/home.html',context)
models.py
from django.db import models
from django.utils import timezone
from decimal import Decimal
# Create your models here.
class Item(models.Model):
name = models.CharField(max_length=70)
date_added = models.DateTimeField(default=timezone.now)
price = models.DecimalField(max_digits=9, decimal_places=2, default=Decimal('0.00'))
description = models.CharField(max_length=300)
def __str__(self):
return self.name
class ItemImage(models.Model):
url = models.CharField(max_length=2000)
is_primary = models.BooleanField(default=False)
item = models.ForeignKey(Item, on_delete=models.CASCADE)
home.html
{% extends "base.html" %}
{% block content %}
<div class="content-section d-flex flex-row">
{% if items%}
{% for item in items %}
<div class="card" style="width: 18rem;">
<img class="card-img-top" src="{{item.image_ur}}" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">{{item.name}}</h5>
<p class="card-text">{{item.description}}</p>
<a href="#" class="btn btn-primary">Add to cart</a>
</div>
</div>
{% endfor %}
{% else %} <h2> No items available. </h2>
{% endif %}
</div>
{% endblock content %}
您可以使用 Prefetch
object [Django-doc] 为每个 Item
获取主 ItemImage
s,其中:
from django.db.models import Prefetch
def home(request):
all_items = Item.objects.prefetch_related(
Prefetch(
'itemimage_set',
ImageItem.objects.<b>filter(is_primary=True)</b>
to_attr='primary_images'
)
)
context = {'items': all_items}
return render(request,'items/home.html',context)
在您看来,您可以使用 item.primary_images
获取与 item
相关的主要图像,因此:
<div class="content-section d-flex flex-row">
{% for item in items %}
<div class="card" style="width: 18rem;">
{% <b>for img in item.primary_images</b> %}
<img class="card-img-top" src="{{ img.url }}" alt="Card image cap">
{% <b>endfor</b> %}
<div class="card-body">
<h5 class="card-title">{{item.name}}</h5>
<p class="card-text">{{item.description}}</p>
<a href="#" class="btn btn-primary">Add to cart</a>
</div>
</div>
{% empty %}
<h2> No items available. </h2>
{% endfor %}
</div>
Note: Django has a
{% for … %} … {% empty %} … {% endfor %}
template tag [Django-doc] to make rendering a message when a collection is empty more convenient.
预取解决方案对我有用。我尝试的另一种解决方案是进行原始查询。可能有一个更简洁的基于模型的解决方案,但现在原始 SQL 对我来说更具可读性。
def home(request):
all_items = Item.objects.raw("SELECT items_item.id, items_item.name, items_item.description, items_item.price, items_item.date_added, items_itemimage.url AS imgurl FROM items_item LEFT JOIN items_itemimage ON items_item.id = items_itemimage.item_id WHERE items_itemimage.is_primary = true ORDER BY date_added DESC")
context = {'items': all_items}
return render(request,'items/home.html',context)