白手起家学Python程序员

Django实践(七)房贷计算器

2018-09-07  本文已影响48人  敖瑞_rick

上一章我们在Django实践(六)房贷计算器中,达成了用户注册登陆系统,这样可以保证用户在自己的账号下录入数据,由我们提供计算结果。
本章我们将开始建立一个用户的房产数据提交入口,让用户可以按部就班的填写相关参数,这离我们计算房贷又更近了一步!


首先我们以models、view、html的顺序来调整:最好是形成注册、登陆、退出的闭环,这样对用户来说友善一些。
拓展用户表:

首先,为了数据的输入的便捷性,我们需要对参数进行分类,分类遵循以下规划:Django实践(二)房贷计算器

项目 描述 预期输出 方法
公积金贷款计算 贷款利率(优惠/无优惠,二套房上浮10%)五年以上3.25,五年以下2.75;贷款年限(贷款年限条件,主贷人/房龄年限);公积金贷款限额(每月缴纳/账户余额)余额的30倍、每月技术0.412*贷款年限,不得大于50万,如果有补充公积金不大于60万;夫妻额度相加 可贷款年限;可贷款金额;公积金月供; 年限计算方法;可贷款金额方法;月供计算方法
商业贷款计算 贷款基准利率4.9%(受到一套房\二套房影响)二套房利率上浮10%,一套房可能打九折;贷款年限(无以银行为准);贷款数额(自定);还款方式(等额本息/等额本金(有可能需要提供明细)/先息后本比较少见) 贷款金额;每年度月供; 可贷款金额方法;每年度月供方法
契税计算 房子属性基本状况、人的属性基本状况;首套房/二套房分别计算;合同价-增值税 一定比例 简单方法
个税 普通住宅/非普通;满五唯一/不满或不唯一 一定比例 简单方法
增值税(及附加税) 5.38%*(买价-上家买价)/售后公房无 简单方法
中介费 自定
* 是否涉及到做低做高合同金额亦需要纳入考虑 合同价=购房房产总价;做低的价值:少增值税、少贷款额度、多首付;做高的价值:适用无增值税房子,多贷款额度,少首付 暂不考虑

一个一个来:
输入:

这里可以计算出贷款总额

这里可以进行房贷的计算


前期税费准备……


要保证我们输入的参数和用户挂钩(我们建立用户注册系统就是为了这个),我们可以增加一对一用户模型。
(一对一的相关知识可以看这里OneToOneField)

myapp/models.py

from django.db import models
import datetime
from django.utils import timezone
from django.contrib.auth.models import User
from django.conf import settings
# Create your models here.

class User(models.Model):
    name = models.CharField(max_length=50)
    password = models.CharField(max_length=50)
    pub_date = models.DateTimeField('date published',blank=True)
    
    def __str__(self):
        return "%s the user" % self.name

class Profile(models.Model):
    user = models.OneToOneField(
        User,
        on_delete=models.CASCADE,
        primary_key =True,
    )
    A1 = models.IntegerField(default=0,blank=True)
    A2 = models.IntegerField(default=0,blank=True)
    B1 = models.IntegerField(default=0,blank=True)
    B2 = models.IntegerField(default=0,blank=True)
    B3 = models.IntegerField(default=0,blank=True)
    C1 = models.IntegerField(default=0,blank=True)
    C2 = models.IntegerField(default=0,blank=True)
    C3 = models.IntegerField(default=0,blank=True)
    
    def __str__(self):
        return "%s the profile" % self.user.name

Profile是User的拓展,用以储存相关的房贷数据,由于我们的计划是一个账户对应一批数据,因此我们使用OneToOneField()外键来处理。

下面是views.py

from django.http import HttpResponse,Http404,HttpResponseRedirect,response
from django.shortcuts import render_to_response,get_object_or_404, render
# Create your views here.
from django.template import RequestContext
from .models import User,Profile
from django.urls import reverse
from django.views import generic
from django import forms

class IndexView(generic.ListView):
    pass


class DetailView(generic.DetailView):
    pass


class ResultsView(generic.DetailView):
    pass


#表单
class UserForm(forms.Form): 
    name = forms.CharField(label='用户名',max_length=100)
    password = forms.CharField(label='密码',widget=forms.PasswordInput())

