美文网首页白手起家学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

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

    相关文章

      网友评论

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

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

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