Django初创shop应用

创建项目和应用


启动一个名为mysite的新项目,其中包含一个名为shop的应用程序。
打开shell并运行以下命令:
django-admin startproject mysite
cd myshop/
django-admin startapp shop

将shop应用程序添加到INSTALLED_APPS
编辑项目的settings.py文件:

INSTALLED_APPS = [# ...'shop.apps.ShopConfig',
]

创建应用模型


商店的目录将包括按不同类别分类的产品。
产品信息包括:

  • 类别(category):关联类别
  • 名称(name):最大长度200,开启索引
  • 描述(description):可选
  • 图像(image):可选
  • 价格(price):最大位数10,小数位数2
  • 可用性(available):默认可用
  • 自动生成创建和更新时间

编辑shop应用的models.py文件:

from django.db import models
from django.urls import reverseclass 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.namedef 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.namedef get_absolute_url(self):return reverse('shop:product_detail',args=[self.id,self.slug])
  • ForeignKey是一对多关系,一个类别对应多个产品。
  • slug讲为这个产品构建URL。
  • decimal.Decimal是固定精度数字,包含两个参数:max_digits设置最大位数(包含小数位),decimal_places设置小数位数。

建议使用DecimalField来存储货币金额。可以避免浮点四舍五入问题。

在Meta中设置的参数含义:

  • ordering:排序。
  • verbose_name:在admin管理界面中显示中文,单数形式显示。
  • verbose_name_plural:复数形式显示,中文单数和复数一半不作区别。

如果需要指定数据库的表名称,可是使用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',)}
  • 使用prepopulated_fields使用name的值自动生成slug
  • 使用list_editable设置从管理站点的列表显示页面编辑字段,可以一次编辑多行。

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,Productdef product_list(request,category_slug=None):category = Nonecategories = 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)
  • product_list使用了一个可选的category_slug参数按给定的类别筛选产品。过滤带有available=True的QuerySet,只检索可用的产品。
  • product_detail视图来检索和显示单个产品。需要id和slug参数,以便检索产品实例。我们可以通过ID获得这个实例,因为它是唯一属性。但是,我们在URL中包含了slug,以便为产品构建seo友好的URL。

创建应用URL

在构建了产品列表和详细信息视图之后,需要为它们定义URL模式。
在shop应用目录中创建一个新文件,并将其命名为urls.py。将以下代码添加到其中:

from django.urls import path
from . import viewsapp_name = 'shop'urlpatterns = [path('',views.product_list,name='product_list'),path('<slug:category_slug>',views.product_list,name='product_list_by_category'),path('<int:id>/<slug:slug>',views.product_detail,name='product_detail'),
]
  • product_list视图定义了两种不同的URL模式:一个名为product_list的模式,它调用product_list视图而不带任何参数;还有一个名为product_list_by_category的模式,它为视图提供了一个category_slug参数,用于根据给定的类别过滤产品。
  • product_detail视图添加了一个模式,它将id和slug参数传递给视图,以便检索特定的产品。

