面对 Django 模板和 Django 模型的 'if' 语句的问题

facing problems with 'if' statement for Django templates and Django Models

我一直在一个价格比较网站上工作,但是当我尝试为不同的产品编写 if 语句以便它们显示自己的详细信息而不是显示每个产品中的所有详细信息字段时,我遇到了一个问题。

views.py

from django.shortcuts import render, get_object_or_404

from .models import Category, Product, Brand, Smartphone_detail

def index(request):
    products = Product.objects.all()
    return render(request, 'core/home.html', {'products': products})

def categories(request):
    return {
        'categories': Category.objects.all()
    }

def product_detail(request, slug):
    product = get_object_or_404(Product, slug=slug, in_stock=True)
    return render(request, 'core/products/detail.html', {'product': product})

def category_list(request, category_slug):
    category = get_object_or_404(Category, slug=category_slug)
    products = Product.objects.filter(category=category)
    return render(request, 'core/products/category.html', {'category': category, 'products': products})

models.py

from django.db import models
from django.urls import reverse
from django.db.models import Case, Value, When


class Category(models.Model):
    name = models.CharField(max_length=120, verbose_name='category name')
    slug = models.SlugField(max_length=150, verbose_name='category url')

    class Meta:
        verbose_name_plural = 'categories'

    def get_absolute_url(self):
        return reverse("core:category_list", args={self.slug})
    

    def __str__(self):
        return self.name


class Brand(models.Model):
    name = models.CharField(max_length=120, verbose_name='name of the brand')
    slug = models.SlugField(max_length=120, verbose_name='brand url')
    image = models.ImageField(upload_to='images/', verbose_name='brand image')
    description = models.TextField(verbose_name='brand moto or tagline')

    class Meta:
        verbose_name_plural = 'brands'

    def __str__(self):
        return self.name


class Smartphone_detail(models.Model):
    name = models.CharField(max_length=220, verbose_name=("product name"))
    brand = models.CharField(max_length=120, verbose_name=("product brand"))
    ram = models.IntegerField(verbose_name=("ram"))
    storage = models.IntegerField(verbose_name=("storage"))
    camera = models.CharField(verbose_name=("camera"), max_length=150)
    processor = models.CharField(verbose_name=("processor"), max_length=50)
    fingerprint = models.CharField(verbose_name=("figerprint"), max_length=50)
    battery = models.CharField(verbose_name=("battery capacity"), max_length=50)
    charger = models.CharField(verbose_name=("charger type and power"), max_length=150)
    charging_speed = models.CharField(verbose_name=("charging speed"), max_length=50)

    def __str__(self):
        return '{}'.format(self.name)


class Fashiondetail(models.Model):
    CHOICES = (
        ('XXS', '22'),
        ('XS', '24'),
        ('S', '26'),
        ('M', '28'),
        ('L', '30'),
        ('XL', '32'),
        ('XXL', '34'),
        ('XXXL', '36'),
    )
    name = models.CharField(max_length=220, verbose_name=("product name"))
    brand = models.CharField(max_length=120, verbose_name=("product brand"))
    size = models.CharField(max_length=250, choices = CHOICES)

    def __str__(self):
        return self.name

    
class Smartphone_accessory_detail(models.Model):
    TYPES = (
        ('Earphones'),
        ('Earbuds'),
        ('Headphones'),
        ('Smartwatch'),
        ('Fitness Bands'),
        ('Bluetooth Speakers'),
        ('Power Banks'),
    )
    name = models.CharField(max_length=220, verbose_name=("product name"))
    brand = models.CharField(max_length=120, verbose_name=("product brand"))
    type = models.CharField(max_length=120, verbose_name=('product type'), choices=TYPES)


