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

Django中Employee模型无法关联Company模型问题排查

Django中Employee与Company关联问题

我正在用Django开发应用,已经成功关联了User和Employee模型,但在关联Company与Employee时遇到了问题。

我的视图代码

from django.shortcuts import render
from django.http import HttpResponse

from company.models import Company
from .models import Employee
from .forms import UserForm, CompanyForm
from django.contrib.auth.models import User
import random, string
from django.db import IntegrityError


def new(request):    
    # Initialize forms
    user_form = UserForm(request.POST or None)
    company_form = CompanyForm(request.POST or None)

    # Check if the request is a POST request
    if request.method == 'POST':
        # Check if both forms are valid
        if user_form.is_valid() and company_form.is_valid():
            email = user_form.cleaned_data['email']

            # Check if a user with this email already exists
            try:
                user = User.objects.get(email=email)
                user_created = False
            except User.DoesNotExist:
                user = User(username=email, email=email)
                random_password = User.objects.make_random_password()
                user.set_password(random_password)
                user.save()
                user_created = True

            # Save the company form data
            company = company_form.save()

            # Check if an Employee already exists for this user
            try:
                employee = Employee.objects.get(user=user)
                employee_created = False
            except Employee.DoesNotExist:
                employee = Employee(user=user, company=company)
                employee.save()
                employee_created = True

            # Return appropriate response based on what was created
            if user_created:
                return HttpResponse('User and Employee created with password: ' + random_password)
            elif employee_created:
                return HttpResponse('Employee created for existing user.')
            else:
                return HttpResponse('User with that username already exists. Please try again.')

    user_form = UserForm()
    company_form = CompanyForm()

    # Render the page with the forms
    return render(request, 'new_business.html', {'user_form': user_form, 'company_form': company_form})

Employee模型代码

from django.db import models
from company.models import Company
from django.contrib.auth.models import User
from varvocrm.models import BaseModel

# Create your models here.
class Employee(models.Model):    
    user = models.OneToOneField(User, on_delete=models.CASCADE, blank=True, null=True)
    first_name = models.CharField(max_length=50, blank=True)
    last_name = models.CharField(max_length=50, blank=True)
    address = models.CharField(max_length=50, blank=True)
    city = models.CharField(max_length=50, blank=True)
    state = models.CharField(max_length=50, blank=True)
    zip_code = models.CharField(max_length=50, blank=True)
    phone = models.CharField(max_length=50, blank=True)
    website = models.CharField(max_length=50, blank=True)
    company = models.ForeignKey(Company, on_delete=models.CASCADE, blank=True, null=True)
    active = models.BooleanField(default=True)
    
    @property
    def is_deleted(self):
        return self.deleted_at is not None
    
    @property
    def is_active(self):
        return self.active and not self.is_deleted
    
    def __str__(self):
        return self.user.username if self.user else ''

Company模型代码

from django.db import models
from varvocrm.models import BaseModel

# Create your models here.
class Company(models.Model):
    
    countries = [
        ('Norway', 'Norway'),
        ('Sweden', 'Sweden'),
        ('Denmark', 'Denmark'),
    ]
    
    organization_number = models.CharField(max_length=50, unique=True)
    name = models.CharField(max_length=50, blank=True)
    address = models.CharField(max_length=50, blank=True)
    city = models.CharField(max_length=50, blank=True)
    state = models.CharField(max_length=50, blank=True)
    zip_code = models.CharField(max_length=50, blank=True)
    country = models.CharField(max_length=50, default='Norway', choices=countries)
    phone = models.CharField(max_length=50, blank=True)
    email = models.EmailField(max_length=50)
    website = models.CharField(max_length=50, blank=True)
    
    def __str__(self):
        return self.organization_number
    
class Settings(models.Model):
    company = models.OneToOneField(Company, on_delete=models.CASCADE, blank=True, null=True)
    logo = models.ImageField(upload_to='logo/', blank=True)
    currency = models.CharField(max_length=50, default='NOK')
    tax = models.IntegerField(default=25)
    option_accept_offers = models.BooleanField(default=True)
    option_price_include_tax = models.BooleanField(default=True)
    option_send_email = models.BooleanField(default=True)
    option_locked = models.BooleanField(default=False)
    option_locked_message = models.CharField(max_length=50, blank=True, default='Locked by admin, contact customer service for more information.')
    
    def __str__(self):
        return self.company.name if self.company else ''

问题分析与修复

当前代码的核心问题有两个:

  1. 每次提交表单都会创建新的Company记录,即使同一家公司已经存在
  2. 当用户已关联Employee时,不会更新该Employee的公司关联

修复步骤

  1. 避免重复创建Company
    利用organization_number的唯一性,先检查公司是否已存在,不存在再创建:

    # 替换原有的company = company_form.save()
    org_number = company_form.cleaned_data['organization_number']
    try:
        company = Company.objects.get(organization_number=org_number)
    except Company.DoesNotExist:
        company = company_form.save()
    
  2. 更新已有Employee的公司关联
    当用户已存在对应Employee时,直接更新其公司字段:

    # 替换原有的Employee判断逻辑
    try:
        employee = Employee.objects.get(user=user)
        # 仅当公司不同时更新
        if employee.company != company:
            employee.company = company
            employee.save()
        employee_created = False
    except Employee.DoesNotExist:
        employee = Employee(user=user, company=company)
        employee.save()
        employee_created = True
    
  3. 修复表单初始化逻辑
    移除POST分支外的表单初始化,避免验证失败后丢失用户输入:

    # 删掉这两行代码
    # user_form = UserForm()
    # company_form = CompanyForm()
    

修复后的完整视图代码

from django.shortcuts import render
from django.http import HttpResponse

from company.models import Company
from .models import Employee
from .forms import UserForm, CompanyForm
from django.contrib.auth.models import User
import random, string
from django.db import IntegrityError


def new(request):    
    # Initialize forms
    user_form = UserForm(request.POST or None)
    company_form = CompanyForm(request.POST or None)

    # Check if the request is a POST request
    if request.method == 'POST':
        # Check if both forms are valid
        if user_form.is_valid() and company_form.is_valid():
            email = user_form.cleaned_data['email']

            # Check if a user with this email already exists
            try:
                user = User.objects.get(email=email)
                user_created = False
            except User.DoesNotExist:
                user = User(username=email, email=email)
                random_password = User.objects.make_random_password()
                user.set_password(random_password)
                user.save()
                user_created = True

            # 检查公司是否已存在,避免重复创建
            org_number = company_form.cleaned_data['organization_number']
            try:
                company = Company.objects.get(organization_number=org_number)
            except Company.DoesNotExist:
                company = company_form.save()

            # 处理Employee关联,已存在则更新公司
            try:
                employee = Employee.objects.get(user=user)
                if employee.company != company:
                    employee.company = company
                    employee.save()
                employee_created = False
            except Employee.DoesNotExist:
                employee = Employee(user=user, company=company)
                employee.save()
                employee_created = True

            # 返回对应提示
            if user_created:
                return HttpResponse(f'用户和员工已创建,密码:{random_password}')
            elif employee_created:
                return HttpResponse('已为现有用户创建员工关联')
            else:
                return HttpResponse('用户已存在,员工的公司关联已更新')

    # Render the page with the forms
    return render(request, 'new_business.html', {'user_form': user_form, 'company_form': company_form})

额外建议

  • 给Employee的company字段添加related_name,方便反向查询公司下的所有员工:
    company = models.ForeignKey(Company, on_delete=models.CASCADE, blank=True, null=True, related_name='employees')
    
  • 可以用Django的get_or_create方法简化存在性判断,让代码更简洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 22:35:11