You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django CRM开发:线索转客户时遇属性错误与对象重复问题

Django CRM系统Lead转Client的问题解决

遇到的问题

  • 无论线索是否存在评论,都会抛出AttributeError: 'Lead' object has no attribute 'comment'
  • 线索被重复转换4次

相关代码及报错信息

models.py

class Lead(models.Model):
    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"

    CHOICES_PRIORITY = ((LOW, "Low"), (MEDIUM, "Medium"), (HIGH, "High"))

    team = models.ForeignKey(Team, related_name="leads", on_delete=models.CASCADE)
    name = models.CharField(max_length=255)
    email = models.EmailField()
    number = models.CharField(max_length=255)
    description = models.TextField(blank=True, null=True)
    priority = models.CharField(max_length=10, choices=CHOICES_PRIORITY, default=MEDIUM)
    converted_to_client = models.BooleanField(default=False)
    created_by = models.ForeignKey(
        User, related_name="leads", on_delete=models.CASCADE, default="Admin"
    )
    created_at = models.DateTimeField(auto_now_add=True)
    modified_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ("name",)

    def __str__(self):
        return self.name

class Comment(models.Model):
    team = models.ForeignKey(
        Team, related_name="lead_comments", on_delete=models.CASCADE
    )
    lead = models.ForeignKey(Lead, related_name="comments", on_delete=models.CASCADE)
    content = models.TextField(blank=True, null=True)
    created_by = models.ForeignKey(
        User, related_name="lead_comments", on_delete=models.CASCADE
    )
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.created_by.username

views.py(原代码)

class ConvertToClientView(LoginRequiredMixin, View):
    def get(self, request, *args, **kwargs):
        pk = self.kwargs.get("pk")

        lead = get_object_or_404(Lead, created_by=request.user, pk=pk)
        team = self.request.user.userprofile.active_team

        client = Client.objects.create(
            name=lead.name,
            email=lead.email,
            number=lead.number,
            description=lead.description,
            created_by=request.user,
            team=team,
        )

        lead.converted_to_client = True
        lead.save()

        # Convert Comments from Lead to Client Comments

        comments = lead.comment.all()

        for comment in comments:
            ClientComment.objects.create(
                client=client,
                content=comment.content,
                created_by=comment.created_by,
                team=team,
            )

        messages.success(request, "The lead was converted")

        return redirect("leads:list")

报错信息

'Lead' object has no attribute 'comment'
Request Method: GET
Request URL: http://127.0.0.1:8000/dashboard/leads/17/convert/
Django Version: 4.2.1
Exception Type: AttributeError
Exception Value: 'Lead' object has no attribute 'comment'

解决方案

1. 修复属性错误

在Comment模型中,lead外键的related_name设置为comments(复数),但原代码中误用了单数comment,导致属性找不到。修改为复数形式即可,同时可增加存在性判断避免空循环:

# 替换原评论转换代码
if lead.comments.exists():
    for comment in lead.comments.all():
        ClientComment.objects.create(
            client=client,
            content=comment.content,
            created_by=comment.created_by,
            team=team,
        )

2. 阻止重复转换

原视图使用GET请求,容易因页面刷新、浏览器重复请求导致重复创建Client。通过以下两点解决:

  • 改用POST请求,避免浏览器误触发
  • 转换前检查线索是否已完成转换,若已转换则直接跳转

修改后的views.py:

class ConvertToClientView(LoginRequiredMixin, View):
    def post(self, request, *args, **kwargs):
        pk = self.kwargs.get("pk")

        lead = get_object_or_404(Lead, created_by=request.user, pk=pk)
        
        # 检查是否已转换,避免重复操作
        if lead.converted_to_client:
            messages.info(request, "该线索已转换为客户")
            return redirect("leads:list")
            
        team = self.request.user.userprofile.active_team

        client = Client.objects.create(
            name=lead.name,
            email=lead.email,
            number=lead.number,
            description=lead.description,
            created_by=request.user,
            team=team,
        )

        lead.converted_to_client = True
        lead.save()

        # 转换评论
        if lead.comments.exists():
            for comment in lead.comments.all():
                ClientComment.objects.create(
                    client=client,
                    content=comment.content,
                    created_by=comment.created_by,
                    team=team,
                )

        messages.success(request, "线索已成功转换为客户")
        return redirect("leads:list")

同时前端需将转换按钮改为POST表单提交(需包含csrf_token):

<form method="POST" action="{% url 'leads:convert' lead.pk %}">
    {% csrf_token %}
    <button type="submit">转换为客户</button>
</form>

内容的提问来源于stack exchange,提问作者CrumblyPringle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 16:53:26