Django: Tại sao một số lĩnh vực mô hình đụng độ với nhau?


174

Tôi muốn tạo một đối tượng có chứa 2 liên kết đến Người dùng. Ví dụ:

class GameClaim(models.Model):
    target = models.ForeignKey(User)
    claimer = models.ForeignKey(User)
    isAccepted = models.BooleanField()

nhưng tôi gặp các lỗi sau khi chạy máy chủ:

  • Trình truy cập cho trường 'đích' đụng độ với trường liên quan 'User.gameclaim_set'. Thêm một đối số có liên quan vào định nghĩa cho 'đích'.

  • Người truy cập cho trường 'người khiếu nại' đụng độ với trường liên quan 'User.gameclaim_set'. Thêm một đối số có liên quan vào định nghĩa cho 'người yêu cầu'.

Bạn có thể vui lòng giải thích tại sao tôi nhận được lỗi và cách khắc phục không?


Những thông báo lỗi là thực sự tốt. Họ đã giải thích làm thế nào để sửa chúng. Và đọc lên ** [ related_nametrong tài liệu] ** ( docs.djangoproject.com/en/dev/ref/models/fields/#argument ) sẽ giải thích lý do tại sao chúng xảy ra.
Lutz Prechelt

Câu trả lời:


294

Bạn có hai khóa ngoại cho Người dùng. Django tự động tạo ra một mối quan hệ ngược từ Người dùng trở lại GameClaim, thường là vậy gameclaim_set. Tuy nhiên, vì bạn có hai FK, bạn sẽ có hai gameclaim_setthuộc tính, điều này rõ ràng là không thể. Vì vậy, bạn cần nói cho Django biết tên nào sẽ được sử dụng cho mối quan hệ ngược lại.

Sử dụng related_namethuộc tính trong định nghĩa FK. ví dụ

class GameClaim(models.Model):
    target = models.ForeignKey(User, related_name='gameclaim_targets')
    claimer = models.ForeignKey(User, related_name='gameclaim_users')
    isAccepted = models.BooleanField()

49
Câu trả lời hay, nhưng tôi không nghĩ bạn đã thành công trong việc tránh sự thô lỗ: P "Tại sao" không rõ ràng trừ khi bạn nhận thức được django hoạt động nội bộ như thế nào.
Kenny

14
Đối với ai đó chỉ học khung, điều này sẽ không rõ ràng.
jkyle

3
Cảm ơn, thông báo lỗi cũng không rõ ràng đối với tôi, nhưng lời giải thích của bạn về mối quan hệ ngược lại rất hữu ích.
ruquay

1
Chỉ vì Clash là một ban nhạc tốt, không biến chúng thành một thông báo lỗi đặc biệt mô tả;)
btown 7/07/11

7
Cũng cần đề cập rằng nếu bạn không cần sử dụng các quan hệ ngược cho tất cả các mô hình. Trong một số trường hợp, bạn có thể muốn quan hệ mô hình là một chiều. Trong trường hợp này, bạn sử dụng Rel_name = '+'. Điều này nói với Django để tạo mối quan hệ một chiều và bỏ qua mối quan hệ ngược lại.
Tommy Strand

8

Các Usermô hình đang cố gắng để tạo ra hai lĩnh vực có cùng tên, một cho GameClaimsrằng có mà Usernhư target, và một cho GameClaimscó mà Usernhư claimer. Đây là các tài liệu trênrelated_name , đó là cách của Django cho phép bạn đặt tên của các thuộc tính để các thuộc tính tự phát không xung đột.


7

OP không sử dụng lớp cơ sở trừu tượng ... nhưng nếu là bạn, bạn sẽ thấy rằng mã hóa cứng tên có liên quan trong FK (ví dụ ..., có liên quan = "tên tôi") sẽ dẫn đến một số lỗi xung đột này - một cho mỗi lớp kế thừa từ lớp cơ sở. Liên kết được cung cấp dưới đây chứa cách giải quyết, đơn giản, nhưng chắc chắn không rõ ràng.

Từ các tài liệu django ...

Nếu bạn đang sử dụng thuộc tính Rel_name trên ForeignKey hoặc ManyToManyField, bạn phải luôn chỉ định một tên đảo ngược duy nhất cho trường. Điều này thường gây ra sự cố trong các lớp cơ sở trừu tượng, vì các trường trên lớp này được bao gồm trong mỗi lớp con, với các giá trị chính xác giống nhau cho các thuộc tính (bao gồm cả tên_bảng) mỗi lần.

Thêm thông tin ở đây .


2

Đôi khi bạn phải sử dụng định dạng bổ sung trong related_name - thực tế, bất cứ lúc nào khi kế thừa được sử dụng.

class Value(models.Model):
    value = models.DecimalField(decimal_places=2, max_digits=5)
    animal = models.ForeignKey(
        Animal, related_name="%(app_label)s_%(class)s_related")

    class Meta:
        abstract = True

class Height(Value):
    pass

class Weigth(Value):
    pass

class Length(Value):
    pass

Không có xung đột ở đây, nhưng tên liên quan được xác định một lần và Django sẽ chăm sóc để tạo các tên quan hệ duy nhất.

sau đó ở trẻ em của lớp Giá trị, bạn sẽ có quyền truy cập vào:

herdboard_height_related
herdboard_lenght_related
herdboard_weight_related

0

Tôi dường như tình cờ bắt gặp điều này khi tôi thêm một mô hình con dưới dạng một ứng dụng cho một dự án django, ví dụ như được đưa ra cấu trúc sau:

myapp/
myapp/module/
myapp/module/models.py

Nếu tôi thêm phần sau vào INSTALLED_APPS:

'myapp',
'myapp.module',

Django dường như xử lý tệp mô hình myapp.mymodule mô hình hai lần và đưa ra lỗi trên. Điều này có thể được giải quyết bằng cách không bao gồm mô-đun chính trong danh sách INSTALLED_APPS:

'myapp.module',

Bao gồm cả myappthay vì myapp.modulelàm cho tất cả các bảng cơ sở dữ liệu được tạo với tên không chính xác, vì vậy đây có vẻ là cách chính xác để làm điều đó.

Tôi đã xem qua bài đăng này trong khi tìm kiếm một giải pháp cho vấn đề này vì vậy tôi nghĩ rằng tôi sẽ đặt nó ở đây :)


0

Chỉ cần thêm vào câu trả lời của Jordan (cảm ơn vì mẹo Jordan) cũng có thể xảy ra nếu bạn nhập cấp trên ứng dụng và sau đó nhập ứng dụng, ví dụ:

myproject/ apps/ foo_app/ bar_app/

Vì vậy, nếu bạn đang nhập ứng dụng, foo_app và bar_app thì bạn có thể gặp sự cố này. Tôi đã có ứng dụng, foo_app và bar_app được liệt kê trong cài đặt.INSTALLED_APPS

Và dù sao bạn cũng muốn tránh nhập ứng dụng, vì sau đó bạn có cùng một ứng dụng được cài đặt ở 2 không gian tên khác nhau

apps.foo_appfoo_app

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.