class Product(models.Model):
    title = models.CharField(max_length=250, verbose_name='product name')
    slug = models.SlugField(max_length=300, verbose_name='product url')
    image = models.ImageField(upload_to='images/', verbose_name='product image')
    category = models.ManyToManyField(Category, blank=False, verbose_name='product category')
    brand = models.ManyToManyField(Brand, blank=True, verbose_name='brand name')
    price = models.DecimalField(max_digits=8,  decimal_places=2, default=000000.00, verbose_name='product price')
    in_stock = models.BooleanField(default=True, verbose_name='product availability')
    description = models.TextField(null=True, verbose_name='product description')
    smartphone_detail = models.OneToOneField(Smartphone_detail, on_delete=models.CASCADE, null=True, blank=True)
    Smartphone_accessory_detail = models.OneToOneField(Smartphone_accessory_detail, on_delete=models.CASCADE, null=True, blank=True)

    class Meta:
        verbose_name_plural = 'products'

    def get_absolute_url(self):
        return reverse('core:product_detail', args={self.slug})
    
    def __str__(self):
        return self.title

我尝试使用案例,当模型获得我想要的结果但无法弄清楚所以如果有人知道一篇很好的博客文章解释了如何使用案例,价值,何时使用 Django 数据库模型link 他们。

admin.py

from django.contrib import admin
from .models import Category, Product, Brand, Smartphone_detail, Smartphone_accessory_detail

@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
    list_display = ['name', 'slug']
    prepopulated_fields = {'slug': ('name',)}

@admin.register(Brand)
class BrandAdmin(admin.ModelAdmin):
    list_display = ['name', 'slug', 'description', 'image']
    prepopulated_fields = {'slug': ('name',)}
    
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    list_display = [
        'title', 'slug', 'price',
        'description', 'in_stock', 'image'
    ]
    prepopulated_fields = {'slug': ('title',)}

@admin.register(Smartphone_detail)
class Smartphone_detailAdmin(admin.ModelAdmin):
    list_display = [
        'name', 'brand', 'ram', 'storage',
        'camera', 'processor', 'fingerprint',
        'battery', 'charger', 'charging_speed'
    ]

@admin.register(Smartphone_accessory_detail)
class Smartphone_accessory_detailAdmin(admin.ModelAdmin):
    list_display = [
        'name', 'brand', 'type'
    ]

urls.py

from django.urls import path
from . import views

app_name = 'core'

urlpatterns = [
    path('', views.index, name='index'),
    path('product/<slug:slug>/', views.product_detail, name='product_detail'),
    path('search/<slug:category_slug>/', views.category_list, name='category_list'),
]

detail.html

{% extends '../base.html' %}

{% block title %}{{ product.title }}{% endblock title %}

{% block content %}

<div class="container-fluid">
    <div class="row">
        <div class="col-md-5">
            <img class="img-fluid mx-auto" alt={{ product.title }} src="{{ product.image.url }}"/>
        </div>
        <div class="col-md-7">
            <div class="row">
                <div class="col-md-12">
                    <h1 class="text-capitalize">{{ product.title }}</h1>
                </div>
            </div>
            <div class="row">
                <div class="col-md-12 bottom-rule">
                    <h3>&#8377;{{ product.price }}</h3>
                </div>
            </div>
            <div class="row">
                <div class="col-md-12">
                    <p>{{ product.description }}</p>
                </div>
            </div>
        </div>
    </div>
    <!-- Table for SmartphoneDetail section -->
    <table class="table">
        <tbody>
            <tr>
                <td class="fw-bold">name</td>
                <td>{{ product.smartphone_detail.name }}</td>
            </tr>
            <tr>
                <td class="fw-bold">brand</td>
                <td>{{ product.smartphone_detail.brand }}</td>
            </tr>
            <tr>
                <td class="fw-bold">ram</td>
                <td>{{ product.smartphone_detail.ram }}Gb</td>
            </tr>
            <tr>
                <td class="fw-bold">storage</td>
                <td>{{ product.smartphone_detail.storage }}Gb</td>
            </tr>
            <tr>
                <td class="fw-bold">camera</td>
                <td>{{ product.smartphone_detail.camera }}</td>
            </tr>
            <tr>
                <td class="fw-bold">processor</td>
                <td>{{ product.smartphone_detail.processor }}</td>
            </tr>
            <tr>
                <td class="fw-bold">fingerprint</td>
                <td>{{ product.smartphone_detail.fingerprint }}</td>
            </tr>
            <tr>
                <td class="fw-bold">battery</td>
                <td>{{ product.smartphone_detail.battery }}</td>
            </tr>
            <tr>
                <td class="fw-bold">charger</td>
                <td>{{ product.smartphone_detail.charger }}</td>
            </tr>
            <tr>
                <td class="fw-bold">charging speed</td>
                <td>{{ product.smartphone_detail.charging_speed }}</td>
            </tr>

        </tbody>
    </table>
