启动一个名为mysite的新项目,其中包含一个名为shop的应用程序。
打开shell并运行以下命令:
django-admin startproject mysite
cd myshop/
django-admin startapp shop
将shop应用程序添加到INSTALLED_APPS
编辑项目的settings.py文件:
INSTALLED_APPS = [
# ...
'shop.apps.ShopConfig',
]
商店的目录将包括按不同类别分类的产品。
产品信息包括:
编辑shop应用的models.py文件:
from django.db import models
from django.urls import reverse
class Category(models.Model):
name = models.CharField(max_length=200,db_index=True)
slug = models.SlugField(max_length=200,unique=True)
class Meta:
ordering = ('name',)
verbose_name = 'category'
verbose_name_plural = 'categories'
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('shop:product_list_by_category',args=[self.slug])
class Product(models.Model):
category = models.ForeignKey(Category,related_name='products',on_delete=models.CASCADE)
name = models.CharField(max_length=200, db_index=True)
slug = models.SlugField(max_length=200, db_index=True)
image = models.ImageField(upload_to='products/%Y/%m/%d', blank=True)
description = models.TextField(blank=True)
price = models.DecimalField(max_digits=10,decimal_places=2)
available = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
ordering = ('name',)
index_together = (('id','slug'),)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('shop:product_detail',args=[self.id,self.slug])
建议使用DecimalField来存储货币金额。可以避免浮点四舍五入问题。
在Meta中设置的参数含义:
如果需要指定数据库的表名称,可是使用db_table = 'Table name'
因为计划通过id和编号查询产品,在Product模型中,使用了index_together指定id,slug一起被索引,提供使用这两个字段的查询性能。
何时需要使用db_index=True?
频繁查询的字段(产品名字),外键字段(类别),唯一值(ID)。虽然所以可以提高查询性能,但也需要消耗一定的存储空间并导致写入速度变慢。
少查询字段,低基数字段(比如性别,只有男,女两个值),稀疏字段(字段值出现频率过低),都是不建议使用的。
通过django.urls导入reverse()函数,并向Category和Product模型添加get_absolute_url()方法。
get_absolute_url()是检索给定对象的URL的约定。后面,我们将在URLs .py文件中定义的url模式。
image字段需要上传图片。打开shell并运行以下命令:
pip install Pillow
同步模型到数据库
python manage.py makemigrations
python manage.py migrate
将模型添加到管理站点,以便使用管理站点轻松地管理类别和产品。
编辑shop应用程序的admin.py文件:
from django.contrib import admin
from .models import Category,Product
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
list_display = ['name','slug']
prepopulated_fields = {'slug':('name',)}
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ['name','slug','price','available','created','updated']
list_filter = ['available','created','updated']
list_editable = ['price','available']
prepopulated_fields = {'slug':('name',)}
list_editable中的任何字段必须在list_display列表中,只有显示的字段可以编辑
运行python .\manage.py runserver
用浏览器登录管理站点 http://127.0.0.1:8000/admin
产品管理列表如图
创建一个视图来列出所有产品或按给定类别筛选产品。
编辑shop应用程序的views.py文件:
from django.shortcuts import render,get_object_or_404
from .models import Category,Product
def product_list(request,category_slug=None):
category = None
categories = Category.objects.all()
products = Product.objects.filter(available=True)
if category_slug:
category = get_object_or_404(Category,slug=category_slug)
print(category.name)
products = products.filter(category=category)
template = 'shop/product/list.html'
context = {'category':category,'categories':categories,'products':products}
return render(request,template,context)
def product_detail(request,id,slug):
product = get_object_or_404(Product,id=id,slug=slug,available=True)
template = 'shop/product/detail.html'
context = {'product':product}
return render(request,template,context)
在构建了产品列表和详细信息视图之后,需要为它们定义URL模式。
在shop应用目录中创建一个新文件,并将其命名为urls.py。将以下代码添加到其中:
from django.urls import path
from . import views
app_name = 'shop'
urlpatterns = [
path('',views.product_list,name='product_list'),
path('',views.product_list,name='product_list_by_category'),
path('/',views.product_detail,name='product_detail'),
]
编辑mysite项目的urls.py文件,使其看起来像这样:
from django.contrib import admin
from django.urls import path,include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
#...
path("shop/",include('shop.urls',namespace='shop')),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
因为用到了图片上传,使用static配置开发环境的静态文件。
在项目的setting.py中,添加以下代码:
STATIC_URL = "static/"
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
需要为产品列表和详细信息视图创建模板。
在shop应用程序目录中创建以下目录和文件结构:
templates/shop/base.html
templates/shop/product/list.html
templates/shop/product/detail.html
首先需要定义一个base基本模板,然后在产品列表(list.html)和详细信息模板(detail.html)中扩展它。编辑shop/base.html模板,并添加以下代码:
{% load static %}
{% block title %}My shop{% endblock %}
Your cart is empty.
{% block content %}
{% endblock %}
为了包含模板使用的CSS样式,这里使用了bootstrap样式库。
编辑shop/product/list.html模板:
{% extends "shop/base.html" %}
{% load static %}
{% block title %}
{% if category %}{{ category.name }}{% else %}Products{% endif %}
{% endblock %}
{% block content %}
Categories
All
{% for c in categories %}
{{ c.name }}
{% endfor %}
{% if category %}{{ category.name }}{% else %}Products
{% endif %}
{% for product in products %}
{% endfor %}
{% endblock %}
编辑产品详细信息模板。
编辑shop/product/detail.html模板,并添加以下代码:
{% extends "shop/base.html" %}
{% load static %}
{% block title %}
{{ product.name }}
{% endblock %}
{% block content %}
{% endblock %}