class ProfileForm(forms.Form):
    A1 = forms.IntegerField(label='A1')
    A2 = forms.IntegerField(label='A2')
    B1 = forms.IntegerField(label='B1')
    B2 = forms.IntegerField(label='B2')
    B3 = forms.IntegerField(label='B3')
    C1 = forms.IntegerField(label='C1')
    C2 = forms.IntegerField(label='C2')
    C3 = forms.IntegerField(label='C3')

#注册
def regist(req):
    if req.method == 'POST':
        uf = UserForm(req.POST)
        if uf.is_valid():
            #获得表单数据
            name = uf.cleaned_data['name']
            password = uf.cleaned_data['password']
            uname = req.GET.get('name')
            users = User.objects.filter(name=name)
            if len(users)>0:
                return HttpResponse('用户已存在')
            else:
                #添加到数据库
                User.objects.create(name= name,password=password)
                return HttpResponse('注册成功!你现在可以返回登陆') #这是原教程
                # return render(req,'home/index.html' ,{'name':name,}) 
    else:
        uf = UserForm()
        return render(req,'home/regist.html',{'uf':uf})

#登陆
def login(req):
    if req.method == 'POST':
        uf = UserForm(req.POST)
        if uf.is_valid():
            #获取表单用户密码
            name = uf.cleaned_data['name']
            password = uf.cleaned_data['password']
            #获取的表单数据与数据库进行比较
            user = User.objects.filter(name__exact = name,password__exact = password)
            if user:
                #比较成功,跳转index
                response = HttpResponseRedirect('/home/index/',{'name':name,})
                #将name写入浏览器cookie,失效时间为3600
                response.set_cookie('name',name,3600)
                return response #网络原文,引发登陆不代入cookie错误
                # return render(req,'home/index.html' ,{'name':name,}) 
            else:
                #比较失败,还在login
                return HttpResponseRedirect('/home/login/')
    else:
        uf = UserForm()
        return render(req,'home/login.html',{'uf':uf})



#登陆成功
def index(req):
    name = req.COOKIES.get('name',None)
    print (name)
    # 获得已输入的房贷信息
    u1 = User.objects.get(name=name)
    p1 = Profile.objects.get(user_id=u1.id)
    if req.method == 'POST':
        uf = ProfileForm(req.POST)
        if uf.is_valid():
            #获得表单数据
            A1 = uf.cleaned_data['A1']
            A2 = uf.cleaned_data['A2']
            B1 = uf.cleaned_data['B1']
            B2 = uf.cleaned_data['B2']
            B3 = uf.cleaned_data['B3']
            C1 = uf.cleaned_data['C1']
            C2 = uf.cleaned_data['C2']
            C3 = uf.cleaned_data['C3']
            #添加到数据库
            p1.A1=A1
            p1.A2=A2
            p1.B1=B1
            p1.B2=B2
            p1.B3=B3
            p1.C1=C1
            p1.C2=C2
            p1.C3=C3
            p1.save()
            return render(req,'home/detail.html',{'p1':p1}) 
            # return HttpResponse
        else:pass
    else:
        uf = ProfileForm()
        return render(req,'home/index.html',{'uf':uf})

#退出
def logout(req):
    response = HttpResponse('logout !!')
    #清理cookie里保存name
    response.delete_cookie('name')
    return response

代码有点多,我也是调整了很久才把关系理顺,其中要注意的是index页面就可以完成所有页面的输入,并将相关数据在detail页面进行展示。

下面是index.html

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title></title>
</head>