</div>

{% endblock content %}

在这里,当我尝试编写 if 语句时,它停止在我的详细信息页面中呈现此 table。所以如果有人能指导我如何编写一个 if 语句,它只呈现与该产品相关的细节而不是不必要的细节。

如果产品属于智能手机类别,我想写声明,然后只显示智能手机的详细信息,而不是其他的,但我不知道如何写这个声明,因为类别是从 Django 管理面板添加的,而不是来自模型。

此问题已由 nigel222 解决,感谢您的回答。我按照他的回答得出的结论是这段代码非常适合我。

更新代码:

views.py

def product_detail(request, slug):
    product = get_object_or_404(Product, slug=slug, in_stock=True)
    is_smartphone = product.category.filter(name='smartphone').exists()
    is_fashion = product.category.filter(name='fashion').exists()
    is_accessory = product.category.filter(name='accessories').exists()
    return render(request, 'core/products/detail.html', {
        'product': product, 'is_smartphone': is_smartphone,
        'is_fashion': is_fashion, 'is_accessory': is_accessory
    })

detail.html

{% if is_smartphone %}
<table class="table">
    <tbody>
        <tr>
            <td class="fw-bold">name</td>
            <td>{{ product.smartphone_detail.name }}</td>
        </tr>
        <tr>
            <td class="fw-bold">brand</td>
            <td>{{ product.smartphone_detail.brand }}</td>
        </tr>
        <tr>
            <td class="fw-bold">ram</td>
            <td>{{ product.smartphone_detail.ram }}Gb</td>
        </tr>
        <tr>
            <td class="fw-bold">storage</td>
            <td>{{ product.smartphone_detail.storage }}Gb</td>
        </tr>
        <tr>
            <td class="fw-bold">camera</td>
            <td>{{ product.smartphone_detail.camera }}</td>
        </tr>
        <tr>
            <td class="fw-bold">processor</td>
            <td>{{ product.smartphone_detail.processor }}</td>
        </tr>
        <tr>
            <td class="fw-bold">fingerprint</td>
            <td>{{ product.smartphone_detail.fingerprint }}</td>
        </tr>
        <tr>
            <td class="fw-bold">battery</td>
            <td>{{ product.smartphone_detail.battery }}</td>
        </tr>
        <tr>
            <td class="fw-bold">charger</td>
            <td>{{ product.smartphone_detail.charger }}</td>
        </tr>
        <tr>
            <td class="fw-bold">charging speed</td>
            <td>{{ product.smartphone_detail.charging_speed }}</td>
        </tr>

    </tbody>
    {% endif %}

    {% if is_accessory %}
    <table class="table">
        <tbody>
            <tr>
                <td class="fw-bold">name</td>
                <td>{{ product.smartphone_accessory_detail.name }}</td>
            </tr>
            <tr>
                <td class="fw-bold">brand</td>
                <td>{{ product.smartphone_accessory_detail.brand }}</td>
            </tr>
            <tr>
                <td class="fw-bold">product type</td>
                <td>{{ product.smartphone_accessory_detail.type }}</td>
            </tr>

        </tbody>
        {% endif %}

我们无法帮助您确定产品是否为智能手机。您是对您的数据库了解最深的人。

但是,如果确定很复杂,那么您应该完成 Python 中的工作,并通过上下文将一个简单的布尔值传递给您的模板。即使它不是很复杂,这也可能使模板比频繁重复 {% if something == 'somevalue' and someotherthing != 'someothervalue' %} 更具可读性。 (例如干)。

例如

def product_detail(request, slug):

    product = get_object_or_404(Product, slug=slug, in_stock=True)

    # as many lines of code as it takes to determine the True/False
    # value of is_smartphone

    return render(request, 'core/products/detail.html', 
        {'product': product, 'is_smartphone': is_smartphone})

在您的模板中

{% if is_smartphone %} ... {% endif %}

有时有用

{{ is_smartphone|yesno:'smartphone text,other text' }}