美文网首页白手起家学Python程序员
Django实践(七)房贷计算器

Django实践(七)房贷计算器

作者: 敖瑞_rick | 来源:发表于2018-09-07 16:21 被阅读48次

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


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

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

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

一个一个来:
输入:

  • 数据A1:购房合同价格(填空)
  • 数据A2:首付价格(填空)*首套首付35%,二套首付70%,普通住宅
  • 数据A3:贷款总额 = A1 - A2

这里可以计算出贷款总额

  • 公积金项目
    • 数据B1:贷款年限(填空题)
      * 告诉他计算方式:60 - 男方年龄 = 贷款年限 或者是 35 - 房龄=贷款年限,两种计算方式取小。数字小于15时可算作15
    • 数据B2:贷款利率确定(选择题)
      • 贷款年限:五年以上3.25,五年以下2.75
      • 是否二套房?是:上浮10%
    • 数据B3:公积金贷款数额(填空题)
      • (每月缴纳/账户余额)余额的30倍、每月技术0.412*贷款年限,不得大于50万,如果有补充公积金不大于60万;夫妻额度可相加。
  • 商贷项目
    • 数据C1:贷款年限(填空题)
      • 告诉他问银行
    • 数据C2:贷款利率(选择题) 基准利率4.9%
      • 需要咨询银行:是否首套房?是,下降10%
      • 是否二套房?是,上浮10%
    • 数据C3:贷款数额(填空题)单位:万
      • 问银行,还款数额不得超过夫妻两人月收入的一半

这里可以进行房贷的计算


前期税费准备……

  • 数据A4:上家买房合同价

  • 增值税计算:(选择题)是否是售后公房
    * 是:0
    * 否:5.38%*(A1 - A4)

  • 契税计算(太复杂了,先略。选择题)首套房/二套房,

  • 个税计算(太复杂了,略)


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

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

相关文章

  • Django实践(七)房贷计算器

    上一章我们在Django实践(六)房贷计算器中,达成了用户注册登陆系统,这样可以保证用户在自己的账号下录入数据,由...

  • Django实践(五)房贷计算器

    在上一章Django实践(四)房贷计算器中,我们建立了Django的基本项目,得到了一个简单的示例页面。 首先我们...

  • Django实践(一)房贷计算器

    前段时间我和太太筹备买房,并计划以首付+公积金贷款+商业贷款的方式进行交易。本来么,下定决心做一位“光荣的房奴”已...

  • Django实践(六)房贷计算器

    上一章我们在Django实践(五)房贷计算器中,达成了前后端基本的交互,恩……真的是相当的基础,仅仅是前端输入的参...

  • Django实践(三)房贷计算器

    在上一篇Django实践(二)房贷计算器中,我们分析了这个产品的产品逻辑,I/O的需求。那么在这一个阶段,我们要理...

  • Django实践(四)房贷计算器

    在上一章Django实践(三)房贷计算器中,我们理顺了相关的知识结构和开发步骤,那么我们现在开始。 1. 建立Dj...

  • Django实践(二)房贷计算器

    在上一篇Django实践(一)房贷计算器中,我们论证了整个项目的价值以及基本的项目结构。那么这一章我们来理顺一下产...

  • 房贷计算器

    最近房产版升级,需要重新制作房贷计算器的功能,主要参考了 房天下房贷计算器和安居客房贷计算器,两大平台的计算器。 ...

  • 房贷计算器

    //等额本息---------(每月还款数一致) //每月月供额=〔贷款本金×月利率×(1+月利率)^还款月数〕÷...

  • 房贷计算器

    一款免费、专业、实用的房贷计算器,2017年买房必备! 界面大气、整洁、优雅 贷款利率实时更新,计算精确 完美支持...

网友评论

  • 1274cbe05173:请问接下来的后台数据计算还会有吗,博主还会继续更新吗
    敖瑞_rick:@蕾仔_73ea 后台计算会有的,我现在还在寻找合适的技术方案。如果你有好的方案的话也可以推荐一下呀

本文标题:Django实践(七)房贷计算器

本文链接:https://www.haomeiwen.com/subject/euoplftx.html