duqing2026's picture
Enhance: Add Templates, more Types, and LocalStorage persistence
7a44571
from flask import Flask, render_template, request, jsonify
from faker import Faker
import random
import traceback
app = Flask(__name__)
# Resolve conflict with Vue.js
app.jinja_env.variable_start_string = '[['
app.jinja_env.variable_end_string = ']]'
fake = Faker('zh_CN') # Default to Chinese
# Helper for credit card
def get_credit_card(f):
return f.credit_card_number()
# Mapping of frontend types to Faker methods or custom logic
FIELD_TYPES = {
'name': {'label': '姓名 (Name)', 'method': lambda f: f.name()},
'address': {'label': '地址 (Address)', 'method': lambda f: f.address()},
'email': {'label': '邮箱 (Email)', 'method': lambda f: f.email()},
'phone_number': {'label': '手机号 (Phone)', 'method': lambda f: f.phone_number()},
'company': {'label': '公司 (Company)', 'method': lambda f: f.company()},
'job': {'label': '职位 (Job)', 'method': lambda f: f.job()},
'ssn': {'label': '身份证号 (ID Card)', 'method': lambda f: f.ssn()},
'date_this_year': {'label': '今年日期 (Date)', 'method': lambda f: f.date_this_year().isoformat()},
'date_of_birth': {'label': '出生日期 (DOB)', 'method': lambda f: f.date_of_birth().isoformat()},
'city': {'label': '城市 (City)', 'method': lambda f: f.city()},
'text': {'label': '短句 (Sentence)', 'method': lambda f: f.sentence()},
'paragraph': {'label': '段落 (Paragraph)', 'method': lambda f: f.paragraph()},
'integer': {'label': '整数 (Integer)', 'method': lambda f: random.randint(0, 100)},
'boolean': {'label': '布尔值 (Boolean)', 'method': lambda f: random.choice([True, False])},
'uuid': {'label': 'UUID', 'method': lambda f: f.uuid4()},
'ipv4': {'label': 'IPv4地址', 'method': lambda f: f.ipv4()},
'url': {'label': 'URL链接', 'method': lambda f: f.url()},
'image_url': {'label': '图片链接 (Image URL)', 'method': lambda f: f.image_url()},
'user_agent': {'label': 'User Agent', 'method': lambda f: f.user_agent()},
'credit_card': {'label': '信用卡号', 'method': get_credit_card},
'color': {'label': '颜色 (Color)', 'method': lambda f: f.color_name()},
'file_name': {'label': '文件名 (Filename)', 'method': lambda f: f.file_name()},
'isbn': {'label': 'ISBN', 'method': lambda f: f.isbn13()},
}
@app.route('/')
def index():
return render_template('index.html')
@app.route('/api/types')
def get_types():
# Sort by label for better UI
sorted_types = sorted(
[{'value': k, 'label': v['label']} for k, v in FIELD_TYPES.items()],
key=lambda x: x['label']
)
return jsonify(sorted_types)
@app.route('/api/generate', methods=['POST'])
def generate_data():
try:
data = request.json
if not data:
return jsonify({'error': 'No data provided'}), 400
count = data.get('count', 10)
# Enforce limits
if not isinstance(count, int) or count < 1:
count = 10
count = min(count, 1000) # Limit to 1000 for preview/safety
schema = data.get('schema', [])
if not schema:
return jsonify({'error': 'Schema is empty'}), 400
results = []
for _ in range(count):
row = {}
for field in schema:
field_name = field.get('name')
field_type = field.get('type')
# Skip invalid fields
if not field_name:
continue
if field_type in FIELD_TYPES:
try:
# Handle special cases if needed (e.g. ranges for integers)
if field_type == 'integer':
min_val = int(field.get('min', 0))
max_val = int(field.get('max', 100))
if min_val > max_val: min_val, max_val = max_val, min_val
row[field_name] = random.randint(min_val, max_val)
else:
row[field_name] = FIELD_TYPES[field_type]['method'](fake)
except Exception:
# Fallback if specific generator fails
row[field_name] = None
else:
row[field_name] = None
results.append(row)
return jsonify(results)
except Exception as e:
traceback.print_exc()
return jsonify({'error': str(e)}), 500
if __name__ == '__main__':
app.run(host='0.0.0.0', port=7860, debug=True)