File size: 8,484 Bytes
d2f89d7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
#!/usr/bin/env python
"""
初始化数据库脚本
1. 导入标准MBTI 93题题库
2. 创建Django后台管理员账号
"""
import os
import sys
import csv

# 添加项目根目录到Python路径
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, BASE_DIR)

import django

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mbti_site.settings')
django.setup()

from django.contrib.auth import get_user_model
from mbti.models import Question, Questionnaire, TypeProfile

User = get_user_model()


def load_standard_questions(csv_path):
    """加载标准MBTI 93题,合并成对的单词选择"""
    items = []
    paired_questions = {}  # 用于存储成对的题目 {question_number: {dimension, options, order}}
    processed_questions = set()  # 记录已处理的题目编号,避免重复
    
    with open(csv_path, 'r', encoding='utf-8-sig') as f:
        reader = csv.DictReader(f)
        for row_num, row in enumerate(reader, start=2):  # 从第2行开始(第1行是标题)
            try:
                text = (row.get('text') or '').strip().strip('"')  # 去除引号
                dimension = (row.get('dimension') or '').strip().upper()
                keyed_pole = (row.get('keyed_pole') or '').strip().upper()
                
                # 安全地解析 question_number
                qn_str = (row.get('question_number') or '').strip()
                try:
                    question_number = int(qn_str) if qn_str else 0
                except ValueError:
                    print(f"[WARN] 第 {row_num} 行 question_number 格式错误: {qn_str},跳过")
                    continue
                
                scoring_rule = (row.get('scoring_rule') or '').strip()
                
                # 安全地解析 weight
                weight_str = (row.get('weight') or '1').strip()
                try:
                    weight = int(weight_str) if weight_str else 1
                except ValueError:
                    weight = 1
                
                # 安全地解析 order
                order_str = (row.get('order') or str(question_number)).strip()
                try:
                    order = int(order_str) if order_str else question_number
                except ValueError:
                    order = question_number
                
                if not text or dimension not in ['IE', 'SN', 'TF', 'JP']:
                    print(f"[WARN] 第 {row_num} 行数据不完整,跳过")
                    continue
                
                # 判断是否是成对的单词选择(第二部分:27-73题,且文本中没有A)或B))
                is_paired_choice = (27 <= question_number <= 73) and "A)" not in text and "B)" not in text
                
                if is_paired_choice:
                    # 成对的单词选择,需要合并
                    if question_number not in paired_questions:
                        paired_questions[question_number] = {
                            'dimension': dimension,
                            'options': [],
                            'order': order,
                        }
                    
                    # 确定这是A选项还是B选项
                    is_option_a = scoring_rule.endswith('_A')
                    
                    paired_questions[question_number]['options'].append({
                        'text': text,
                        'keyed_pole': keyed_pole,
                        'is_a': is_option_a,
                        'scoring_rule': scoring_rule,
                    })
                else:
                    # 第一部分和第三部分,直接添加(但要去除已处理的成对题目)
                    if question_number not in processed_questions:
                        items.append({
                            'text': text,
                            'dimension': dimension,
                            'keyed_pole': keyed_pole,
                            'question_number': question_number,
                            'scoring_rule': scoring_rule,
                            'weight': weight,
                            'order': order,
                        })
                        processed_questions.add(question_number)
            except Exception as e:
                print(f"[ERROR] 第 {row_num} 行处理失败: {e},跳过")
                continue
    
    # 处理成对的题目,合并成一个题目
    for q_num, pair_data in sorted(paired_questions.items()):
        options = pair_data['options']
        if len(options) == 2:
            # 按A/B顺序排序(A在前)
            options.sort(key=lambda x: not x['is_a'])
            
            # 构建合并后的题目文本
            combined_text = f"你更容易喜欢或倾向哪一个词? A) {options[0]['text']} B) {options[1]['text']}"
            
            items.append({
                'text': combined_text,
                'dimension': pair_data['dimension'],
                'keyed_pole': options[0]['keyed_pole'],  # 使用第一个选项的keyed_pole
                'question_number': q_num,
                'scoring_rule': options[0]['scoring_rule'],
                'weight': 1,
                'order': pair_data['order'],
            })
            processed_questions.add(q_num)
        else:
            print(f"[WARN] 题目 {q_num} 的选项数量不是2(实际{len(options)}),跳过合并")
    
    # 按order排序
    items.sort(key=lambda x: x['order'])
    print(f"[INFO] 合并后共 {len(items)} 题(标准MBTI应为93题)")
    return items


def import_questions():
    """导入标准MBTI题库(从JSON文件)"""
    print("=" * 50)
    print("开始导入标准MBTI题库...")
    print("=" * 50)
    
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))  # 项目根目录
    json_path = os.path.join(BASE_DIR, 'data', 'questions_standard_mbti_93.json')
    
    if not os.path.exists(json_path):
        print(f"❌ 题库文件不存在:{json_path}")
        return False
    
    # 使用JSON导入脚本
    try:
        from database_management.add_questions_from_json import import_questions_from_json
        import_questions_from_json(json_path)
        return True
    except Exception as e:
        print(f"❌ 导入失败:{e}")
        import traceback
        traceback.print_exc()
        return False


def create_admin_user():
    """创建Django后台管理员账号"""
    print("\n" + "=" * 50)
    print("创建Django后台管理员账号...")
    print("=" * 50)
    
    USERNAME = 'admin'
    EMAIL = 'admin@example.com'
    PASSWORD = 'admin@123..'
    
    # 检查用户是否已存在
    if User.objects.filter(username=USERNAME).exists():
        print(f"用户 {USERNAME} 已存在,更新密码...")
        user = User.objects.get(username=USERNAME)
        user.set_password(PASSWORD)
        user.is_staff = True
        user.is_superuser = True
        user.save()
        print(f"✓ 已更新用户 {USERNAME} 的密码")
    else:
        # 创建新用户
        user = User.objects.create_superuser(
            username=USERNAME,
            email=EMAIL,
            password=PASSWORD
        )
        print(f"✓ 已创建管理员账号:{USERNAME}")
    
    print(f"\n管理员账号信息:")
    print(f"  用户名: {USERNAME}")
    print(f"  密码: {PASSWORD}")
    print(f"  访问地址: http://localhost:8989/admin/")


def main():
    """主函数"""
    print("\n" + "=" * 50)
    print("数据库初始化脚本")
    print("=" * 50)
    
    # 1. 导入题库
    if not import_questions():
        print("❌ 题库导入失败,终止初始化")
        sys.exit(1)
    
    # 2. 创建管理员账号
    create_admin_user()
    
    print("\n" + "=" * 50)
    print("✅ 数据库初始化完成!")
    print("=" * 50)
    print("\n下一步:")
    print("1. 访问 http://localhost:8989/admin/ 登录管理后台")
    print("2. 使用账号 admin / admin@123.. 登录")
    print("3. 可以导入16种人格类型数据:python populate_personality_data.py")


if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        print("\n\n❌ 操作被用户中断")
        sys.exit(1)
    except Exception as e:
        print(f"\n\n❌ 发生错误: {e}")
        import traceback
        traceback.print_exc()
        sys.exit(1)