表单不保存到带有两个外键的模型 - Django

Form not saving to model with two Foreign Keys - Django

我在将表单保存到具有两个外键的模型时遇到问题:

  1. 正在提交表单的用户
  2. 提交的加密货币的当前价格。

表单值似乎通过 AssetView 但未被保存。任何人都可以帮助他们为什么不储蓄。我提供了模型、视图、表单,HTML。

Django 模型

from django.contrib.auth.models import User

class CryptoPrices(models.Model):
    symbol = models.CharField(max_length=20)
    current_price = models.FloatField(default=0.0)

class CryptoAssets(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    symbol = models.CharField(max_length=20)
    amount = models.FloatField(default=0.0)
    purchase_price = models.FloatField(default=0.0)
    crypto_prices = models.ForeignKey(CryptoPrices, on_delete=models.CASCADE)

Django 视图

from coinprices.forms import AssetForm

class AssetView(TemplateView):
    template_name = 'coinprices/my-dashboard.html'

    def get(self, request):
        form_a = AssetForm(prefix='form_a')
        return render(request, self.template_name, {'form_a': form_a})

    def post(self, request):
        form_a = AssetForm(request.POST, prefix='form_a')
        if form_a.is_valid():
            post = form_a.cleaned_data
            post.save()
            form = AssetForm()
            args = {'form': form}
            return render(request, self.template_name, args)

        args = {'form_a': form_a}
        return render(request, self.template_name, args)

Django 表单

from coinprices.models import CryptoPrices

tickers = (('BTC', 'BTC'), ('ETH', 'ETH'))

class AssetForm(forms.ModelForm):

    symbol = forms.ChoiceField(choices=tickers, required=True, label='')
    amount = forms.DecimalField(decimal_places=2, max_digits=20, required=True, label='')
    purchase_price = forms.DecimalField(decimal_places=2, max_digits=20, required=True, label='')

    class Meta:
        model = CryptoAssets
        fields = (
            'symbol',
            'amount',
            'purchase_price'
        )

HTML

{% extends 'base.html' %}

    {% block head %}
    <title>My Dashboard</title>
    {% endblock %}

    {% block body %}
<br>
<div class="container">
      <h1>My Dashboard</h1>
        <p>
          <form method="post">
          {% csrf_token %}
          {{ form_a.as_p }}
          <button type="submit">Submit</button>
      </form>
    </p>
</div>
    {% endblock %}

错误

AttributeError: 'dict' object has no attribute 'save'

让我解释一下错误:

AttributeError: 'dict' object has no attribute 'save'

发生此错误是因为您正在尝试以这种方式保存:

post = form_a.cleaned_data
post.save()

这是错误的,因为 cleaned_data 是一个字典,它包含您的表单的值作为 fieldname:value 对。

正确的做法是:

post = form_a.save()

下一个错误表明字段 crypto_prices 的值是必需的,但您传递的是空值。

django.db.utils.IntegrityError: null value in column "crypto_prices_id" of relation "coinprices_cryptoassets" violates not-null constraint

发生这种情况是因为在您的 AssetForm 表单中您只选择了以下字段:

fields = (
            'symbol',
            'amount',
            'purchase_price'
        )

crypto_prices在哪里?该字段在您的 models.py 中定义为必填项:

crypto_prices = models.ForeignKey(CryptoPrices, on_delete=models.CASCADE)

解决方案:您需要在表单中包含字段'crypto_prices',或者在将表单保存到AssetView 之前设置它。像这样:

class资产形式(forms.ModelForm):

symbol = forms.ChoiceField(choices=tickers, required=True, label='')
amount = forms.DecimalField(decimal_places=2, max_digits=20, required=True, label='')
purchase_price = forms.DecimalField(decimal_places=2, max_digits=20, required=True, label='')

class Meta:
    model = CryptoAssets
    fields = (
        'symbol',
        'amount',
        'purchase_price',
        'crypto_prices'
    )

或者这样:

class AssetView(TemplateView):
    template_name = 'coinprices/my-dashboard.html'

    def get(self, request):
        form_a = AssetForm(prefix='form_a')
        return render(request, self.template_name, {'form_a': form_a})

    def post(self, request):
        form_a = AssetForm(request.POST, prefix='form_a')
        if form_a.is_valid():
            post = form_a.save(commit=False)
            post.crypto_prices = CryptoPrices.objects.get(id=someid) # this way with object
            post.crypto_prices_id = 1 # or this way with a integer
            post.save()
            form = AssetForm()
            args = {'form': form}
            return render(request, self.template_name, args)

        args = {'form_a': form_a}
        return render(request, self.template_name, args)