【问题标题】:Django: How to Edit Page with Foreign Key Field set (Unable to edit and post to models)Django:如何使用外键字段集编辑页面(无法编辑和发布到模型)
【发布时间】:2018-08-04 07:30:54
【问题描述】:

我正在尝试通过 html 表单编辑 django 数据库。但是我不确定为什么会出现以下错误。产品类别是外键,我无法更改它的值。我该如何解决这个错误?谢谢。

ValueError 在 /shop/polyester-cushions/eiffel/edit_product/ 不能 分配“'Polyester Cushions'”:“Product.category”必须是“Category” 实例。

models.py

from django.db import models
from django.urls import reverse
from django.contrib.auth.models import User

class Category(models.Model):
    name = models.CharField(max_length=250, unique=True)
    slug = models.SlugField(max_length=250, unique=True)
    description = models.TextField(blank=True)
    image = models.ImageField(upload_to='category', blank=True)

    def __str__(self):
        return '{}'.format(self.name)

class Product(models.Model):    
    CATEGORY_CHOICES = (
        ("Cotton Cushions", "Cotton Cushions"),
        ("Polyester Cushions", "Polyester Cushions")
    )
    name = models.CharField(max_length=250, unique=True)
    slug = models.SlugField(max_length=250, unique=True)
    description = models.TextField(blank=True)
    category = models.ForeignKey(Category, on_delete=models.CASCADE, choices=CATEGORY_CHOICES)
    price = models.DecimalField(max_digits=10, decimal_places=2)

    def __str__(self):
        return '{}'.format(self.name)

edit_product.html

<div class="form-group row">
    <label class="col-sm-2 col-form-label">Category</label>
        <div class="col-sm-10">
            <select name="category" class="form-control" value="{{ product.category }}">
            <option {% if product.category == "Cotton Cushions" %} selected {% endif %} value="Cotton Cushions">Cotton Cushions</option>
            <option {% if product.category == "Polyester Cushions" %} selected {% endif %} value="Polyester Cushions">Polyester Cushions</option>
            </select>
        </div>
</div>

views.py

@login_required(login_url="/")
def EditProduct(request, c_slug, product_slug):
    try:
        product = Product.objects.get(category__slug=c_slug, slug=product_slug)
        error = ''
        if request.method == 'POST':
            product_form = ProductForm(request.POST, request.FILES, instance=product)
            if product_form.is_valid():
                product.save()
                return redirect('shop/my_products.html/')
            else:
                error = "Data is not valid"

        return render(request, 'shop/edit_product.html', {'product':product, 'error':error})
    except Product.DoesNotExist:
        return redirect('/')

forms.py

from django import forms
from django.forms import ModelForm
from .models import Product

class ProductForm(ModelForm):
    class Meta:
        model = Product
        fields = ('name','slug','description','category','price','image','stock','available')

【问题讨论】:

  • 该选项中的值是一个字符串,您基本上是在尝试将字符串插入 ForeignKey 字段。尝试将值设置为 ID 并从视图中的 ID 获取模型。
  • 添加您的views.py以及表单类代码(如果有问题)
  • 维吉:谢谢。我明白你现在的意思了。 Satendra:我已经加进去了。

标签: python html django templates


【解决方案1】:

如果您使用ForeignKey 字段,请不要在其中传递choices 属性。 Category 模型的对象将作为它的选择。

Product 模型中的category 字段中删除choices 属性

category = models.ForeignKey(Category, on_delete=models.CASCADE)

不要忘记运行makemigrationsmigrate之后的命令 从字段中删除choices

在您的模板中使用 {{form}} 上下文变量,尽管手动呈现表单

如果您手动渲染使用类别对象的pk 作为选项值。并遍历所有类别对象。

更新

从 url 中删除 c_slug 并将您的 EditProduct 视图修改为

@login_required(login_url="/")
def EditProduct(request, product_slug):
    try:
        product = Product.objects.get(slug=product_slug)
        error = ''
        if request.method == 'POST':
            product_form = ProductForm(request.POST, request.FILES, instance=product)
            if product_form.is_valid():
                product_form.save()
                return redirect('shop/my_products.html/')
            else:
                error = "Data is not valid"
        else:
           # create and edit form when request is GET
           product_form = ProductForm(instance=product)

        # add `product_form` in context instead of `product`
        return render(request, 'shop/edit_product.html', {'product_form':product_form, 'error':error})
    except Product.DoesNotExist:
        return redirect('/')

注意:当请求为 GET 并发送时,创建编辑 product_form 表单 上下文中的product_form 而不是模板中的product

edit_product.html 中,只需使用下面的代码来呈现表单

<form method="post">
  {% csrf_token %}
  {{product_form}}
  <input type="submit" value="submit"/>
</form>

【讨论】:

  • 对不起,我还是没听明白。 html部分应该怎么写。感谢您的帮助。
  • @moonfairy 检查我答案中的更新部分,希望这会有所帮助
  • 如果还是不明白,在Github上创建一个repo,我会直接修改。
  • 嗨 satendra,抱歉回复晚了。以下是我的 github github.com/moonfairyz/sun 的链接,我现在自己也在努力。非常感谢您的帮助!
  • @Satendra,我知道了,我刚刚删除了:action="{%%}" 现在可以使用了。超级棒!非常感谢。
【解决方案2】:

试试下面的代码:

通常html是这样的:

<form method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="ok">
</form>

models.py(您可能需要运行 makemigrations 并进行迁移)

from django.db import models
from django.urls import reverse
from django.contrib.auth.models import User

class Category(models.Model):
    CATEGORY_CHOICES = (
        ("Cotton Cushions", "Cotton Cushions"),
        ("Polyester Cushions", "Polyester Cushions")
    )
    name = models.CharField(max_length=250, unique=True, choices=CATEGORY_CHOICES)
    slug = models.SlugField(max_length=250, unique=True)
    description = models.TextField(blank=True)
    image = models.ImageField(upload_to='category', blank=True)

    def __str__(self):
        return self.name

class Product(models.Model):    
    name = models.CharField(max_length=250, unique=True)
    slug = models.SlugField(max_length=250, unique=True)
    description = models.TextField(blank=True)
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    price = models.DecimalField(max_digits=10, decimal_places=2)

    def __str__(self):
        return self.name

views.py(或者你可以使用 django 的 UpdateView)

@login_required(login_url="/")
def EditProduct(request, c_slug, product_slug):
    try:
        product = Product.objects.get(category__slug=c_slug, slug=product_slug)
    except Product.DoesNotExist:
        return redirect('/')
    if request.method == 'POST':
        form = ProductForm(request.POST, request.FILES, instance=product)
        if form.is_valid():
            form.save()
            return redirect('shop/my_products.html')
    else:
        form = ProductForm(instance=product)
    return render(request, 'shop/edit_product.html', {'form': form})

【讨论】:

  • 对不起,我试过了,但它不起作用,它还没有解决将字符串传递到外键字段的 html 部分,我是初学者。感谢您的帮助
  • @moonfairy 见django.views.generic.edit.UpdateView
【解决方案3】:

请检查数据库中您的产品表类别字段名称。它是一个外键。它可以像添加 category_id 一样更改文件名。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-19
    • 2016-08-31
    • 2020-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多