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)