- 后端
- 电商
【免费下载链接】django-oscar
Domain-driven e-commerce for Django
导读
Django Oscar 是一套基于领域驱动设计(DDD)思想构建的 Django 电商框架,开箱即用地提供了 catalogue(目录)、basket(购物车)、checkout(结算)、dashboard(后台管理)、offer(优惠)、wishlists(愿望清单)、reviews(商品评价)等完整模块。然而在实际项目中,你往往并不需要全部功能——例如想用自己的后台替代 Oscar 自带的 dashboard,或者想在不删除代码的前提下临时下线商品评价功能。本文基于官方 How-to 文档(docs/source/howto/how_to_disable_an_app_or_feature.rst),系统讲解两种"裁剪"方案:一是通过自定义Shop根应用配置精确移除某个 App 的 URL;二是通过OSCAR_HIDDEN_FEATURES设置与{% iffeature %}模板标签声明式隐藏某个特性。读完本文,你将掌握如何在保留 Oscar 框架完整代码的前提下,按需关闭后台、评价、愿望清单等功能,并能够为自己的业务模块接入可隐藏机制。
为什么需要"禁用"而非"删除"
Oscar 的设计哲学之一是"可定制优先":框架源码保持完整,项目通过继承、fork 和配置来改变行为。直接删代码会导致升级框架版本时难以合并,而"禁用"是一种低侵入方案:
- URL 级禁用:从 URLconf 中剔除某个 App 的路由,用户将无法访问该功能的所有页面;
- 特性级禁用:通过设置项与模板标签组合,同时隐藏 URL 和页面上的入口、按钮、评分区块等 UI 元素。
两种方案都无需改动oscar包内部代码,完全在项目自己的应用层完成,这也是 Oscar 自定义体系(docs/source/topics/customisation.rst)所推崇的做法。
方案一:禁用某个 App 的 URL
适用场景:不使用 Oscar 的 dashboard、search、wishlists 等模块,希望直接移除其所有路由。
第一步:根 urls.py 改为引用自己的 AppConfig
Oscar 根路由默认由oscar.config.Shop提供(见 src/oscar/config.py),它把 catalogue、basket、checkout、customer、search、dashboard、offer、wishlists 等子应用的 URL 统一挂载到各前缀下。要获得对 URL 结构的完全控制,你需要把根urls.py从引用oscar.urls改为引用你自己项目的 AppConfig:
# urls.py from django.apps import apps urlpatterns = [ # ... path('', include(apps.get_app_config('myproject').urls[0])), ]其中myproject是一个 Django/Oscar 应用,它的 AppConfig 类是oscar.config.Shop的子类,并在其中排除了 dashboard 应用的 URL 配置。
这里的关键在于apps.get_app_config('myproject').urls:在 src/oscar/core/application.py 中,OscarConfigMixin.urls是一个返回(urlpatterns, label, namespace)三元组的属性,所以include()只取下标[0](即 URL 列表)。
第二步:自定义 Shop 子类并重写 get_urls
在myproject/config.py中定义一个Shop子类,重写get_urls(),遍历父类生成的 URL 列表并移除名为dashboard的 URLPattern:
# myproject/config.py from oscar.config import Shop from oscar.core.application import OscarConfig class MyShop(Shop): # Override the get_urls method to remove the URL configuration for the # dashboard app def get_urls(self): urls = super().get_urls() for urlpattern in urls[:]: if hasattr(urlpattern, 'app_name') and (urlpattern.app_name == 'dashboard'): urls.remove(urlpattern) return self.post_process_urls(urls)然后在myproject/__init__.py中声明默认的 AppConfig:
# myproject/__init__.py default_app_config = 'myproject.config.MyShop'原理剖析:为什么这样能生效
Shop.get_urls()(src/oscar/config.py)返回的列表中,path("dashboard/", self.dashboard_app.urls)这一项是一个带app_name == 'dashboard'的 URLPattern,因此能被精确匹配并移除;- 循环中使用
urls[:]创建副本遍历,避免在迭代过程中修改列表导致跳过元素或抛异常; self.post_process_urls(urls)(src/oscar/core/application.py)会递归处理所有 URLPattern,并应用各视图的权限装饰器(permissions_map/default_permissions),确保移除 dashboard 后其余路由仍保持 Oscar 原有的权限保护逻辑。
注意:Shop在ready()中会通过apps.get_app_config("dashboard")加载各子应用(src/oscar/config.py),因此即使 dashboard 路由被移除,其 AppConfig 仍存在于INSTALLED_APPS中,不会引发导入错误——你只是关闭了它的对外 URL。
第三步:清理模板引用
移除 URL 后还有一件收尾工作:确保你的模板不再引用任何 dashboard 的 URL。Oscar 自带模板(src/oscar/templates/oscar/)中,dashboard 相关的反向解析(如{% url 'dashboard:index' %})如果被渲染到页面上,会因 URL 不存在而抛NoReverseMatch。若你 fork 了模板并保留了相关链接,需要一并删除或改为条件渲染。
方案二:通过 OSCAR_HIDDEN_FEATURES 隐藏特性
与"整体移除 URL"相比,Oscar 还提供了一种更细粒度、声明式的特性隐藏机制,它同时作用于路由层与模板层。
设置项与默认值
在项目的settings.py中把要隐藏的特性名加入OSCAR_HIDDEN_FEATURES列表即可:
OSCAR_HIDDEN_FEATURES = ['reviews', 'wishlists']该设置默认为空列表(见 src/oscar/defaults.py):
# Hidden Oscar features, e.g. wishlists or reviews OSCAR_HIDDEN_FEATURES = []从源码结构看,当前版本内置声明了可隐藏特性的 App 是 reviews(商品评价):CatalogueReviewsConfig在 src/oscar/apps/catalogue/reviews/apps.py 中设置了hidable_feature_name = "reviews"。官方文档同时将 wishlists 列为受支持特性,测试套件也分别用OSCAR_HIDDEN_FEATURES=["reviews"]和["wishlists"]验证了两者的隐藏行为(见 tests/integration/test_hidden_features.py)。
模板层的隐藏:{% iffeature %} 标签
在模板中,用{% iffeature %}/{% endiffeature %}包裹的代码块,在对应特性被隐藏时不会渲染:
{% iffeature "reviews" %} {% include "catalogue/reviews/partials/review_stars.html" %} {% endiffeature %}该标签的实现位于 src/oscar/templatetags/display_tags.py:
iffeature是一个 block tag,解析{% iffeature "reviews" %}与{% endiffeature %}之间的nodelist,并强制要求参数用引号包裹,否则抛出TemplateSyntaxError;ConditionalOutputNode.render()调用feature_hidden(feature_name)判断:若特性被隐藏则返回空字符串,否则正常渲染nodelist。
Oscar 自带模板已经大量使用了该标签,例如商品详情页 src/oscar/templates/oscar/catalogue/detail.html 用{% iffeature "reviews" %}控制评价区域,加入购物车表单 src/oscar/templates/oscar/catalogue/partials/add_to_basket_form.html 用其控制"加入愿望清单"按钮。因此,只要设置OSCAR_HIDDEN_FEATURES,这些 UI 入口会自动消失,无需逐个修改模板。
路由层的隐藏:post_process_urls 自动拦截
隐藏特性不仅在模板层生效,还会自动移除对应 App 的 URL。其底层机制是 src/oscar/core/application.py 中post_process_urls()开头的判断:
# Test if this the URLs in the Application instance should be # available. If the feature is hidden then we don't include the URLs. if feature_hidden(self.hidable_feature_name): return []而feature_hidden()定义在 src/oscar/core/loading.py:
def feature_hidden(feature_name): """ Test if a certain Oscar feature is disabled. """ return feature_name is not None and feature_name in settings.OSCAR_HIDDEN_FEATURES当某 AppConfig 的hidable_feature_name非空且命中OSCAR_HIDDEN_FEATURES时,get_urls()最终返回空列表(各 App 的get_urls()都以self.post_process_urls(urls)收尾,例如 src/oscar/apps/catalogue/reviews/apps.py 与 src/oscar/apps/wishlists/apps.py),该特性的所有路由便从 URLconf 中消失。
方案三:让你的自定义模块支持隐藏
hidable_feature_name是OscarConfigMixin提供的通用机制(见 src/oscar/core/application.py),因此你可以为自己的业务 App 接入同样的隐藏能力。
1. 在 AppConfig 中声明特性名
假设你有一个lottery(抽奖)模块,其 AppConfig 继承OscarConfig并设置特性名:
# myproject/apps/lottery/apps.py from oscar.core.application import OscarConfig class LotterConfig(OscarConfig): hidable_feature_name = 'lottery'2. 加入隐藏列表
在settings.py中:
OSCAR_HIDDEN_FEATURES = ['lottery']3. 用模板标签包裹相关 UI
{% iffeature "lottery" %} ... 抽奖入口、横幅、组件 ... {% endiffeature %}这样配置后,lottery的 URL 会自动从 URLconf 中移除,模板中包裹的区块也不会渲染,整套逻辑与内置的 reviews 特性完全一致。
值得注意的细节
- 特性名是字符串匹配:
feature_hidden做的是feature_name in settings.OSCAR_HIDDEN_FEATURES的成员判断,因此hidable_feature_name必须与列表中的字符串完全一致(区分大小写); hidable_feature_name默认为None,此时feature_hidden恒为False,即未声明特性名的 App 永远不会被该机制隐藏;- 隐藏仅影响路由注册与模板渲染,不影响模型、迁移与后台任务:例如隐藏 reviews 后,数据库中已存在的评价数据仍然保留,相关 management command 也照常可用。
测试验证:隐藏行为如何被保障
仓库为隐藏机制提供了专门的集成测试 tests/integration/test_hidden_features.py,可以当作行为规范来理解:
test_reviews_enabled:默认配置下,商品详情页包含 "Number of reviews"(评价计数)区块;test_reviews_disabled:在OSCAR_HIDDEN_FEATURES=["reviews"]下访问同一页面,断言不包含该区块;test_wishlists_enabled:账户页包含愿望清单 URL,商品详情页包含 "Add to wish list" 按钮;test_wishlists_disabled:隐藏后,账户页不再包含customer:wishlists-list的 URL,商品页也不再出现 "Add to wish list"。
这些用例通过self.settings(OSCAR_HIDDEN_FEATURES=[...])上下文管理器动态切换设置,直观印证了"设置即生效"的声明式设计——模板层与路由层的行为都可以被测试覆盖,你在为自定义模块接入hidable_feature_name后,完全可以参照该文件编写同样的测试。
两种方案对比与选型建议
| 维度 | 方案一:自定义 Shop.get_urls | 方案二:OSCAR_HIDDEN_FEATURES |
|---|---|---|
| 控制粒度 | 以整个 App 为单位移除 URL | 以特性名(feature name)为单位,同时控制 URL 与模板 |
| 配置位置 | 项目根 AppConfig(myproject/config.py) | settings.py中的OSCAR_HIDDEN_FEATURES |
| 对模板的影响 | 需手动清理所有相关 URL 引用 | 自动配合{% iffeature %}隐藏 UI 区块 |
| 是否需写代码 | 需重写get_urls() | 无需,纯配置;自定义特性时需设置hidable_feature_name |
| 典型场景 | 替换整个 dashboard、关闭整个搜索模块 | 临时下线评价、愿望清单等局部特性,或为业务模块接入开关 |
两条路径可以组合使用:例如用方案一整体移除 dashboard 路由,同时用方案二声明式地隐藏 reviews 与 wishlists,从而把商城前台裁剪成"仅浏览 + 下单"的精简形态。无论选择哪种方式,其共同原则都是:保留框架代码完整性,把"要不要展示"的决策留在项目配置层,这正是 Oscar 可定制架构(docs/source/topics/customisation.rst)的核心价值所在。
- 后端
- 电商
【免费下载链接】django-oscar
Domain-driven e-commerce for Django
相关推荐
如何在普通电脑上运行MiniCPM5-1B-GGUF:打造你的专属本地AI助手
如何在普通电脑上运行MiniCPM5 1B GGUF:打造你的专属本地AI助手 你是否厌倦了依赖云端的AI服务,担心隐私泄露?想要一个完全掌控在自己手中的智能助
人工智能大模型基础模型本地部署DeePMD-kit多后端支持深度解析:TensorFlow、PyTorch、JAX全面对比
DeePMD kit多后端支持深度解析:TensorFlow、PyTorch、JAX全面对比 DeePMD kit作为一款先进的深度学习分子动力学模拟工具,通过
人工智能深度学习预训练微调模型推理科研科学计算AI 技能PictureSelector Library图片裁剪功能详解:比例调整与自定义裁剪框
PictureSelector Library图片裁剪功能详解:比例调整与自定义裁剪框 在Android应用开发中,图片裁剪功能是用户交互的重要组成部分。Pic
移动开发UI组件音视频
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考