2010-10-06 29 views
50

Tôi đang cố gắng lấy mẫu đối tượng mô hình trong một trường hợp khác. Và tôi nâng lỗi này:Trình quản lý không thể truy cập được qua các phiên bản mẫu

Manager isn't accessible via topic instance 

Dưới đây là mô hình của tôi:

class forum(models.Model): 
    # Some attributs 

class topic(models.Model): 
    # Some attributs 

class post(models.Model): 
    # Some attributs 

    def delete(self): 
     forum = self.topic.forum 
     super(post, self).delete() 
     forum.topic_count = topic.objects.filter(forum = forum).count() 

Dưới đây là quan điểm của tôi:

def test(request, post_id): 
    post = topic.objects.get(id = int(topic_id)) 
    post.delete() 

và tôi nhận được:

post.delete() 
forum.topic_count = topic.objects.filter(forum = forum).count() 
Manager isn't accessible via topic instances 

Trả lời

77

Các lỗi trong câu hỏi được gây ra khi bạn cố gắng truy cập vào Manager của một mô hình thông qua một thể hiện của mô hình. Bạn đã sử dụng trường hợp thấp hơn tên lớp học. Điều này làm cho nó khó để nói nếu lỗi được gây ra bởi một trường hợp truy cập vào Manager hay không. Kể từ khi các kịch bản khác có thể gây ra lỗi này là không rõ tôi đang tiến hành trên giả định rằng bạn đã bằng cách nào đó trộn lên biến topic để bạn kết thúc chỉ đến một thể hiện của mô hình topic thay vì lớp.

Dòng này là thủ phạm:

forum.topic_count = topic.objects.filter(forum = forum).count() 
#     ^^^^^ 

Bạn phải sử dụng:

forum.topic_count = Topic.objects.filter(forum = forum).count() 
#     ^^^^^ 
#     Model, not instance. 

gì đang xảy ra vậy? objects là một số Manager khả dụng ở cấp lớp, không phải cho các phiên bản. Xem chi tiết documentation for retrieving objects. quote tiền:

Managers có thể truy cập chỉ qua lớp mô hình, chứ không phải từ các trường hợp mô hình, để thực thi một sự tách biệt giữa hoạt động "bảng cấp" và các hoạt động "kỷ lục cấp".

(Nhấn mạnh thêm)

Cập nhật

Xem các ý kiến ​​từ @Daniel dưới đây. Đó là một ý tưởng tốt (nay, bạn PHẢI: P) để sử dụng trường hợp tiêu đề cho tên lớp. Ví dụ: Topic thay vì topic. Tên lớp của bạn gây ra một số nhầm lẫn cho dù bạn đang đề cập đến một thể hiện hay một lớp. Kể từ khi Manager isn't accessible via <model> instances là rất cụ thể tôi có thể cung cấp một giải pháp. Các lỗi có thể không được như vậy tự hiển nhiên luôn.

+0

Tuy nhiên, 'chủ đề' dường như là lớp mô hình thực tế chứ không phải một phiên bản theo mã mà anh ta cung cấp. –

+0

@Daniel: đúng. Tuy nhiên, lỗi 'Người quản lý không thể truy cập thông qua các trường hợp Foo' chỉ có thể thực hiện được khi bạn cố gắng truy cập vào một 'Trình quản lý' bằng cách sử dụng một cá thể. Xem mã nguồn: http://code.djangoproject.com/svn/django/trunk/django/db/models/manager.py –

+4

Thật vậy, có lẽ một lý do khác (không phải là "thực hành tốt nhất") không sử dụng chữ thường cho tên lớp :) Nó sẽ xuất hiện anh ta có khả năng sử dụng 'topic' như là một biến cá thể cục bộ và thổi đi tham chiếu đến lớp. –

31

Đối với django < 1,10

topic._default_manager.get(id=topic_id) 

Mặc dù bạn không nên sử dụng nó như thế này.Các _default_manager và _base_manager là tư nhân, vì vậy nó được đề nghị để sử dụng chúng chỉ khi bạn đang ở trong các mô hình Chủ đề, giống như khi bạn muốn sử dụng quản lý trong một chức năng độc quyền giả:

class Topic(Model): 
. 
. 
. 
    def related(self) 
     "Returns the topics with similar starting names" 
     return self._default_manager.filter(name__startswith=self.name) 

topic.related() #topic 'Milan wins' is related to: 
# ['Milan wins','Milan wins championship', 'Milan wins by one goal', ...] 
+4

Cảm ơn, câu trả lời này chỉ là những gì tôi đã tìm kiếm. Tôi ước tôi có thể bỏ phiếu nhiều lần. Trường hợp sử dụng của tôi cho điều này là khi bạn thêm chức năng vào một mô hình trừu tượng, nơi bạn sẽ không biết (ở cấp độ này) những gì lớp mô hình cuối cùng được gọi. – fadedbee

+2

Hoặc sử dụng 'chủ đề .__ lớp __. Objects.get (id = topic_id)'. – Bentley4

+0

Đây là một câu trả lời cũ, nhưng như của Django v1.10 tôi không thấy những phương pháp riêng tư nữa. Tuy nhiên, 'self .__ class __. Objects' thực hiện thủ thuật cho câu trả lời khác của bạn. – James

28
topic.__class__.objects.get(id=topic_id) 
+0

Hoạt động như của Django v1.10. – James

0

nếu chủ đề là một thể loại ContentType (mà nó không phải là), điều này có thể đã làm việc:

topic.model_class().objects.filter(forum = forum) 
+0

['model_class()'] (https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#django.contrib.contenttypes.models.ContentType.model_class) là một phương thức của 'ContentType' mô hình. Các trường hợp mô hình khác, bao gồm 'chủ đề', không có phương thức' model_class'. – Alasdair

+0

Xin lỗi, tôi phải đọc sai câu hỏi. Tôi đã cố giải quyết một câu hỏi dường như tương tự ... – Nimo

3

Cũng có thể là do một cặp các cặp quá nhiều, ví dụ

ModelClass().objects.filter(...) 

thay vì đúng

ModelClass.objects.filter(...) 

xảy ra với tôi đôi khi bpython (hoặc một IDE) tự động thêm parantheses.

Kết quả, tất nhiên là giống nhau - bạn có một phiên bản thay vì một lớp.

Các vấn đề liên quan