我正在一个项目中使用具有多个OneToOne
和OneToMany
关系的模型。主要模型Listing
有4个其他模型,其中根据类型将其引用为OneToOne
模型。另一个模型ListingImages
模型与OneToMany
模型具有Listing
关系。因此,我想将Listing
模型的数据以及ListingImages
和其他4个模型的其他任何相关数据传递给模板。为了清楚地理解这一点,请参见附件中的代码:
models.py
from django.db import models
from django.contrib.auth.models import User
from location_field.models.plain import PlainLocationField
from PIL import Image
from slugify import slugify
from django.utils.translation import gettext as _
from django.core.validators import MaxValueValidator, MinValueValidator
from listing_admin_data.models import (Service, SubscriptionType, PropertySubCategory,
PropertyFeatures, VehicleModel, VehicleBodyType, VehicleFuelType,
VehicleColour, VehicleFeatures, BusinessAmenities, Currency
)
def current_year():
return datetime.date.today().year
def max_value_current_year(value):
return MaxValueValidator(current_year())(value)
class Listing(models.Model):
listing_type_choices = [('P', 'Property'), ('V', 'Vehicle'), ('B', 'Business/Service'), ('E', 'Events')]
listing_title = models.CharField(max_length=255)
listing_type = models.CharField(choices=listing_type_choices, max_length=1, default='P')
status = models.BooleanField(default=False)
featured = models.BooleanField(default=False)
city = models.CharField(max_length=255, blank=True)
location = PlainLocationField(based_fields=['city'], zoom=7, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
expires_on = models.DateTimeField(auto_now=True)
created_by = models.ForeignKey(User,
on_delete=models.CASCADE, editable=False, null=True, blank=True
)
listing_owner = models.ForeignKey(User,
on_delete=models.CASCADE, related_name='list_owner'
)
def __str__(self):
return self.listing_title
def get_image_filename(instance, filename):
title = instance.listing.listing_title
slug = slugify(title)
return "listings_pics/%s-%s" % (slug, filename)
class ListingImages(models.Model):
listing = models.ForeignKey(Listing, on_delete=models.CASCADE)
image_url = models.ImageField(upload_to=get_image_filename,
verbose_name='Listing Images')
main_image = models.BooleanField(default=False)
class Meta:
verbose_name_plural = "Listing Images"
def __str__(self):
return f'{self.listing.listing_title} Image'
class Subscriptions(models.Model):
subscription_type = models.ForeignKey(SubscriptionType, on_delete=models.CASCADE)
subscription_date = models.DateTimeField(auto_now_add=True)
subscription_amount = models.DecimalField(max_digits=6, decimal_places=2)
subscribed_by = models.ForeignKey(User, on_delete=models.CASCADE)
duration = models.PositiveIntegerField(default=0)
listing_subscription = models.ManyToManyField(Listing)
updated_at = models.DateTimeField(auto_now=True)
status = models.BooleanField(default=False)
class Meta:
verbose_name_plural = "Subscriptions"
def __str__(self):
return f'{self.listing.listing_title} Subscription'
class Property(models.Model):
sale_hire_choices = [('S', 'Sale'), ('R', 'Rent')]
fully_furnished_choices = [('Y', 'Yes'), ('N', 'No')]
listing = models.OneToOneField(Listing, on_delete=models.CASCADE)
sub_category = models.ForeignKey(PropertySubCategory, on_delete=models.CASCADE)
for_sale_rent = models.CharField(choices=sale_hire_choices, max_length=1, default=None)
bedrooms = models.PositiveIntegerField(default=0)
bathrooms = models.PositiveIntegerField(default=0)
rooms = models.PositiveIntegerField(default=0)
land_size = models.DecimalField(max_digits=10, decimal_places=2)
available_from = models.DateField()
car_spaces = models.PositiveIntegerField(default=0)
fully_furnished = models.CharField(choices=fully_furnished_choices, max_length=1, default=None)
desc = models.TextField()
property_features = models.ManyToManyField(PropertyFeatures)
price = models.DecimalField(max_digits=15, decimal_places=2)
currency = models.ForeignKey(Currency, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name_plural = "Properties"
def __str__(self):
return f'{self.listing.listing_title}'
class Vehicle(models.Model):
sale_hire_choices = [('S', 'Sale'), ('H', 'Hire')]
transmission_choices = [('A', 'Automatic'), ('M', 'Manual')]
drive_choices = [('L', 'Left'), ('R', 'Right')]
condition_choices = [('L', 'Locally Used'), ('F', 'Foreign Used'), ('N', 'Brand New')]
interior_choices = [('C', 'Cloth'), ('L', 'Leather'), ('O', 'Other')]
listing = models.OneToOneField(Listing, on_delete=models.CASCADE)
for_sale_hire = models.CharField(choices=sale_hire_choices, max_length=1, default=None)
# year_of_manufacture = models.PositiveIntegerField()
year_of_manufacture = models.IntegerField(_('year'), validators=[MinValueValidator(1900), max_value_current_year])
engine_capacity = models.PositiveIntegerField()
model = models.ForeignKey(VehicleModel, on_delete=models.CASCADE)
description = models.TextField()
transmission = models.CharField(choices=transmission_choices, max_length=1, default=None)
drive = models.CharField(choices=drive_choices, max_length=1, default=None)
current_millage = models.PositiveIntegerField(validators=[MinValueValidator(0)])
condition = models.CharField(choices=condition_choices, max_length=1, default=None)
interior = models.CharField(choices=interior_choices, max_length=1, default=None)
number_of_doors = models.PositiveIntegerField(default=0)
body_type = models.ForeignKey(VehicleBodyType, on_delete=models.CASCADE)
fuel_type = models.ForeignKey(VehicleFuelType, on_delete=models.CASCADE)
colour = models.ForeignKey(VehicleColour, on_delete=models.CASCADE)
vehicle_features = models.ManyToManyField(VehicleFeatures)
asking_price = models.DecimalField(max_digits=10, decimal_places=2)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return f'{self.listing.listing_title}'
class Business(models.Model):
listing = models.OneToOneField(Listing, on_delete=models.CASCADE)
service = models.ForeignKey(Service, on_delete=models.CASCADE)
business_name = models.CharField(max_length=100)
slogan = models.CharField(max_length=255)
desc = models.TextField()
website_address = models.CharField(max_length=50)
email_address = models.EmailField(max_length=50)
business_amenities = models.ManyToManyField(BusinessAmenities)
contact = models.CharField(max_length=15)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name_plural = "Businesses"
def __str__(self):
return f'{self.listing.listing_title}'
views.py
from django.shortcuts import render
from listings.models import Listing
def index(request):
listings = Listing.objects.filter(status=True).prefetch_related("listingimages_set").all()
context = {
'listing': [
{
'title': listing.listing_title,
'listing_type': listing.listing_type,
'featured': listing.featured,
'city': listing.city,
'images': list(listing.listingimages_set.all()),
} for listing in listings
]
}
return render(request, 'base/index.html', context)
index.html
<!--Featured listings section start-->
<div class="property-section section pt-100 pt-lg-80 pt-md-70 pt-sm-60 pt-xs-50 pb-60 pb-lg-40 pb-md-30 pb-sm-20 pb-xs-10">
<div class="container">
<!--Section Title start-->
<div class="row">
<div class="col-md-12 mb-60 mb-xs-30">
<div class="section-title center">
<h1>New Listings</h1>
</div>
</div>
</div>
<!--Section Title end-->
<div class="row">
{% for listing in listings %}
{% if listing.listing_type == 'P' %}
<!--Listing start-->
<div class="property-item col-lg-3 col-md-6 col-12 mb-40">
<div class="property-inner">
<div class="image">
<a href="single-properties.html"><img src="{% static 'base/assets/images/property/property-1.jpg' %}" alt=""></a>
<ul class="property-feature">
<li>
<span class="area"><img src="{% static 'base/assets/images/icons/area.png' %}" alt="">{{ listing.property.land_size }} SqFt</span>
</li>
<li>
<span class="bed"><img src="{% static 'base/assets/images/icons/bed.png' %}" alt="">{{ listing.property.bedrooms }}</span>
</li>
<li>
<span class="bath"><img src="{% static 'base/assets/images/icons/bath.png' %}" alt="">{{ listing.property.bathrooms }}</span>
</li>
<li>
<span class="parking"><img src="{% static 'base/assets/images/icons/parking.png' %}" alt="">{{ listing.property.car_spaces }}</span>
</li>
</ul>
</div>
<div class="content">
<div class="left">
<h3 class="title"><a href="single-properties.html">{{ listing.title }}</a></h3>
<span class="location"><img src="{% static 'base/assets/images/icons/marker.png' %}" alt="">{{ listing.city }}</span>
</div>
<div class="right">
<div class="type-wrap">
<span class="price">Kshs {{ listing.property.price }}</span>
<span class="type">{{ listing.property.get_for_sale_rent_display }}</span>
</div>
</div>
</div>
</div>
</div>
<!--Listing end-->
{% elif listing.listing_type == 'V' %}
<!--Listing start-->
<div class="property-item col-lg-3 col-md-6 col-12 mb-40">
<div class="property-inner">
<div class="image">
<a href="single-properties.html"><img src="{% static 'base/assets/images/property/property-1.jpg' %}" alt=""></a>
<ul class="property-feature">
<li>
<span class="area"><img src="{% static 'base/assets/images/icons/area.png' %}" alt="">550 SqFt</span>
</li>
<li>
<span class="bed"><img src="{% static 'base/assets/images/icons/bed.png' %}" alt="">6</span>
</li>
<li>
<span class="bath"><img src="{% static 'base/assets/images/icons/bath.png' %}" alt="">4</span>
</li>
<li>
<span class="parking"><img src="{% static 'base/assets/images/icons/parking.png' %}" alt="">3</span>
</li>
</ul>
</div>
<div class="content">
<div class="left">
<h3 class="title"><a href="single-properties.html">{{ listing.listing_title }}</a></h3>
<span class="location"><img src="{% static 'base/assets/images/icons/marker.png' %}" alt="">{{ listing.city }}</span>
</div>
<div class="right">
<div class="type-wrap">
<span class="price">$550<span>M</span></span>
<span class="type">For Rent</span>
</div>
</div>
</div>
</div>
</div>
<!--Listing end-->
{% elif listing.listing_type == 'B' %}
<!--Listing start-->
<div class="property-item col-lg-3 col-md-6 col-12 mb-40">
<div class="property-inner">
<div class="image">
<a href="single-properties.html"><img src="{% static 'base/assets/images/property/property-1.jpg' %}" alt=""></a>
<ul class="property-feature">
<li>
<span class="area"><img src="{% static 'base/assets/images/icons/area.png' %}" alt="">550 SqFt</span>
</li>
<li>
<span class="bed"><img src="{% static 'base/assets/images/icons/bed.png' %}" alt="">6</span>
</li>
<li>
<span class="bath"><img src="{% static 'base/assets/images/icons/bath.png' %}" alt="">4</span>
</li>
<li>
<span class="parking"><img src="{% static 'base/assets/images/icons/parking.png' %}" alt="">3</span>
</li>
</ul>
</div>
<div class="content">
<div class="left">
<h3 class="title"><a href="single-properties.html">{{ listing.listing_title }}</a></h3>
<span class="location"><img src="{% static 'base/assets/images/icons/marker.png' %}" alt="">{{ listing.city }}</span>
</div>
<div class="right">
<div class="type-wrap">
<span class="price">$550<span>M</span></span>
<span class="type">For Rent</span>
</div>
</div>
</div>
</div>
</div>
<!--Listing end-->
{% elif listing.listing_type == 'E' %}
<!--Listing start-->
<div class="property-item col-lg-3 col-md-6 col-12 mb-40">
<div class="property-inner">
<div class="image">
<a href="single-properties.html"><img src="{% static 'base/assets/images/property/property-1.jpg' %}" alt=""></a>
<ul class="property-feature">
<li>
<span class="area"><img src="{% static 'base/assets/images/icons/area.png' %}" alt="">550 SqFt</span>
</li>
<li>
<span class="bed"><img src="{% static 'base/assets/images/icons/bed.png' %}" alt="">6</span>
</li>
<li>
<span class="bath"><img src="{% static 'base/assets/images/icons/bath.png' %}" alt="">4</span>
</li>
<li>
<span class="parking"><img src="{% static 'base/assets/images/icons/parking.png' %}" alt="">3</span>
</li>
</ul>
</div>
<div class="content">
<div class="left">
<h3 class="title"><a href="single-properties.html">{{ listing.listing_title }}</a></h3>
<span class="location"><img src="{% static 'base/assets/images/icons/marker.png' %}" alt="">{{ listing.city }}</span>
</div>
<div class="right">
<div class="type-wrap">
<span class="price">$550<span>M</span></span>
<span class="type">For Rent</span>
</div>
</div>
</div>
</div>
</div>
<!--Listing end-->
{% endif %}
{% endfor %}
</div>
</div>
</div>
<!--Featured listings section end-->
为此,Listing
可以是Property
,Vehicle
,Business
或Event
。每个Listing
都有几个图像,但是对于这种情况,我只希望传递从数据库中首先检索到的单个图像。
我的主要问题是在上下文部分。我只能从模板中获取Listing
实例并获取其他模型的其他详细信息,但是从研究中发现,不建议在Django中进行实践。因此,如何获取Listing
,Property
,Vehicle
或Business
的详细信息,并获取Event
并将其传递给通过字典的模板让我感到非常困惑。
我尝试使用显示的代码,但是在合并来自single image
,Property
,Vehicle
和Business
的其他数据时遇到了麻烦图片。
答案 0 :(得分:0)
根据@Higor的建议,这就是我对view.py所做的:
context = {
'listings': Listing.objects.filter(status=True).order_by('-created_at').prefetch_related("listingimages_set")
}
return render(request, 'base/index.html', context)
然后在模板中,我通过以下方式继续访问详细信息:
{% for listing in listings %}
{% if listing.listing_type == 'P' %}
{{ listing.listingimages_set.first.image_url.url }} #accessing a single image
{{ listing.listing_title }}
{{ listing.property.land_size }}
{% elif listing.listing_type == 'V' %}
....
{% elif listing.listing_type == 'B' %}
....
{% endif %}
{% endfor %}
这更加整洁了,在访问图像列表时使用first
可以为我节省很多时间。