Форма не сохраняется в модели с двумя внешними ключами - Django
У меня проблемы с сохранением формы в модели, которая имеет два внешних ключа:
- User who is submitting the form
- The current price of the Crypto submitted.
Значения формы проходят через AssetView, но не сохраняются. Может ли кто-нибудь помочь, почему они не сохраняются. Я предоставил модели, представления, форму, HTML.
Django Models
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 View
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 Form
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'
Эта ошибка возникает потому, что вы пытаетесь сохранить таким образом:
post = form_a.cleaned_data
post.save()
Это неправильно, потому что clean_data - это dict, он содержит значения вашей формы в виде пар 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 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',
'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)