Django: Đặt khóa ngoại bằng số nguyên?


104

Có cách nào để thiết lập mối quan hệ khóa ngoại bằng cách sử dụng id số nguyên của một mô hình không? Điều này sẽ dành cho mục đích tối ưu hóa.

Ví dụ: giả sử tôi có mô hình Nhân viên:

class Employee(models.Model):
  first_name = models.CharField(max_length=100)
  last_name = models.CharField(max_length=100)
  type = models.ForeignKey('EmployeeType')

EmployeeType(models.Model):
  type = models.CharField(max_length=100)

Tôi muốn sự linh hoạt của việc có các loại nhân viên không giới hạn, nhưng trong ứng dụng đã triển khai có thể sẽ chỉ có một loại duy nhất nên tôi tự hỏi liệu có cách nào để mã hóa id và thiết lập mối quan hệ theo cách này không. Bằng cách này, tôi có thể tránh một lệnh gọi db để lấy đối tượng EmployeeType trước.

Câu trả lời:


205

Vâng:

employee = Employee(first_name="Name", last_name="Name")
employee.type_id = 4
employee.save()

ForeignKeycác trường lưu trữ giá trị của chúng trong một thuộc tính có _idở cuối, bạn có thể truy cập trực tiếp để tránh truy cập cơ sở dữ liệu.

Các _idphiên bản của một ForeignKeylà một khía cạnh đặc biệt hữu ích của Django, một trong đó tất cả mọi người nên biết và sử dụng bất cứ lúc nào khi cần thiết.

cảnh báo:

@RuneKaagaard chỉ ra rằng điều đó employee.typekhông chính xác sau đó trong các phiên bản Django gần đây, ngay cả sau khi gọi employee.save()(nó vẫn giữ nguyên giá trị cũ). Sử dụng nó tất nhiên sẽ đánh bại mục đích của việc tối ưu hóa ở trên, nhưng tôi muốn một truy vấn bổ sung tình cờ không chính xác. Vì vậy, hãy cẩn thận, chỉ sử dụng điều này khi bạn đã hoàn thành việc làm việc với cá thể của mình (ví dụ employee:).


10
Đây có phải là tài liệu?
Scott Stafford

8
Sử dụng giá trị chính nước ngoài trực tiếp: docs.djangoproject.com/en/1.8/topics/db/optimization/...
Dan Oliphant

1
Tôi đã thử nghiệm điều này trên Django 1.7 ngày hôm nay và đó không phải là một ý tưởng hay. Trong khi nó hoạt động và typetrường được ghi vào cơ sở dữ liệu, nếu bạn truy cập thuộc typetính sau đó thì nó không phản ánh thay đổi. Đã nói trong mã, điều này sẽ không thành công assert(employe.type.id == 4).
Rune Kaagaard,

3
@AmichaiSchreiber Tôi tin rằng bản phát hành tiếp theo của Django sẽ có bản sửa lỗi cho vấn đề này: code.djangoproject.com/ticket/27710
Will Hardy

2
Đối với bất kỳ ai đến đây trong tương lai, vấn đề này đã được khắc phục trong Django 2.1 .
humcat 13/09/19

45

Một giải pháp thay thế sử dụng create để tạo đối tượng và lưu nó vào cơ sở dữ liệu trong một dòng:

employee = Employee.objects.create(first_name='first', last_name='last', type_id=4)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.