我正在将有效输入写入表单,以便将其保存到我的数据库中,但是,由于以下错误,它将无法保存:
追溯
内部响应中的C:\ Python34 \ lib \ site-packages \ django \ core \ handlers \ exception.py = get_response(request)... C:\ Python34 \ lib \ site-packages \ django \ core \ handlers \ base _get_response response中的.py = self.process_exception_by_middleware(e,request)C:\ Python34 \ lib \ site-packages \ django \ core \ handlers \ base.py in _get_response response = wrapped_callback(request,* callback_args,** callback_kwargs)G :\ NEA计算机科学\ mysite \ finance \ views.py in record_input if form.is_valid():#检查is_valid返回self是否有效C:\ Python34 \ lib \ site-packages \ django \ forms \ forms.py . is_bound而不是self.errors C:\ Python34 \ lib \ site-packages \ django \ forms \ forms.py错误self.full_clean()C:\ Python34 \ lib \ site-packages \ django \ forms \ forms.py in full_clean self._post_clean()C:\ Python34 \ lib \ site-packages \ django \ forms \ models.py in _post_clean self.instance.full_clean(exclude = exclude,validate_unique = False)C:\ Python34 \ lib \ site-packages在full_clean self.clean_fields中的\ django \ db \ models \ base.py(exc lude = exclude)c:\ Python34 \ lib \ site-packages \ django \ db \ models \ base.py in clean_fields setattr(self,f.attname,f.clean(raw_value,self))C:\ Python34 \ lib \ site-packages \ django \ db \ models \ fields__init __ . py in clean self.run_validators(value)C:\ Python34 \ lib \ site-packages \ django \ db \ models \ fields__init __ . py in run_validators v(value)G:\如果self.payment_method!=“Cash”和self.list_price == self.deposit:NE属计算机科学\ mysite \ finance \ models.py在validate_pay_method中:'Attribute':'str'对象没有属性'payment_method'
我认为这与PAYMENT_CHOICES及其 Value 类型有关,但我无法思考如何去做 . 谢谢!
代码:views.py
from django.http import HttpResponse
from django.shortcuts import render, redirect
from .models import Customer, Dealer
from .forms import CustomerForm
import datetime
# Lists all dealers and links them to their welcome page
def index(request):
dealer_list = Dealer.objects.order_by('name')
html = "<ol>"
for dealer in dealer_list:
html += "<li><a href='"+str(dealer.id)+"/'>"+dealer.name+"</a></li>"
html += "</ol>"
return HttpResponse(html)
# Welcome page for dealer
def welcome(request, dealer_id):
html = "Welcome!<br>"
# Link to results page
html += "<a href='/finance/"+str(dealer_id)+"/results/'>""See your performance""</a><br>"
# Link to input page
html += "<a href='/finance/"+str(dealer_id)+"/record_input/'>""Enter a new record""</a>"
return HttpResponse(html)
# Outputs the results of targets and statistics for a specific dealer
def results(request, dealer_id):
response = """Below are your results:
<input type='button' value='Print' onClick='javascript:window.print()' /><br>""" # Print button
response += "Finance deals made in the last 30 days: <br>"
date_threshold = datetime.date.today() - datetime.timedelta(days=30)
response += str(Customer.objects.filter(date_ordered=date_threshold))
response += "All your customers: "+str(Customer.objects.filter(dealers=dealer_id))+"<br>"
return HttpResponse(response)
# Input form for dealers needing to enter a record into the database
def record_input(request, dealer_id):
if request.method == "POST": # if this is a POST request, process the form data
form = CustomerForm(request.POST) # create a form instance and populate it with data from the request
if form.is_valid(): # check whether it's valid
form += Customer(finance_balance=Customer.validate_balance(), monthly_payment=Customer.validate_month_pay())
form.save() # Save it!
return redirect(success)
# if GET (or any other method), create a blank form
else:
form = CustomerForm()
return render(request, '../templates/finance/form_input.html', {'form': form})
def success(request, dealer_id):
submitted = "SUBMITTED - Thank you!"
return HttpResponse(submitted)
models.py
from django.db import models
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
from django.db.models import F
class Dealer(models.Model):
REGION_CHOICES = (
("Northern", "Northern"),
("Central", "Central"),
("Southern", "Southern")
)
def __str__(self):
return self.name
def validate_commission(self):
a = Customer().return_pay_method()
if a != "Cash":
self.commission = F("commission") + 200 # Dealer gains £200 for every financed deal
self.achieved_deals = F("achieved_deals") + 1 # Add 1 to achieved_deals for the dealer
if self.achieved_deals > self.target:
self.commission = F("commission") + 200 # If the target is achieved, gain £400 per deal
return int(self.commission), int(self.achieved_deals)
name = models.CharField(max_length=50)
region = models.CharField(max_length=8, choices=REGION_CHOICES)
target = models.PositiveIntegerField()
achieved_deals = models.PositiveIntegerField()
commission_earned = models.PositiveIntegerField(default=0)
class Product(models.Model):
def __str__(self):
return self.last_order
last_order = models.DateField(auto_now=True)
number_of_orders = models.PositiveIntegerField()
class Login(models.Model):
def __str__(self):
return self.user
def validate_password(self):
if len(self.password) < 8:
raise ValidationError(
_("Password is not long enough."))
dealer = models.OneToOneField(Dealer)
user = models.CharField(max_length=30)
password = models.CharField(max_length=50, validators=[validate_password])
class Customer(models.Model):
New = "New"
Used = "Used"
CONDITION_CHOICES = (
(New, "New"),
(Used, "Used")
)
MANUFACTURER_CHOICES = (
(1, "Citroën"),
(2, "Peugeot"),
(3, "DS")
)
PCP = "PCP" # Personal Contract Purchase
PCH = "PCH" # Personal Contract Hire
HP = "HP" # Hire Purchase
Cash = "Cash"
PAYMENT_CHOICES = (
(PCP, "PCP"),
(PCH, "PCH"),
(HP, "HP"),
(Cash, "Cash")
)
def __str__(self):
return "%s %s" % (self.first_name, self.last_name)
def return_pay_method(self):
return str(self.payment_method)
def return_list_price(self):
return int(self.list_price)
def return_deposit(self):
return int(self.deposit)
def validate_price(self): # List price cannot be less than the deposit
a = Customer.return_list_price(self)
b = Customer.return_deposit(self)
if a < b:
raise ValidationError(
_('List price cannot be greater than the deposit.'))
def validate_pay_method(self): # Ensures the correct payment method is used
if self.payment_method != "Cash" and self.list_price == self.deposit:
raise ValidationError(
_('Payment method is not cash.'))
def validate_month_pay(self): # Validates the monthly payment amount
numerator = self.list_price * ((self.interest_rate / 100) / 12) # Formula for monthly payment calculation
denominator = (1 - (1 + (self.interest_rate / 100) / 12)) ** (self.agreement_length * -1)
actual_monthly_payment = round((numerator / denominator), 2) # Rounds correct payments to 2 decimal places
self.monthly_payment = actual_monthly_payment
return self.monthly_payment
def validate_balance(self): # Validates the balance left to pay on finance
self.finance_balance = self.list_price - self.deposit
return int(self.finance_balance)
def validate_interest(self): # Validates to ensure the interest rate isn't negative
if self.interest_rate < 0:
raise ValidationError(
_("Interest rate must be positive."))
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
address_line_1 = models.CharField(max_length=100)
address_line_2 = models.CharField(max_length=100)
town = models.CharField(max_length=60) # Validated up to the longest town name in Britain
postcode = models.CharField(max_length=7)
dealers = models.ManyToManyField(Dealer)
date_ordered = models.DateField(auto_now_add=True)
manufacturers = models.ManyToManyField(Product, max_length=7, choices=MANUFACTURER_CHOICES)
vehicle_model = models.CharField(max_length=50, default="")
vehicle_reg = models.CharField(max_length=7, unique=True)
vehicle_condition = models.CharField(max_length=4, choices=CONDITION_CHOICES)
payment_method = models.CharField(max_length=4, choices=PAYMENT_CHOICES, validators=[validate_pay_method])
list_price = models.PositiveIntegerField(validators=[validate_price])
deposit = models.PositiveIntegerField()
agreement_length = models.PositiveIntegerField()
finance_balance = models.PositiveIntegerField(validators=[validate_balance])
monthly_payment = models.FloatField(validators=[validate_month_pay])
interest_rate = models.FloatField(validators=[validate_interest])
customer_informed = models.BooleanField()
forms.py
from django.forms import ModelForm
from .models import Customer
from django.core.exceptions import ValidationError
class CustomerForm(ModelForm): # The form for dealers to enter their completed sales
class Meta:
model = Customer
fields = ["first_name", "last_name", "address_line_1", "address_line_2", "town", "postcode", "dealers",
"manufacturers", "vehicle_model", "vehicle_reg", "vehicle_condition", "payment_method",
"list_price", "deposit", "agreement_length", "interest_rate", "customer_informed"]
# Hide the balance and monthly payment fields as they are calculated in models.py
3 回答
这样的事情应该有效:
您不能将实例方法用作验证器 . 它不作为绑定方法调用,只传递值来验证自身而不是实例,因此您不能使用它来与其他值进行比较 .
您应该使用单个
clean()
方法来执行所有验证,而不是使用这些单独的验证器方法 . 您可以pass a dictionary of field names to errors提出多个验证错误 .这里的问题是Django将字段的值传递给验证器 - 所以在这种情况下,self是一个字符串 .
您应该在表单中执行此验证,方法是在CustomerForm中实现clean_payment_method()方法