Django模型外键问题

0 投票
1 回答
515 浏览
提问于 2025-04-17 02:44

我刚开始学习编程和数据库,有个关于Django中外键的问题。

假设我有一个叫做 Expenses 的模型,它有一个外键指向 Employees 模型。

class Employees(models.Model):
    ...

class Expenses(models.Model):
    ...
    employee = models.ForeignKey(Employees)

我看到这个外键字段是员工的ID。

所以我的问题是,如果在实际操作中我在一个表单上能看到 员工的名字,我需要:

  1. Employees 表中根据名字获取 员工ID
  2. 然后把这个 员工ID 作为外键插入到 Expenses 表中,像这样:

    emp_id = Employees.object.get(name = 'John Doe')

    new_expense = Expenses(foo = 'bar', ..., employee_id = emp_id.employee_id,)

    new_expenses.save()

我这样做对吗?如果对的话,这样做是正确的吗?

1 个回答

3

模型类的名字应该用单数形式,这样在Python中看起来更顺眼。你可以通过在模型类里面使用 class Meta: 来让关联的数据库表有不同的名字。而且,默认的管理器是 objects,而不是 object

其实你不需要费那么大劲。Django会自动处理ID的映射。它会在目标模型中创建一个“反向”字段,和 ForeignKey 相关联。这个反向连接的名字是带有ForeignKey的模型名字加上 _set。所以在你的例子中,Employees 会自动生成一个叫 expenses_set 的字段,这个字段就像一个管理器,里面包含了所有这个员工的开支。这个管理器还有一些方法,比如 createdelete。所以你的例子其实就是:

new_expense = (Employee.objects.get(name='John Doe')
    .expense_set.create(foo='bar', ...))

不过最好还是关注一下 Employee 对象:

employee = Employee.objects.get(name='John Doe')
new_expense = employee.expense_set.create(foo='bar', ...)

(在参数列表中使用 = 时,周围不要有空格。)要注意,你不需要用这种方式来设置员工ID。

话说回来,我们大多数人会通过使用 related_name 参数给 ForeignKey 提供一个更好的名字来表示那个反向链接:

class Expenses(models.Model):
    ...
    employee = models.ForeignKey(Employees, related_name='expenses')

...
employee = Employee.objects.get(name='John Doe')
new_expense = employee.expenses.create(foo='bar', ...)

顺便说一下,如果你想获取某个员工的开支,有三种方法。第一种就像上面那样:

employee = Employee.objects.get(name='John Doe')
employee_expenses = employee.expenses.all()

或者你可以用一行代码:

employee_expenses = Employee.objects.get(name='John Doe').expenses.all()

还有一种方法是:

employee_expenses = Expense.objects.filter(employee__name="John Doe")

这里的 __ 表示要解引用ForeignKey,以便访问它的字段。第一种方法会进行两次查询,而其他方法只需一次,但你不能在后面使用中间的 Employee 对象。

撰写回答