2010-07-11 13 views
29

Tôi đang tìm thông tin xung đột về việc có nên sử dụng OneToOneField (Người dùng) hoặc ForeignKey (Người dùng, duy nhất = True) khi tạo mô hình UserProfile bằng cách mở rộng mô hình Người dùng Django hay không.Django: Khi mở rộng Người dùng, tốt hơn để sử dụng OneToOneField (Người dùng) hoặc ForeignKey (Người dùng, duy nhất = True)?

Là nó tốt hơn để sử dụng này ?:

class UserProfile(models.Model): 
    user = models.ForeignKey(User, unique=True) 

hay này ?:

class UserProfile(models.Model): 
    user = models.OneToOneField(User) 

Các Django Doc định OneToOneField, trong khi Django Book example sử dụng ForeignKey.

James Bennett cũng có hai Blog viết rằng việc cung cấp ví dụ mâu thuẫn cũng như:

Trong bài cũ, Bennett đưa ra một số lý do tại sao ông chuyển sang sử dụng ForeignKey thay của OneToOneField, nhưng tôi không hoàn toàn hiểu được nó, đặc biệt là khi tôi thấy các bài viết khác đề xuất ngược lại.

Tôi tò mò muốn biết tùy chọn của bạn và lý do. Hay nó thậm chí còn quan trọng?

+0

Tôi không thấy gì trong bài viết đầu tiên của Bennett về hồ sơ người dùng. –

+0

@Ignacio - Rất tiếc, tôi đã thêm một liên kết đến bài viết sai. Nó nên có được bài viết của mình trên "Mở rộng mô hình người dùng". Tôi đã sửa liên kết. Cảm ơn bạn đã chỉ ra điều này. –

+0

Đối với tôi, http://stackoverflow.com/questions/5870537/whats-the-difference-between-django-onetoonefield-and-foreignkey rõ ràng hơn để hiểu –

Trả lời

17

Lý do thực sự chỉ được đưa ra trong bài báo là nó có thể được thiết lập để các trang quản trị cho User sẽ hiển thị cả các trường trong UserUserProfile. Điều này có thể được nhân rộng với một OneToOneField với một chút mỡ khuỷu tay, vì vậy, trừ khi bạn đang nghiện để hiển thị nó trong trang quản trị mà không làm việc với chi phí của một chút rõ ràng ("Chúng tôi có thể tạo nhiều hồ sơ cho mỗi người dùng ?! Oh không , chờ đã, nó được đặt là duy nhất. ") Tôi muốn sử dụng OneToOneField.

7

Bên cạnh dòng trang quản trị, lý do khác cho giải pháp ForeignKey là nó cho phép bạn sử dụng đúng trình quản lý DB mặc định khi đối tượng được truy cập với một mối quan hệ đảo ngược. Xem xét ví dụ từ số subclasses manager snippet này. Hãy nói rằng định nghĩa Post lớp từ ví dụ như sau:

class Post(ParentModel): 
    title = models.CharField(max_length=50) 
    onetoone = models.ForeignKey(SomeModel, unique=True) 

    children = ChildManager() 
    objects = models.Manager() 

Bằng cách gọi somemodel_instance.post_set.all()[0], bạn sẽ có được lớp con đối tượng mong muốn của lớp Post như được chỉ ra bằng cách xác định quản lý đầu tiên (mặc định) như là một ChildManager. Mặt khác, với OneToOneField, bằng cách gọi somemodel_instance.post bạn nhận được phiên bản lớp Post. Bạn luôn có thể gọi somemodel_instance.post.subclass_object và nhận được kết quả tương tự, nhưng người quản lý mặc định có thể thực hiện bất kỳ loại thủ thuật nào khác và giải pháp FK giấu chúng một cách độc đáo.

Nếu bạn sở hữu và có thể sửa đổi mã người quản lý tùy chỉnh, bạn có thể sử dụng thuộc tính use_for_related_fields thay vì sử dụng FK thay cho trường 1to1 hợp pháp, nhưng điều đó có thể không thành công do một số phiền toái của người quản lý tự động. Theo như tôi nhớ nó sẽ thất bại trong ví dụ trên.

5

lý do khác để thường không sử dụng OneToOneField liên quan đến đảo ngược quan hệ: khi bạn sử dụng các mối quan hệ ngược được xác định thông qua OneToOneField bạn sẽ có được một thể hiện mô hình, trái với Manager cho ForeignKey mối quan hệ ngược và như một hệ quả luôn có một DB nhấn.Điều này là tốn kém nếu bạn làm một số công cụ chung về quan hệ ngược lại (thông qua _meta.get_all_related_objects()) và không biết và quan tâm nếu bạn sẽ sử dụng tất cả hay không.