最近在帮朋友改造他们公司的房屋租赁管理系统,发现市面上很多现成方案要么功能过剩要么扩展性不足。于是决定用Python技术栈从头搭建一个轻量级但足够灵活的系统。这个项目结合了Flask的轻便和Django的完善生态,特别适合中小型租赁公司或房东群体使用。
系统最核心的竞争力在于:
实测下来,这套系统比传统Excel管理效率提升3倍以上,特别是自动生成的电子合同模板,让我们的签约流程从平均3天缩短到2小时内完成。
选择Flask+Django混合方案主要基于以下考量:
前端交互层用Flask构建(优势):
后台管理用Django Admin改造(优势):
关键配置:通过Nginx反向代理实现两个应用的路由分发
location /admin { proxy_pass http://django:8000; }
location /
采用PostgreSQL作为主数据库,关键表结构设计如下:
房源表(properties)
sql复制CREATE TABLE properties (
id SERIAL PRIMARY KEY,
title VARCHAR(100) NOT NULL,
address JSONB NOT NULL, -- 包含经纬度、结构化地址
price INTEGER CHECK (price > 0),
status VARCHAR(20) CHECK (status IN ('available','rented','maintenance')),
landlord_id INTEGER REFERENCES users(id),
features JSONB -- 家电、装修等特征标签
);
租赁合同表(contracts)
sql复制CREATE TABLE contracts (
id UUID PRIMARY KEY,
property_id INTEGER REFERENCES properties(id),
tenant_id INTEGER REFERENCES users(id),
start_date DATE NOT NULL,
end_date DATE NOT NULL,
payment_terms JSONB NOT NULL, -- 支付周期、押金等条款
digital_signature TEXT -- Base64编码的签名图片
CHECK (end_date > start_date)
);
特别说明:使用JSONB类型存储非结构化数据,既保证查询效率又满足灵活扩展需求。
在search路由中实现基于多种权重的推荐逻辑:
python复制@app.route('/search')
def property_search():
# 获取用户偏好参数
price_range = request.args.get('price')
location = request.args.get('loc')
# 基础查询
query = Property.query.filter(
Property.status == 'available'
)
# 动态权重计算
if price_range:
min_p, max_p = map(int, price_range.split('-'))
query = query.filter(Property.price.between(min_p, max_p))
if location:
# 使用PostGIS地理查询
point = f"POINT({location['lng']} {location['lat']})"
query = query.order_by(
Property.address['coordinates'].ST_Distance(point)
)
# 添加个性化权重(需登录)
if current_user.is_authenticated:
favorite_features = current_user.preferences.get('features', [])
query = query.add_columns(
func.jsonb_array_length(
Property.features & favorite_features
).label('match_score')
).order_by(desc('match_score'))
return render_template('results.html', properties=query.limit(20).all())
安全签署流程的关键步骤:
核心的合同生成代码:
python复制from docxtpl import DocxTemplate
def generate_contract(property_id, tenant_id):
doc = DocxTemplate("templates/contract.docx")
context = {
'property': Property.query.get(property_id),
'landlord': User.query.get(Property.landlord_id),
'tenant': User.query.get(tenant_id),
'sign_date': datetime.now().strftime("%Y年%m月%d日")
}
doc.render(context)
return doc.get_docx()
使用Docker-compose编排三个核心服务:
yaml复制version: '3.8'
services:
flask:
build: ./flask_app
ports:
- "5000:5000"
environment:
- DB_URL=postgresql://user:pass@db:5432/rental
depends_on:
- db
django:
build: ./django_admin
ports:
- "8000:8000"
command: >
sh -c "python manage.py migrate &&
python manage.py runserver 0.0.0.0:8000"
db:
image: postgres:13
volumes:
- pg_data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: example
volumes:
pg_data:
针对高并发场景的缓存方案:
python复制def cache_response(timeout):
def decorator(f):
@wraps(f)
def wrapper(*args, **kwargs):
cache_key = f"{request.path}{hash(frozenset(request.args.items()))}"
data = redis.get(cache_key)
if not data:
data = f(*args, **kwargs)
redis.setex(cache_key, timeout, data)
return data
return wrapper
return decorator
@app.route('/property/<int:id>')
@cache_response(300) # 5分钟缓存
def property_detail(id):
return render_template('detail.html',
property=Property.query.get_or_404(id))
实施的多层防护方案:
字段级加密:
python复制class EncryptedString(TypeDecorator):
impl = TEXT
def process_bind_param(self, value, dialect):
return fernet.encrypt(value.encode())
def process_result_value(self, value, dialect):
return fernet.decrypt(value).decode()
审计日志:
权限控制矩阵:
| 操作类型 | 房东 | 租客 | 管理员 |
|---|---|---|---|
| 修改房源信息 | ✓ | ✗ | ✓ |
| 查看联系方式 | ✓ | ✓* | ✓ |
| 生成合同 | ✓ | ✗ | ✓ |
| 修改支付信息 | ✗ | ✓ | ✓ |
- 仅限已签约租客查看对应房东联系方式
早期出现的典型问题:多个用户同时预订同一房源导致超售。
解决方案:
python复制with db.session.begin_nested():
property = Property.query.filter_by(
id=property_id,
status='available'
).with_for_update().first()
if property:
property.status = 'reserved'
db.session.commit()
python复制class Property(db.Model):
__tablename__ = 'properties'
id = db.Column(db.Integer, primary_key=True)
version_id = db.Column(db.Integer, nullable=False)
__mapper_args__ = {
'version_id_col': version_id
}
遇到的支付状态同步延迟问题,采用以下改进方案:
python复制class PaymentStateMachine:
states = ['pending', 'processing', 'verified', 'failed']
def __init__(self, payment):
self.payment = payment
def verify(self, transaction_id):
if self.payment.state != 'processing':
raise InvalidStateError
# 调用支付网关API验证
if api.verify(transaction_id):
self.payment.state = 'verified'
else:
self.payment.state = 'failed'
推荐的功能扩展方向:
关键配置示例:
python复制from wechat import WeChat
wechat = WeChat(
appid='YOUR_APPID',
secret='YOUR_SECRET',
token='YOUR_TOKEN'
)
@app.route('/wechat/auth')
def wechat_auth():
code = request.args.get('code')
user_info = wechat.get_user_info(code)
# 与本地用户系统对接...
使用Pandas实现的经营分析示例:
python复制def generate_monthly_report():
df = pd.read_sql("""
SELECT date_trunc('month', start_date) AS month,
count(*) AS contracts,
sum(price) AS revenue
FROM contracts
GROUP BY 1 ORDER BY 1
""", db.engine)
# 生成可视化
ax = df.plot(x='month', y=['contracts', 'revenue'],
kind='bar', secondary_y='revenue')
return ax.get_figure()
这套系统经过三个月的实际运行,日均处理200+次房源查询和约30份合同签署。最大的收获是认识到:在业务系统开发中,与其追求技术新颖性,不如把80%精力放在解决那些看似简单的业务异常流程上——比如如何处理租客临时换人、怎样计算提前解约的违约金这些实际场景中的琐碎问题。