【发布时间】:2019-11-10 09:13:26
【问题描述】:
我正在处理具有多个 OneToOne 和 OneToMany 关系的模型的项目。主模型 Listing 有 4 个其他模型引用它,其中一个 OneToOne 模型取决于类型。另一个模型ListingImages 模型与Listing 模型具有OneToMany 关系。因此,我想传递来自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 和 Event 的其他数据并获取单个图像时遇到了麻烦。
【问题讨论】:
-
我可能遗漏了一些东西,但你为什么要这样做?你可以简单地做
context = {'listings': listings},就是这样。然后您像在模板上所做的那样遍历该列表。无论是在列表实例中的任何内容,您都可以访问它。 -
@Higor,我将如何使用您的方法从模板中获取图像?
-
与您在视图中所做的相同,但现在在模板上。
listing.listingimages_set.all基本上你会看那些 -
这是在 Django 中正确的做法吗?对大型数据库数据有影响吗?
-
嗯通过再次阅读您的代码,您在模板上有很多 if/else。你知道你会看到什么类型吗?如果是这样,您可以在此处公开过滤
标签: python django dictionary django-templates django-views