5.0 KiB
5.0 KiB
网站字段修复说明
问题描述
您遇到了 "can only join an iterable" 错误,这是因为将 CrawlTask 模型中的 websites 字段从 JSONField 改为了 ManyToManyField,但代码中还有一些地方没有相应更新。
已修复的问题
1. 任务执行器修复
在 core/task_executor.py 中,已经修复了以下方法:
_execute_keyword_task()- 关键词搜索任务执行_execute_historical_task()- 历史文章任务执行_execute_full_site_task()- 全站爬取任务执行
修复前:
websites = task.websites if task.websites else list(WEBSITE_SEARCH_CONFIGS.keys())
修复后:
selected_websites = task.websites.all()
if selected_websites:
websites = [w.name for w in selected_websites]
else:
websites = list(WEBSITE_SEARCH_CONFIGS.keys())
2. 模型方法修复
在 core/models.py 中,get_websites_display() 方法已经正确处理了 ManyToManyField:
def get_websites_display(self):
"""获取网站列表的显示文本"""
try:
websites = self.websites.all()
if not websites:
return "所有网站"
# 确保网站名称是字符串并可以被join处理
website_names = [str(w.name) for w in websites if w.name]
return ", ".join(website_names) if website_names else "所有网站"
except Exception:
# 如果出现任何异常,返回默认值
return "所有网站"
3. 管理界面修复
在 core/admin_extended.py 中,已经修复了任务创建逻辑:
- 使用
Website.objects.filter(name__in=websites)获取网站对象 - 使用
task.websites.set(website_objects)设置关联关系
测试验证
已经通过以下测试验证修复:
- 网站字段功能测试 - 验证
ManyToManyField的基本操作 - 任务执行器测试 - 验证任务执行器中的网站获取逻辑
- Web界面操作测试 - 验证完整的Web界面操作流程
- 系统检查 - Django系统检查无错误
使用方法
1. 确保数据库迁移已应用
python manage.py migrate
2. 创建网站数据
如果还没有网站数据,可以通过以下方式创建:
from core.models import Website
# 创建一些测试网站
websites_to_create = ["新华网", "人民日报", "央视网"]
for name in websites_to_create:
website, created = Website.objects.get_or_create(
name=name,
defaults={
'base_url': f'http://{name}.com',
'enabled': True
}
)
3. 通过Web界面创建任务
- 启动服务器:
python manage.py runserver - 访问管理后台:
http://localhost:8000/admin/ - 在首页点击"快速创建爬取任务"
- 选择任务类型并填写相关信息
- 选择目标网站
- 创建并启动任务
4. 通过命令行创建任务
# 关键词搜索
python manage.py crawl_by_keyword --keyword "人工智能"
# 历史文章爬取
python manage.py crawl_by_keyword --keyword "新闻" --historical
# 多网站一键爬取
python manage.py crawl_all_websites --mode both --keyword "人工智能"
故障排除
如果仍然遇到 "can only join an iterable" 错误
-
检查数据库迁移:
python manage.py showmigrations core python manage.py migrate -
检查网站数据:
from core.models import Website print(Website.objects.filter(enabled=True).count()) -
检查任务数据:
from core.models import CrawlTask task = CrawlTask.objects.first() if task: print(f"任务网站: {task.get_websites_display()}") -
重启服务器:
# 停止当前服务器 (Ctrl+C) python manage.py runserver
如果遇到其他错误
- 检查日志:查看Django日志输出
- 检查网络连接:确保可以访问目标网站
- 检查网站配置:确保
WEBSITE_SEARCH_CONFIGS中的配置正确
技术细节
ManyToManyField vs JSONField
之前的JSONField方式:
websites = models.JSONField(default=list, verbose_name="目标网站")
# 使用: task.websites = ["新华网", "人民日报"]
现在的ManyToManyField方式:
websites = models.ManyToManyField(Website, blank=True, verbose_name="目标网站")
# 使用: task.websites.set(website_objects)
优势
- 数据完整性:通过外键关系确保数据一致性
- 查询效率:可以利用数据库索引进行高效查询
- 关系管理:Django自动处理多对多关系的创建和删除
- 数据验证:自动验证关联的网站是否存在
总结
修复已经完成,现在您可以:
- 通过Web界面创建和管理爬取任务
- 选择特定的网站进行爬取
- 实时监控任务进度
- 查看详细的爬取结果
如果仍然遇到问题,请检查:
- 数据库迁移是否已应用
- 网站数据是否存在
- 服务器是否已重启
系统现在应该可以正常工作了!