<body>
    <h1>基本数据输入:</h1>
    {% csrf_token %}
    <body>
        <p>请输入相关信息</p>
        <a href="http://127.0.0.1:8000/home/login/">登陆</a>
        <a href="http://127.0.0.1:8000/home/regist/">注册</a>
        <a href="http://127.0.0.1:8000/home/logout/">退出</a>
        <p><b>用户输入房贷相关信息:</b></p>
    <form method = 'post' enctype="multipart/form-data">
        {% csrf_token %}
        <div class="fieldWrapper">
            {{ uf.A1.errors }}
            <label for="{{ uf.A1.id_for_label }}">数据A1</label>
            {{ uf.A1 }}
        </div>
        <div class="fieldWrapper">
            {{ uf.A2.errors }}
            <label for="{{ uf.A2.id_for_label }}">数据A2</label>
            {{ uf.A2 }}
        </div>
        <div class="fieldWrapper">
            {{ uf.B1.errors }}
            <label for="{{ uf.B1.id_for_label }}">数据B1</label>
            {{ uf.B1 }}
        </div>
        <div class="fieldWrapper">
            {{ uf.A2.errors }}
            <label for="{{ uf.B2.id_for_label }}">数据B2</label>
            {{ uf.B2 }}
        </div>
        <div class="fieldWrapper">
            {{ uf.B3.errors }}
            <label for="{{ uf.B3.id_for_label }}">数据B3</label>
            {{ uf.B3 }}
        </div>
        <div class="fieldWrapper">
            {{ uf.C1.errors }}
            <label for="{{ uf.C1.id_for_label }}">数据C1</label>
            {{ uf.C1 }}
        </div>
        <div class="fieldWrapper">
            {{ uf.C2.errors }}
            <label for="{{ uf.C1.id_for_label }}">数据C2</label>
            {{ uf.C2 }}
        </div>
        <div class="fieldWrapper">
            {{ uf.C3.errors }}
            <label for="{{ uf.C3.id_for_label }}">数据C3</label>
            {{ uf.C3 }}
        </div>
        <input type="submit" value = "ok" />
    </form>

</body>
</html>

效果:


index页面效果

建立detail.html页面:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title></title>
</head>

<body>
    <h1>已录入的数据:</h1>
    <form method = 'post' enctype="multipart/form-data">
        {% csrf_token %}
        <div class="fieldWrapper">
            {{ p1.A1.errors }}
            <label for="{{ p1.A1.id_for_label }}">数据A1</label>
            {{ p1.A1 }}
        </div>
        <div class="fieldWrapper">
            {{ p1.A2.errors }}
            <label for="{{ p1.A2.id_for_label }}">数据A2</label>
            {{ p1.A2 }}
        </div>
        <div class="fieldWrapper">
            {{ p1.B1.errors }}
            <label for="{{ p1.B1.id_for_label }}">数据B1</label>
            {{ p1.B1 }}
        </div>
        <div class="fieldWrapper">
            {{ p1.A2.errors }}
            <label for="{{ p1.B2.id_for_label }}">数据B2</label>
            {{ p1.B2 }}
        </div>
        <div class="fieldWrapper">
            {{ p1.B3.errors }}
            <label for="{{ p1.B3.id_for_label }}">数据B3</label>
            {{ p1.B3 }}
        </div>
        <div class="fieldWrapper">
            {{ p1.C1.errors }}
            <label for="{{ p1.C1.id_for_label }}">数据C1</label>
            {{ p1.C1 }}
        </div>
        <div class="fieldWrapper">
            {{ p1.C2.errors }}
            <label for="{{ p1.C1.id_for_label }}">数据C2</label>
            {{ p1.C2 }}
        </div>
        <div class="fieldWrapper">
            {{ p1.C3.errors }}
            <label for="{{ p1.C3.id_for_label }}">数据C3</label>
            {{ p1.C3 }}
        </div>
    </form>
    <br>
    <p>数据我还要再改改</p>
    <input type="button" value="后退" onclick="history.go(-1)" />
    <p>我已经满意了</p>
    <a href="http://127.0.0.1:8000/home/logout/">退出</a>
    </body>
</html>

myapp/urls.py:

from django.conf.urls import url
from home import views
from django.urls import path
 
urlpatterns = [
    url(r'^$', views.login, name='login'),
    url(r'^login/$',views.login,name = 'login'),
    url(r'^regist/$',views.regist,name = 'regist'),
    url(r'^index/$',views.index,name = 'index'),
    url(r'^logout/$',views.logout,name = 'logout'),
    # url(r'^detail/$',views.detail,name='detail'),
]

效果:


image.png

接下来调整一下admin.py:
myapp/admin.py:

from django.contrib import admin
from .models import Profile, User

class ProfileInline(admin.TabularInline):
    model = Profile
    # extra = 3

class UserAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,{'fields': ['name']}),
        ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
    ]
    inlines = [ProfileInline]
    list_display = ('name', 'pub_date')
    list_filter = ['pub_date']
    search_fields = ['name']

admin.site.register(User, UserAdmin)

效果:


image.png

好的,本章我们成功的利用一对一外键把用户表扩展了,给输入房贷信息建立了新的数据库,下一步我们要对这些数据进行处理,让用户真正得到有价值的信息。

上一篇 下一篇

猜你喜欢

热点阅读