【问题标题】:How to display a ForeignKey as RadioSelect options from DetailView in Django?如何在 Django 的 DetailView 中将 ForeignKey 显示为 RadioSelect 选项?
【发布时间】:2012-08-03 04:13:23
【问题描述】:

我正在学习如何使用 python/django 进行编程,并且我已经挑战自己为印刷企业构建电子商务网站。总体思路如下:

一旦客户选择了产品,他必须从一组选项(尺寸、边框宽度、材料)中进行选择,以便定制他的产品。值得一提的是,每个选项都具有将其与其他选项区分开来的特征。例如:每个尺寸都有一个宽度和一个高度,这是材质不需要的属性。然后他会上传一张图片(但我还没有),商店会处理他的订单。

因此,我选择将 models.py 设计为如下(简化):

class Product(models.Model):
    title = models.CharField(max_length = 150)
    slug = models.SlugField(max_length = 150)
    base_price = models.DecimalField(max_digits = 12, decimal_places = 2, default=0.00)

    class Meta:
        verbose_name = ('Product')
        verbose_name_plural = ('Products')

    #Methods. There is a method for each option.
    def get_materials(self):
        materials = self.materials.all()
        return materials

#There is a model for each option. Each model has a ForeignKey to Product.
class Material(models.Model):
    product = models.ForeignKey(Product, verbose_name = "Product", related_name="materials")
    name = models.CharField(max_length = 150)
    code = models.SlugField(max_length=150)
    price_per_meter = models.DecimalField(max_digits = 12, decimal_places = 2, blank = True, default = 0.00)
    created_at = models.DateTimeField(auto_now_add = True)

    class Meta:
        ordering = ["-created_at"]
        verbose_name_plural = "Materials"

为了简化我使用 DetailView 的操作。所以在我的 catalogue.urls.py 中:

from django.conf.urls import patterns, include, url
from django.views.generic import DetailView
from catalogue.models import Product

urlpatterns = patterns('',
    url(r'^(?P<pk>\d+)/$', DetailView.as_view(
        model = Product,
        template_name = "detail.html"
        )),
)

所以,问题来了终于

如何自定义我的 DetailView 以便在 UI 中每个选项都显示为 RadioSelect?

已经发布了类似的问题,但它们与表单更相关:即如何在表单中将 ForeignKey 显示为 RadioSelect。

我目前的方法使用以下detail.html

{% extends "base.html" %}

{% block content %}

<h1>{{ product.title }}</h1>

<h2>Please select one of the following:</h2>
<p>{{ product.get_materials }}</p>
<p>{{ product.get_sizes }}</p>
<p>{{ product.get_border_width }}</p>
<p>{{ product.get_border_color }}</p>

{% endblock %}

这会呈现以下内容: 我在数据库中添加了一些随机数据

Please select one of the following:

[<Material: Material 1>, <Material: Material 2>]

[<Size: Size 1>, <Size: Size 2>]

[<BorderWidth: Border 1>, <BorderWidth: Border 2>]

[<BorderColor: Color 1>, <BorderColor: Color 1>]

任何帮助/指出正确方向的人都将不胜感激。

【问题讨论】:

  • 您似乎在谈论您认为不是表格的表格。
  • 您可能还会发现基于类的视图对于 Django 来说是一个很难开始的地方(尤其是在处理表单时)。有关非基于类的介绍,请参阅 Django 的 "Working with forms" 指南。
  • @slackjake 嗯...也许哈哈。我认为我不能将表单用于产品视图,因为表单会将信息发布到数据库(即创建“新产品”)?

标签: django e-commerce detailview


【解决方案1】:

简而言之,DetailView 用于显示数据。鉴于您正在向用户提问(“哪种材料?”、“哪种尺寸?”),您几乎可以肯定确实想要使用表单.这就是表单的设计目的!

为了使以下工作,我建议您颠倒您的ForeignKeys 的定义方式;我假设您希望在多种产品中使用相同的材​​料,而不是相反!将material = models.ForeignKey(Material, related_name='products') 之类的字段添加到您的Product,并从Material 中删除product 字段

在您的情况下,使用表单可能会很容易。查看"Creating forms from models" documentation,并尝试以下操作:

# urls.py
from django.views.generic import CreateView

urlpatterns = patterns('', ...
    url(r'^(?P<pk>\d+)/$', CreateView.as_view(
        model = Product,
        template_name = "add_product.html"
    )),
)

这将为您提供默认的Select 小部件——“从模型创建表单”文档(上图)包含有关customising the widget used to draw form fields 的信息。您需要创建一个新表单(继承自 ModelForm)并将您的观点指向该表单:

# forms.py
from django import forms

from catalogue.models import Product

class ProductForm(forms.ModelForms):
    class Meta:
        model = Product 
        widgets = {
            'material': forms.RadioSelect()
            ...
        }

# urls.py

from catalogue.forms import ProductForm

# add the following parameter to your call to as_view():
...
    'form_class': ProductForm

【讨论】:

  • 感谢您这么快的回答!我似乎确实有我的逻辑倒退^^)只是一个简单的问题:表单是否应该在“detail.html”模板中有一个“post”方法?或者我将如何继续,以便用户不在数据库中创建新产品,而是将信息传递到购物车? (当然,将东西添加到购物车是另一回事,但只是想确定我是否应该使用“post”?谢谢
  • 为此,您可能希望将信息存储在会话/cookie 中。您可以为此使用 CreateView,但您需要覆盖 form_valid 并且不确定还有什么。
  • @slackjake 谢谢!正如我指出的那样,我仍处于学习曲线中。你和@supervacuo 的回答都为我指明了正确的方向,这太棒了!谢谢你们的时间和及时的回应。作为 Stackoverflow 的新手,我不能投票,但要精神上投票!
  • 抱歉,保留名为detail.html 的模板是一个错误——我在上面的示例中将其更改为add_product.html。关于不保存到数据库,slackjake 是对的;而是存储在会话中。您确实想要override CreateView.form_valid,使用commit=False 保存表单并将Product 实例存储在self.request.session 中。
猜你喜欢
  • 2021-03-17
  • 1970-01-01
  • 2020-07-24
  • 2021-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-30
  • 2016-06-01
相关资源
最近更新 更多