Django Lead模型CSV上传优化:是否需新增List模型实现自定义名单命名筛选
方案结论
是的,新增关联的批次模型是最优实现方案,建议将模型命名为LeadImportBatch(避免和Python内置的list关键字冲突),相比直接在Lead模型中冗余存储批次名称,这种关联结构扩展性更强,后续还可以灵活补充导入时间、操作人、导入日志、备注等批次维度的属性。
具体修改步骤
1. 调整models.py
from django.db import models from django.contrib.auth import get_user_model User = get_user_model() # 新增批次模型 class LeadImportBatch(models.Model): name = models.CharField(max_length=100, verbose_name="批次名称", unique=True) import_time = models.DateTimeField(auto_now_add=True, verbose_name="导入时间") operator = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, verbose_name="操作人") remark = models.TextField(blank=True, verbose_name="备注") def __str__(self): return self.name class Lead(models.Model): # 原有字段保留,新增关联字段 # 如果允许同一个Lead属于多个批次,换成ManyToManyField即可 import_batch = models.ForeignKey( LeadImportBatch, on_delete=models.SET_NULL, null=True, blank=True, related_name="leads", verbose_name="所属导入批次" ) first_name = models.CharField(max_length=20) last_name = models.CharField(max_length=20) # 小优化:原有address字段是CharField,default=0属于类型不匹配,建议改成default="" address = models.CharField(default="", max_length=50) city = models.CharField(max_length=30, default="") state = models.CharField(max_length=20, default="") zipcode = models.IntegerField(default=0) phone = models.CharField(max_length=10, null=True, default="", blank=True) email = models.EmailField(default="") def __str__(self): return f"{self.first_name} {self.last_name}"
修改完成后执行makemigrations和migrate命令同步数据库结构。
2. 修改csv_upload.html模板
补充批次名称输入框和Django必填的CSRF校验标签:
<form action="" method="POST" enctype="multipart/form-data"> {% csrf_token %} <label for="batch_name">本次导入名单名称:</label> <input type="text" id="batch_name" name="batch_name" required placeholder="请输入自定义批次名称"> <br> <label for="file1">上传CSV文件:</label> <input type="file" id="file1" name="file" accept=".csv" required> <button type="submit">上传</button> </form>
3. 调整csv_upload视图逻辑
先创建批次实例,再关联到本次导入的Lead数据:
import io import csv from django.shortcuts import render, redirect from django.contrib import messages from .models import Lead, LeadImportBatch def csv_upload(request): template = "leads/lead_csv_upload.html" data = Lead.objects.all() prompt = { 'order': 'CSV列顺序应为:first_name, last_name, address, city, state, zipcode, phone, email', 'profiles': data } if request.method == "GET": return render(request, template, prompt) # 先校验必填参数 batch_name = request.POST.get('batch_name') csv_file = request.FILES.get('file') if not batch_name or not csv_file: messages.error(request, "请填写批次名称并选择CSV文件") return render(request, template, prompt) if not csv_file.name.endswith('.csv'): messages.error(request, "请上传后缀为.csv的文件") return render(request, template, prompt) # 先创建批次实例 import_batch = LeadImportBatch.objects.create( name=batch_name, operator=request.user # 如果不需要关联操作人可以删掉这行 ) try: data_set = csv_file.read().decode('UTF-8') io_string = io.StringIO(data_set) next(io_string) # 跳过表头 for column in csv.reader(io_string, delimiter=',', quotechar="|"): _, created = Lead.objects.update_or_create( first_name=column[0], last_name=column[1], address=column[2], city=column[3], state=column[4], zipcode=column[5], phone=column[6], email=column[7], # 关联本次导入批次 defaults={"import_batch": import_batch} ) messages.success(request, f"批次【{batch_name}】导入完成") except Exception as e: # 导入失败则删除已经创建的空批次 import_batch.delete() messages.error(request, f"导入失败:{str(e)}") return render(request, template, prompt) return render(request, template, {})
后续筛选使用
要查询特定批次的Lead数据,直接通过批次实例反向查询即可:
# 按批次名称筛选该批次所有Lead batch = LeadImportBatch.objects.get(name="2024年Q3线索名单") leads = batch.leads.all()
如果在Django Admin中注册了Lead和LeadImportBatch模型,还可以直接在后台通过批次名称筛选Lead数据。
内容的提问来源于stack exchange,提问作者Danny
相关产品推荐
相关产品推荐

