2012-04-27 40 views
115

Tôi đang sử dụng Django cho phép mọi người thêm thông số bổ sung vào một lớp học bằng cách sử dụng class Meta.Lớp Meta của Django hoạt động như thế nào?

class FooModel(models.Model): 
    ... 
    class Meta: 
     ... 

Điều duy nhất tôi tìm thấy trong tài liệu hướng dẫn Python là:

class FooMetaClass(type): 
    ... 

class FooClass: 
    __metaclass__ = FooMetaClass 

Tuy nhiên, tôi không nghĩ rằng đây là điều tương tự.

+3

Tiêu đề hỏi về meta meta, nhưng câu hỏi dường như hỏi về meta Django - bạn đang hỏi về cái nào? – ckhan

Trả lời

145

Bạn đang hỏi một câu hỏi về hai điều khác nhau:

  1. Meta lớp bên trong các mô hình Django:

    Đây chỉ là một container lớp học với một số tùy chọn (metadata) gắn liền với mô hình . Nó định nghĩa những thứ như quyền có sẵn, liên quan đến tên bảng cơ sở dữ liệu, cho dù mô hình này là trừu tượng hay không, số ít và số nhiều phiên bản của tên, vv

    lời giải thích ngắn là ở đây: Django docs: Models: Meta options

    Danh sách các tùy chọn có sẵn là meta ở đây: Django docs: Model Meta options

  2. metaclass bằng Python:

    Mô tả tốt nhất là ở đây: What is a metaclass in Python?

+1

Hai thứ này có liên quan gì không? tức là, lớp bên trong 'Meta' của Django có ngăn cản bạn sử dụng các tính năng metaclass được xây dựng của Python không? – nnyby

+7

@nnyby: Có hai điều tạo ra mối quan hệ giữa hai khái niệm này: tên và nhầm lẫn mà nhiều người dùng có (như OP đã có nó trong câu hỏi ban đầu). Tôi tin rằng giải quyết sự nhầm lẫn phổ biến là lợi thế đáng kể của topi này. Bạn không đồng ý – Tadeck

19

Django's Model lớp xử lý cụ thể có thuộc tính có tên Meta là lớp học. Nó không phải là một điều Python chung.

metaclasses Python hoàn toàn khác nhau.

+11

Tôi nghĩ câu trả lời của bạn chưa đủ rõ ràng - bạn có thể giải thích cách lớp 'Meta' hoạt động không? Tôi tin rằng OP đã hỏi cụ thể về điều đó. – Tadeck

34

Mở rộng câu trả lời Django của Tadeck ở trên, việc sử dụng 'lớp Meta:' trong Django cũng chỉ là Python bình thường.

Lớp nội bộ là vùng tên thuận tiện cho dữ liệu được chia sẻ giữa các phiên bản lớp (vì thế tên Meta cho 'siêu dữ liệu' nhưng bạn có thể gọi nó là bất kỳ thứ gì bạn thích). Trong thời gian ở Django nó thường chỉ đọc những thứ cấu hình, không có gì để ngăn chặn bạn thay đổi nó là:

In [1]: class Foo(object): 
    ...:  class Meta: 
    ...:   metaVal = 1 
    ...:   
In [2]: f1 = Foo() 
In [3]: f2 = Foo() 
In [4]: f1.Meta.metaVal 
Out[4]: 1 
In [5]: f2.Meta.metaVal = 2 
In [6]: f1.Meta.metaVal 
Out[6]: 2 
In [7]: Foo.Meta.metaVal 
Out[7]: 2 

Bạn có thể khám phá nó trong Django trực tiếp quá ví dụ:

In [1]: from django.contrib.auth.models import User 
In [2]: User.Meta 
Out[2]: django.contrib.auth.models.Meta 
In [3]: User.Meta.__dict__ 
Out[3]: 
{'__doc__': None, 
'__module__': 'django.contrib.auth.models', 
'abstract': False, 
'verbose_name': <django.utils.functional.__proxy__ at 0x26a6610>, 
'verbose_name_plural': <django.utils.functional.__proxy__ at 0x26a6650>} 

Tuy nhiên, trong Django bạn có nhiều có khả năng muốn khám phá thuộc tính _meta là một đối tượng Tùy chọn được tạo bởi mô hình metaclass khi một mô hình được tạo ra. Đó là nơi bạn sẽ tìm thấy tất cả thông tin 'meta' của lớp django. Trong Django, Meta chỉ được sử dụng để chuyển thông tin vào quá trình tạo đối tượng Tùy chọn _meta.

+0

này không hoạt động trên mô hình người dùng định nghĩa: >>> từ myapp.models nhập MyModel >>> MyModel.Meta Traceback (cuộc gọi gần đây nhất cuối cùng): File "", dòng 1, trong Thuộc tínhLỗi: loại đối tượng 'MyModel' không có thuộc tính 'meta' – bdf

+0

Bạn cần dấu gạch dưới, ví dụ: 'MyUser.objects.get (pk = 1) ._ meta' –

+0

Đúng, nhưng điều đó không truy cập lớp Meta bên trong của Model. Điều đó truy cập các tùy chọn _meta cho cá thể của Model đó ... dường như không có cách nào để truy cập vào lớp Meta bên trong. Trường hợp sử dụng cho tôi là phân lớp lớp MyModelProxy proxy từ MyModel theo cách mà MyModelProxy có thể kế thừa lớp Meta bên trong MyModel. – bdf

1

Câu trả lời khẳng định mô hình Django Meta và 'metaclasses' là "hoàn toàn khác" là câu trả lời gây hiểu lầm.

Việc xây dựng mô hình Django lớp đối tượng (có nghĩa là để nói rằng đối tượng đó là viết tắt của định nghĩa lớp chính nó) đang thực sự điều khiển bởi một metaclass gọi ModelBase, bạn có thể thấy rằng mã ở đây:

https://github.com/django/django/blob/master/django/db/models/base.py#L61

Và một trong những điều mà ModelBase thực hiện là tạo thuộc tính _meta trên mọi mô hình Django có chứa máy móc xác thực, chi tiết trường, máy móc tiết kiệm, v.v. Và, trong quá trình hoạt động này, bất cứ điều gì được chỉ định trong lớp bên trong của mô hình Meta được đọc và sử dụng trong quá trình đó.

Vì vậy, trong khi có, theo nghĩa Meta và metaclasses là những thứ khác nhau '', trong cơ chế xây dựng mô hình Django họ có liên quan mật thiết; hiểu cách họ làm việc cùng nhau sẽ làm sâu sắc hơn cái nhìn sâu sắc của bạn vào cả hai cùng một lúc.

Đây có thể là nguồn thông tin hữu ích để hiểu rõ hơn cách các mô hình Django sử dụng metaclasses.

https://code.djangoproject.com/wiki/DevModelCreation

Và điều này có thể giúp quá nếu bạn muốn hiểu rõ hơn về cách đối tượng làm việc nói chung.

https://docs.python.org/3/reference/datamodel.html