编辑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 staticurlpatterns = [#...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 %}
<!DOCTYPE html>
<html>
<head><meta charset="utf-8" /><title>{% block title %}My shop{% endblock %}</title><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
</head>
<body><div class="navbar bg-body-tertiary"><div class="container-fluid"><a class="navbar-brand" href="/shop">My shop</a></div></div><div id="subheader"><div class="cart"><div class="alert alert-light" role="alert">Your cart is empty.</div></div></div><div class="container">{% block content %}{% endblock %}</div><script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js" integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.min.js" integrity="sha384-BBtl+eGJRgqQAUMxJ7pMwbEyER4l1g+O15P+16Ep7Q9Q+zqX6gSbd85u4mG4QzX+" crossorigin="anonymous"></script>
</body>
</html>

为了包含模板使用的CSS样式,这里使用了bootstrap样式库。

编辑shop/product/list.html模板:

{% extends "shop/base.html" %}
{% load static %}
{% block title %}{% if category %}{{ category.name }}{% else %}Products{% endif %}
{% endblock %}
{% block content %}<div class="row"><div class="col-3" style="margin-top: 60px; padding: 10px;"><h3>Categories</h3><div class="list-group"><a href="{% url 'shop:product_list' %}" {% if not category %} class="list-group-item list-group-item-action active"{%else%}class="list-group-item list-group-item-action"{% endif %}>All</a>{% for c in categories %}<a href="{{ c.get_absolute_url }}" {% if category.slug == c.slug %}class="list-group-item list-group-item-action active"{%else%}class="list-group-item list-group-item-action"{% endif %}>{{ c.name }}</a>{% endfor %}</div></div><div class="col"><h1>{% if category %}{{ category.name }}{% else %}Products{% endif %}</h1><div class="container"><div class="row">{% for product in products %}<div class="col text-center"><a href="{{ product.get_absolute_url }}"><img src="{% if product.image %}{{ product.image.url }}{%else %}{% static 'shop/no_image.png' %}{% endif %}" style="width: 200px; height: 100px;"></a><br><a href="{{ product.get_absolute_url }}" class="text-decoration-none">{{ product.name }}</a><br>${{ product.price }}</div>{% endfor %}</div></div></div></div>
{% endblock %}
  • 这是产品列表模板。它扩展了shop/base.html模板,并使用categories上下文变量来显示侧边栏中的所有类别,使用products来显示当前页面的产品。两者都使用相同的模板:列出所有可用产品和列出按类别过滤的产品。
  • 当在模版中使用{{ product.get_absolute_url  }} 会使用product实例id和slug自动填充URL中的参数。
  • 由于产品图像字段可以为空白,需要为没有图像的产品提供默认图像。该图像位于静态文件目录中,相对路径为shop/static/shop/no_image.png。

编辑产品详细信息模板。
编辑shop/product/detail.html模板,并添加以下代码:

{% extends "shop/base.html" %}
{% load static %}
{% block title %}
{{ product.name }}
{% endblock %}
{% block content %}<div class="product-detail"><img src="{% if product.image %}{{ product.image.url }}{% else %}{% static 'img/no_image.png' %}{% endif %}"><h1>{{ product.name }}</h1><h2><a href="{{ product.category.get_absolute_url }}">{{ product.category }}</a></h2><p class="price">${{ product.price }}</p>{{ product.description|linebreaks }}</div>
{% endblock %}

列表页面预览

详情页面预览

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/413953.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QT quick基础:组件gridview

组件gridview与android中gridview布局效果相同。 一、下面记录qt quick该组件的使用方法。 方法一&#xff1a; // ContactModel.qml import QtQuick 2.0ListModel {ListElement {name: "1"portrait: "icons/ic_find.png"}ListElement {name: "2&quo…

十一、常用API——正则表达式

目录 练习1&#xff1a; 正则表达式的作用 正则表达式 字符类&#xff08;只匹配一个字符&#xff09; 预定义字符&#xff08;只匹配一个字符&#xff09; 数量词 类 Pattern 正则表达式的构造摘要 反斜线、转义和引用 字符类 行结束符 组和捕获 Unicode 支持 与…

CSS笔记II

CSS第二天笔记 复合选择器后代选择器子选择器并集选择器交集选择器伪类选择器 三大特性继承性层叠性优先级优先级-叠加计算规则 Emmet写法 背景属性背景图平铺方式位置缩放固定复合属性 显示模式转换显示模式 复合选择器 定义&#xff1a;由两个或多个基础选择器&#xff0c;通…

最终Docker6:nacos集群部署

目录 mysql容器构建 1.进入soft 文件夹&#xff0c;创建mysql文件夹 2.进入conf文件夹 放入my.conf 配置文件 3.运行mysql容器 4.进入script文件夹 导入 sql文件 5.进入mysql 容器 并登录 6.创建nacos 数据库并使用&#xff0c;运行nacos.sql文件 7.授予用户所有权限 部…

基于Prism框架的WPF前端框架开发《知产代理数字化解决方案》

最近新开发了一套WPF前端界面框架&#xff0c;叫《知产代理数字化解决方案》&#xff0c;采用了时下流行的Prism框架作为整个系统的基础架构&#xff0c;演示了Prism中的IRegionManager区域管理器、IDialogAware对话框、IDialogService对话框服务、IContainerExtension容器等用…

gitgud.io+Sapphire注册账号教程

gitgud.io是一个仓库&#xff0c;地址 https://gitgud.io/&#xff0c;点进去之后会看到注册页面。 意思是需要通过注册这个Sapphire账户来登录。点击右边的Sapphire&#xff0c;就跳转到Sapphire的登陆页面&#xff0c;点击创建新账号&#xff0c;就进入注册页面。&#xff0…

阿里云地域和可用区分布表,2024更新

2024年阿里云服务器地域分布表&#xff0c;地域指数据中心所在的地理区域&#xff0c;通常按照数据中心所在的城市划分&#xff0c;例如华北2&#xff08;北京&#xff09;地域表示数据中心所在的城市是北京。阿里云地域分为四部分即中国、亚太其他国家、欧洲与美洲和中东&…

【办公类-21-01】20240117育婴员操作题word合并1.0

背景需求&#xff1a; 最近学校组织老师们学习“育婴员”高级&#xff0c;每周学习2题操作&#xff0c;所以我是把每个学习内容单独做在一个word文件里 上周8套保健操作学完了&#xff0c;需要整理&#xff0c;并将8份Word文件合并 第一步&#xff1a;doc装docx 合并时程序报…

springBoot如何动态切换数据源

项目背景&#xff1a;最近公司中需要搭建mysql的主从&#xff0c;想着在spring中集成多数据源。mybatisplus提供的有插件用DS注解就能够实现&#xff0c;但是这种在mysql服务宕机的情况下不能够进行自动切换&#xff0c;于是就想着用aop自定义注解的方式来实现 项目实现效果&a…

JCIM | 在gromacs中进行恒定ph模拟

恒定pH分子动力学(MD)是一种强大的技术&#xff0c;可以动态地改变残留物的质子化状态&#xff0c;从而能够以一种以前不可能实现的方式研究pH相关性。最近&#xff0c;这样一项技术引入到了Gromacs中。为了简化和自动化设置此过程&#xff0c;来自瑞典的研究团队提出了一个名为…

【机器学习】调配师:咖啡的完美预测

有一天&#xff0c;小明带着一脸期待找到了你这位数据分析大师。他掏出手机&#xff0c;屏幕上展示着一份详尽的Excel表格。“看&#xff0c;这是我咖啡店过去一年的数据。”他滑动着屏幕&#xff0c;“每个月的销售量、广告投入&#xff0c;还有当月的气温&#xff0c;我都记录…

Yolov8_使用自定义数据集训练模型1

前面几篇文章介绍了如何搭建Yolov8环境、使用默认的模型训练和推理图片及视频的效果、并使用GPU版本的torch加速推理、导出.engine格式的模型进一步利用GPU加速&#xff0c;本篇介绍如何自定义数据集&#xff0c;这样就可以训练出识别特定物体的模型。 《Yolov8_使用自定义数据…