Lớp Meta của Django hoạt động như thế nào?


189

Tôi đang sử dụng Django cho phép mọi người thêm các tham số bổ sung vào một lớp bằng cách sử dụng class Meta.

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

Điều duy nhất tôi tìm thấy trong tài liệu của 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ự.


6
Tiêu đề hỏi về meta Python, 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

10
@ckhan anh bối rối vì quyết định vô lý (IMO) khi gọi một lớp lồng nhau là "Meta", điều này rất sai lệch; cho người mới bắt đầu, về siêu dữ liệu của Python và cho những người dùng có kinh nghiệm hơn chưa từng thấy nó, về mục đích của nó (thay vì sử dụng các thuộc tính lớp hoặc siêu dữ liệu thực sự)
JC Rocamonde

Câu trả lời:


231

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

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

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

    Giải thích ngắn gọn ở đây: Tài liệu Django: Mô hình: Tùy chọn meta

    Danh sách các tùy chọn meta khả dụng có tại đây: Tài liệu Django: Tùy chọn Meta Model

    Đối với phiên bản mới nhất của Django: Django docs: Model Meta tùy chọn

  2. Siêu dữ liệu trong Python :

    Mô tả tốt nhất là ở đây: Siêu dữ liệu trong Python là gì?


3
Có phải hai điều này liên quan đến nhau? tức là, Metalớp bên trong của Django có ngăn bạn sử dụng các tính năng siêu dữ liệu dựng sẵn của Python không?
nnyby 3/03/2015

10
@nnyby: Có hai điều tạo ra mối quan hệ giữa hai khái niệm này: tên và sự nhầm lẫn mà nhiều người dùng có (như OP đã có 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 3/03/2015

48

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 bên trong là một không gian tên thuận tiện cho dữ liệu được chia sẻ giữa các thể hiện của lớp (do đó tên Meta cho 'siêu dữ liệu' nhưng bạn có thể gọi nó là bất cứ thứ gì bạn thích). Mặc dù trong Django, công cụ cấu hình chỉ đọc, không có gì ngăn bạn thay đổi:

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ũng có thể khám phá nó trong Django, vd:

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 khả năng muốn khám phá _metathuộc tính là Optionsđối tượng được tạo bởi mô hình metaclasskhi mô hình được tạo. Đó là nơi bạn sẽ tìm thấy tất cả thông tin 'meta' của lớp Django. Trong Django, Metachỉ được sử dụng để truyền thông tin vào quá trình tạo _meta Optionsđối tượng.


Điều này không hoạt động trên các mô hình do người dùng xác định: >>> từ myapp.models nhập MyModel >>> MyModel.Meta TracBack (cuộc gọi gần đây nhất vừa qua): Tệp "<console>", dòng 1, trong <module> AttributionError: loại đối tượng 'MyModel' không có thuộc tính 'meta'
bdf

2
Bạn cần gạch dưới ví dụMyUser.objects.get(pk=1)._meta
Paul Whipp

Đúng, nhưng điều đó không truy cập vào lớp Meta bên trong của lớp Model. Truy cập các tùy chọn _meta cho thể hiện của Mô hình đó ... 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 đối với tôi là phân lớp một lớp MyModelProxy proxy từ MyModel theo cách mà MyModelProxy có thể kế thừa lớp Meta bên trong của MyModel.
bdf

Tôi không hoàn toàn rõ ràng về những gì bạn có ý nghĩa bởi 'lớp Meta bên trong' của mô hình nhưng bạn luôn có thể làm việc trực tiếp với lớp học của dụ ví dụtype(MyUser.objects.get(pk=1)).Meta
Paul Whipp

2
"không gian tên thuận tiện cho dữ liệu được chia sẻ giữa các thể hiện của lớp" Dòng đó đã làm điều đó cho tôi.
MGP

22

ModelLớp của Django đặc biệt xử lý việc có một thuộc tính có tên Metalà một lớp. Đây không phải là một điều Python chung.

Siêu dữ liệu Python là hoàn toàn khác nhau.


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

6

Câu trả lời cho rằng mô hình Django Metavà siêu dữ liệu "hoàn toàn khác nhau" là những câu trả lời sai lệch.

Việc xây dựng các đối tượng lớp mô hình Django (nghĩa là đối tượng đại diện cho chính định nghĩa lớp; vâng, các lớp cũng là đối tượng) thực sự được điều khiển bởi một siêu dữ liệu được gọi ModelBase, bạn có thể xem mã đó ở đây:

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

Và một trong những điều cần ModelBaselàm là tạo _metathuộc tính trên mọi mô hình Django có chứa máy móc xác nhận, chi tiết trường, lưu logic và vv. Trong hoạt động này, những thứ được chỉ định trong Metalớp bên trong của mô hình được đọc và sử dụng trong quy trình đó.

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

Đây có thể là một nguồn thông tin hữu ích để hiểu rõ hơn về cách các mô hình Django sử dụng siêu dữ liệu.

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

Và điều này cũng có thể hữu ích nếu bạn muốn hiểu rõ hơn về cách thức các đối tượng hoạt động nói chung.

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


0

Tài liệu lớp Meta bên trong Tài liệu này của siêu dữ liệu mô hình django là bất cứ thứ gì không phải là một trường, chẳng hạn như tùy chọn đặt hàng (thứ tự), tên bảng cơ sở dữ liệu (db_table) hoặc tên số nhiều và số nhiều người có thể đọc được (verbose_name và verbose_name_plural). Không bắt buộc và việc thêm lớp Meta vào mô hình là hoàn toàn tùy chọn. https://docs.djangoproject.com/en/dev/topics/db/models/#meta-options


0

Trong Django, nó hoạt động như một lớp cấu hình và giữ dữ liệu cấu hình ở một nơi !!

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.