首页 文章

Django 1.11.6:'str'对象没有属性'payment_method'

提问于
浏览
1

我正在将有效输入写入表单,以便将其保存到我的数据库中,但是,由于以下错误,它将无法保存:

追溯

内部响应中的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 回答

  • 0

    这样的事情应该有效:

    from django import forms
    from .models import Customer
    from django.core.exceptions import ValidationError
    
    
    class CustomerForm(forms.ModelForm):
        def clean(self):
            super(CustomerForm, self).clean()
    
            if self.cleaned_data['payment_method'] != "Cash" and self.cleaned_data['list_price'] == self.cleaned_data['deposit']:
                raise forms.ValidationError({'payment_method': _('Payment method is not cash.')})
    
        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"]
    
  • 0

    您不能将实例方法用作验证器 . 它不作为绑定方法调用,只传递值来验证自身而不是实例,因此您不能使用它来与其他值进行比较 .

    您应该使用单个 clean() 方法来执行所有验证,而不是使用这些单独的验证器方法 . 您可以pass a dictionary of field names to errors提出多个验证错误 .

  • 0

    这里的问题是Django将字段的值传递给验证器 - 所以在这种情况下,self是一个字符串 .

    您应该在表单中执行此验证,方法是在CustomerForm中实现clean_payment_method()方法

相关问题