【问题标题】:Django form to formsetDjango 表单到表单集
【发布时间】:2020-11-17 18:00:32
【问题描述】:

我目前正在学习 Django 表单,我遇到了this post

其中一种形式目前如下所示:

我想做的是将类别更改为表单集,并能够在创建产品时呈现多个下拉列表。

我的models.py:

class Category(models.Model):
    name = models.CharField(max_length=30)
    user = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

class Product(models.Model):
    name = models.CharField(max_length=30)
    price = models.DecimalField(decimal_places=2, max_digits=10)
    category = models.ForeignKey(Category, on_delete = models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

我的forms.py:

class CategoryForm(forms.ModelForm):
    class Meta:
        model = Category
        fields = ('name', )


class ProductForm(forms.ModelForm):
    class Meta:
        model = Product
        fields = ('name', 'price', 'category', )

    def __init__(self, user, *args, **kwargs):
        super(ProductForm, self).__init__(*args, **kwargs)
        self.fields['category'].queryset = Category.objects.filter(user=user)

views.py 中的当前方法:

@login_required
def new_product(request):
    if request.method == 'POST':
        form = ProductForm(request.user, request.POST)
        if form.is_valid():
            product = form.save(commit=False)
            product.user = request.user
            product.save()
            return redirect('products_list')
    else:
        form = ProductForm(request.user)
    return render(request, 'products/product_form.html', {'form': form})

products_form.html:

{% extends 'base.html' %}

{% block content %}
  <h1>New product</h1>
  <form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="save">
    <a href="{% url 'products_list' %}">cancel</a>
  </form>
{% endblock %}

我尝试的是利用modelformset_factory并通过创建一个CategoryFormSet来更改views.py中的方法:

CategoryFormSet = modelformset_factory(Category, fields=('name', ), extra=2)
formset = CategoryFormSet(data=data, queryset=Category.objects.filter(user=request.user))

然后将 views.py 中的原始表单替换为创建的表单集。在 html 中,我只需将 {{form}} 替换为 {{formset}}。在玩了一段时间之后,我要么只使用提交按钮(未呈现表单)获得新产品,要么用户对象没有属性 GET 错误。我做错了什么?

【问题讨论】:

    标签: django django-forms django-views formset


    【解决方案1】:

    本教程的重点是允许用户添加/更新一个模型的更多实例。你想编辑一件东西,有多个相关的东西内联

    但是,您的数据模型只允许每个产品一个类别,因此这没有任何意义。您是否想要每个产品多个类别,只有您可以回答:) - 我假设您想要。

    首先,您需要更改模型以允许每个产品有多个类别:

    class Product(models.Model):
        name = models.CharField(max_length=30)
        price = models.DecimalField(decimal_places=2, max_digits=10)
        categories = models.ManyToManyField(Category, related_name='products')
        user = models.ForeignKey(User, on_delete=models.CASCADE)
    

    然后你需要了解Inline Formsets

    如果您遇到困难,请返回具体内容。

    【讨论】:

    • 但是我可以为多对多字段创建内联表单集吗? link
    • 哇,如此糟糕的接受答案仍然存在于 SO :(。诀窍是使用直通模型,因为它包含外键。我会更新我的答案。
    【解决方案2】:

    而不是创建新的模型类别。你可以这样做。

    CATEGORY_CHOICES= ( 
        ("1", "1"), 
        ("2", "2"), 
        ("3", "3"), 
        ("4", "4"), 
        ("5", "5"), 
        ("6", "6"), 
        ("7", "7"), 
        ("8", "8"), 
    )
    category = models.CharField(max_length = 20,choices = CATEGORY_CHOICES,default = '1')
    

    它会自动呈现在 HTML 中。

    【讨论】:

    • 我想从数据库中获取类别,而不是硬编码
    • 这将类别与代码联系起来,因此需要更改代码以添加新类别。它不会自动呈现在 HTML 中,实际上经常有人问如何处理模板中的选择标签和值。
    猜你喜欢
    • 2011-12-11
    • 2016-03-18
    • 1970-01-01
    • 1970-01-01
    • 2018-02-08
    • 1970-01-01
    • 2013-02-15
    • 1970-01-01
    • 2017-01-04
    相关资源
    最近更新 更多