feat(家庭成员): 添加家庭成员模型并关联感悟和计划
添加家庭成员模型(FamilyMember)并关联到感悟记录(InsightRecord)和今日计划(TodayPlan) 修改相关表单、视图和模板以支持发言人功能 添加数据库迁移文件和初始化脚本 更新报告模板显示发言人信息
This commit is contained in:
@@ -6,7 +6,8 @@ from .models import (
|
||||
InsightRecord,
|
||||
FamilyTask,
|
||||
TodayPlan,
|
||||
SystemConfig
|
||||
SystemConfig,
|
||||
FamilyMember
|
||||
)
|
||||
|
||||
class ReadingRecordForm(forms.ModelForm):
|
||||
@@ -27,8 +28,9 @@ class InsightRecordForm(forms.ModelForm):
|
||||
"""感悟记录表单"""
|
||||
class Meta:
|
||||
model = InsightRecord
|
||||
fields = ['content', 'file']
|
||||
fields = ['speaker', 'content', 'file']
|
||||
widgets = {
|
||||
'speaker': forms.Select(attrs={'class': 'form-select'}),
|
||||
'content': forms.Textarea(attrs={'class': 'form-control', 'rows': 5, 'placeholder': '请输入感悟'}),
|
||||
'file': forms.FileInput(attrs={'class': 'form-control'}),
|
||||
}
|
||||
@@ -50,9 +52,10 @@ class TodayPlanForm(forms.ModelForm):
|
||||
"""今日计划表单"""
|
||||
class Meta:
|
||||
model = TodayPlan
|
||||
fields = ['date', 'content', 'priority', 'type', 'status']
|
||||
fields = ['date', 'speaker', 'content', 'priority', 'type', 'status']
|
||||
widgets = {
|
||||
'date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}),
|
||||
'speaker': forms.Select(attrs={'class': 'form-select'}),
|
||||
'content': forms.Textarea(attrs={'class': 'form-control', 'rows': 3, 'placeholder': '请输入计划内容'}),
|
||||
'priority': forms.Select(attrs={'class': 'form-select'}),
|
||||
'type': forms.Select(attrs={'class': 'form-select'}),
|
||||
|
||||
38
core/migrations/0005_initial_speaker.py
Normal file
38
core/migrations/0005_initial_speaker.py
Normal file
@@ -0,0 +1,38 @@
|
||||
# Generated by Django 5.1.4
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0004_systemconfig_sender_email'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='FamilyMember',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=20, unique=True, verbose_name='姓名')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
|
||||
('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': '家庭成员',
|
||||
'verbose_name_plural': '家庭成员',
|
||||
'ordering': ['name'],
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='insightrecord',
|
||||
name='speaker',
|
||||
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='core.familymember', verbose_name='发言人'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='todayplan',
|
||||
name='speaker',
|
||||
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='core.familymember', verbose_name='发言人'),
|
||||
),
|
||||
]
|
||||
@@ -71,6 +71,20 @@ class PlanType(models.Model):
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class FamilyMember(models.Model):
|
||||
"""家庭成员"""
|
||||
name = models.CharField(max_length=20, unique=True, verbose_name="姓名")
|
||||
created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
|
||||
updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
|
||||
|
||||
class Meta:
|
||||
verbose_name = "家庭成员"
|
||||
verbose_name_plural = "家庭成员"
|
||||
ordering = ['name']
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class ReadingRecord(models.Model):
|
||||
"""阅读记录表"""
|
||||
date = models.DateField(default=timezone.now, verbose_name="日期")
|
||||
@@ -95,6 +109,7 @@ class InsightRecord(models.Model):
|
||||
"""感悟记录表"""
|
||||
date = models.DateField(default=timezone.now, verbose_name="日期")
|
||||
content = models.TextField(verbose_name="内容")
|
||||
speaker = models.ForeignKey(FamilyMember, on_delete=models.CASCADE, verbose_name="发言人")
|
||||
file = models.FileField(upload_to='insight_files/', blank=True, null=True, verbose_name="上传文件")
|
||||
created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
|
||||
updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
|
||||
@@ -129,6 +144,7 @@ class TodayPlan(models.Model):
|
||||
"""今日计划表"""
|
||||
date = models.DateField(default=timezone.now, verbose_name="日期")
|
||||
content = models.TextField(verbose_name="内容")
|
||||
speaker = models.ForeignKey(FamilyMember, on_delete=models.SET_NULL, null=True, blank=True, verbose_name="发言人")
|
||||
priority = models.ForeignKey(Priority, on_delete=models.CASCADE, default=2, verbose_name="优先级")
|
||||
type = models.ForeignKey(PlanType, on_delete=models.CASCADE, default=4, verbose_name="类型")
|
||||
status = models.ForeignKey(Status, on_delete=models.CASCADE, default=1, verbose_name="状态")
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
{% if yesterday_insight %}
|
||||
<ul>
|
||||
{% for insight in yesterday_insight %}
|
||||
<li>{{ insight.content }}</li>
|
||||
<li><strong>{{ insight.speaker.name }}:</strong>{{ insight.content }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
@@ -148,6 +148,7 @@
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>发言人</th>
|
||||
<th>类型</th>
|
||||
<th>内容</th>
|
||||
<th>优先级</th>
|
||||
@@ -157,6 +158,7 @@
|
||||
<tbody>
|
||||
{% for plan in today_plan %}
|
||||
<tr>
|
||||
<td>{{ plan.speaker.name }}</td>
|
||||
<td>{{ plan.get_type_display }}</td>
|
||||
<td>{{ plan.content }}</td>
|
||||
<td>{{ plan.get_priority_display }}</td>
|
||||
|
||||
@@ -39,7 +39,8 @@ from .models import (
|
||||
InsightRecord,
|
||||
FamilyTask,
|
||||
TodayPlan,
|
||||
SystemConfig
|
||||
SystemConfig,
|
||||
FamilyMember
|
||||
)
|
||||
from .forms import (
|
||||
ReadingRecordForm,
|
||||
@@ -147,6 +148,7 @@ def delete_reading(request, pk):
|
||||
# 添加感悟记录
|
||||
def add_insight(request):
|
||||
"""添加感悟记录"""
|
||||
family_members = FamilyMember.objects.all()
|
||||
if request.method == 'POST':
|
||||
form = InsightRecordForm(request.POST, request.FILES)
|
||||
if form.is_valid():
|
||||
@@ -158,13 +160,14 @@ def add_insight(request):
|
||||
else:
|
||||
form = InsightRecordForm()
|
||||
|
||||
context = {'form': form}
|
||||
context = {'form': form, 'family_members': family_members}
|
||||
return render(request, 'core/add_insight.html', context)
|
||||
|
||||
# 编辑感悟记录
|
||||
def edit_insight(request, pk):
|
||||
"""编辑感悟记录"""
|
||||
insight = get_object_or_404(InsightRecord, pk=pk)
|
||||
family_members = FamilyMember.objects.all()
|
||||
if request.method == 'POST':
|
||||
form = InsightRecordForm(request.POST, request.FILES, instance=insight)
|
||||
if form.is_valid():
|
||||
@@ -174,7 +177,7 @@ def edit_insight(request, pk):
|
||||
else:
|
||||
form = InsightRecordForm(instance=insight)
|
||||
|
||||
context = {'form': form, 'insight': insight}
|
||||
context = {'form': form, 'insight': insight, 'family_members': family_members}
|
||||
return render(request, 'core/edit_insight.html', context)
|
||||
|
||||
# 删除感悟记录
|
||||
@@ -257,6 +260,7 @@ def delete_today_reading(request, pk):
|
||||
# 添加今日感悟记录
|
||||
def add_today_insight(request):
|
||||
"""添加今日感悟记录"""
|
||||
family_members = FamilyMember.objects.all()
|
||||
if request.method == 'POST':
|
||||
form = InsightRecordForm(request.POST, request.FILES)
|
||||
if form.is_valid():
|
||||
@@ -268,13 +272,14 @@ def add_today_insight(request):
|
||||
else:
|
||||
form = InsightRecordForm()
|
||||
|
||||
context = {'form': form}
|
||||
context = {'form': form, 'family_members': family_members}
|
||||
return render(request, 'core/add_insight.html', context)
|
||||
|
||||
# 编辑今日感悟记录
|
||||
def edit_today_insight(request, pk):
|
||||
"""编辑今日感悟记录"""
|
||||
insight = get_object_or_404(InsightRecord, pk=pk)
|
||||
family_members = FamilyMember.objects.all()
|
||||
if request.method == 'POST':
|
||||
form = InsightRecordForm(request.POST, request.FILES, instance=insight)
|
||||
if form.is_valid():
|
||||
@@ -284,7 +289,7 @@ def edit_today_insight(request, pk):
|
||||
else:
|
||||
form = InsightRecordForm(instance=insight)
|
||||
|
||||
context = {'form': form, 'insight': insight}
|
||||
context = {'form': form, 'insight': insight, 'family_members': family_members}
|
||||
return render(request, 'core/edit_insight.html', context)
|
||||
|
||||
# 删除今日感悟记录
|
||||
@@ -373,6 +378,7 @@ def today_plan(request):
|
||||
# 添加今日计划
|
||||
def add_today_plan(request):
|
||||
"""添加今日计划"""
|
||||
family_members = FamilyMember.objects.all()
|
||||
if request.method == 'POST':
|
||||
form = TodayPlanForm(request.POST)
|
||||
if form.is_valid():
|
||||
@@ -382,13 +388,14 @@ def add_today_plan(request):
|
||||
else:
|
||||
form = TodayPlanForm()
|
||||
|
||||
context = {'form': form}
|
||||
context = {'form': form, 'family_members': family_members}
|
||||
return render(request, 'core/add_today_plan.html', context)
|
||||
|
||||
# 编辑今日计划
|
||||
def edit_today_plan(request, pk):
|
||||
"""编辑今日计划"""
|
||||
plan = get_object_or_404(TodayPlan, pk=pk)
|
||||
family_members = FamilyMember.objects.all()
|
||||
if request.method == 'POST':
|
||||
form = TodayPlanForm(request.POST, instance=plan)
|
||||
if form.is_valid():
|
||||
@@ -398,7 +405,7 @@ def edit_today_plan(request, pk):
|
||||
else:
|
||||
form = TodayPlanForm(instance=plan)
|
||||
|
||||
context = {'form': form, 'plan': plan}
|
||||
context = {'form': form, 'plan': plan, 'family_members': family_members}
|
||||
return render(request, 'core/edit_today_plan.html', context)
|
||||
|
||||
# 删除今日计划
|
||||
|
||||
22
update_db.py
Normal file
22
update_db.py
Normal file
@@ -0,0 +1,22 @@
|
||||
import sqlite3
|
||||
|
||||
conn = sqlite3.connect('db.sqlite3')
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute('''
|
||||
INSERT INTO core_familymember (name, created_at, updated_at)
|
||||
VALUES ('默认成员', datetime('now', 'localtime'), datetime('now', 'localtime'));
|
||||
''')
|
||||
|
||||
cursor.execute('''
|
||||
ALTER TABLE core_insightrecord ADD COLUMN speaker_id INTEGER NOT NULL DEFAULT 1;
|
||||
''')
|
||||
|
||||
cursor.execute('''
|
||||
ALTER TABLE core_todayplan ADD COLUMN speaker_id INTEGER NOT NULL DEFAULT 1;
|
||||
''')
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
print("Database updated successfully!")
|
||||
10
verify_db.py
Normal file
10
verify_db.py
Normal file
@@ -0,0 +1,10 @@
|
||||
import sqlite3
|
||||
conn = sqlite3.connect('db.sqlite3')
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'core_%' ORDER BY name;")
|
||||
print("Tables:", [r[0] for r in cursor.fetchall()])
|
||||
cursor.execute("SELECT COUNT(*) FROM core_familymember;")
|
||||
print("Family members count:", cursor.fetchone()[0])
|
||||
cursor.execute("SELECT sql FROM sqlite_master WHERE type='table' AND name='core_insightrecord';")
|
||||
print("InsightRecord schema:", cursor.fetchone()[0])
|
||||
conn.close()
|
||||
Reference in New Issue
Block a user