上一章我们在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万;夫妻额度可相加。
- 数据B1:贷款年限(填空题)
- 商贷项目
- 数据C1:贷款年限(填空题)
- 告诉他问银行
- 数据C2:贷款利率(选择题) 基准利率4.9%
- 需要咨询银行:是否首套房?是,下降10%
- 是否二套房?是,上浮10%
- 数据C3:贷款数额(填空题)单位:万
- 问银行,还款数额不得超过夫妻两人月收入的一半
- 数据C1:贷款年限(填空题)
这里可以进行房贷的计算了
前期税费准备……
-
数据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
好的,本章我们成功的利用一对一外键把用户表扩展了,给输入房贷信息建立了新的数据库,下一步我们要对这些数据进行处理,让用户真正得到有价值的信息。
网友评论