1. 程式人生 > >西遊之路——python全棧——Django中模型類中Meta元物件瞭解

西遊之路——python全棧——Django中模型類中Meta元物件瞭解

目錄

Django中模型類中Meta元物件瞭解
  1.使用python manage.py shell 進入編輯命令列模式,可以直接進入專案(為我們配置好了環境)
  2.對於元類資料的獲取,需要使用_meta獲取
  3.幾個重要屬性
   4.通過元類獲取choice欄位值

Django中模型類中Meta元物件瞭解

1.使用python manage.py shell 進入編輯命令列模式,可以直接進入專案(為我們配置好了環境)

python manage.py shell

2.對於元類資料的獲取,需要使用_meta獲取

>>> models.CustumerInfo._meta
<Options for CustumerInfo>
dir(models.CustumerInfo._meta)獲取該資料表所有的元類屬性

3.幾個重要屬性

複製程式碼
app_label:表示它屬於哪個應用    models.CustumerInfo._meta.app_label ---> 'repository' 在repository應用下面

model_name:獲取模型名(表對應的類名)models.CustumerInfo._meta.model_name ---> 'custumerinfo' #小寫

label:獲取的是repository.CustumerInfo  #分大小寫

label_lower:不區分大小寫

db_table:獲取完整表名,含資料庫 repository_custumerinfo

其他可以根據在元類中所設定的去獲取資料:更多屬性可看https://blog.csdn.net/gavinking0110/article/details/53126203
複製程式碼

 4.通過元類獲取choice欄位值

(1)補充:如何獲取含choice屬性的欄位值對應的字串(重點)

    status_choices = ((0,"未報名"),(1,"已報名"),(2,"已退學"))
    status = models.SmallIntegerField(choices=status_choices)

================

 1
source_choices = ( 2 (0,'QQ群'), 3 (1,"51CTO"), 4 (2,"百度推廣"), 5 (3,"知乎"), 6 (4,"轉介紹"), 7 (5,"其他") 8 ) 9 source = models.SmallIntegerField(choices=source_choices) 10 11 source 欄位
source 欄位

===============

複製程式碼
1.首先獲取當前物件
>>> a = models.CustumerInfo.objects.last()
>>> a
<CustumerInfo: 三狗子>

2.使用方法get_欄位名_display()獲取對應字串
>>> a.get_status_display()
'未報名'
>>> a.get_source_display()
'其他'
複製程式碼

 

這種方法也可以動態獲取對應的字串:

複製程式碼
動態拼接:獲取方法名
>>> hasattr(a,"get_status_display")
True
>>> hasattr(a,"get_name_display")
False

根據返回的bool值,去判斷是否去呼叫對應的方法

>>> getattr(a,"get_status_display")()
'未報名'
複製程式碼

但是上面只能獲取到當前選中的值得對應字串,如何去獲取所有可選選項,一種是去model模型類獲取該屬性。若是上面這個不允許,那我們可以使用元類的屬性去獲取

(2)注意:每一個欄位,都是一個物件。

models.CustumerInfo._meta.fields
1 >>> models.CustumerInfo._meta.fields
2 (<django.db.models.fields.AutoField: id>, <django.db.models.fields.CharField: na
3 me>, <django.db.models.fields.SmallIntegerField: contact_type>, <django.db.model
4 s.fields.CharField: contact>, <django.db.models.fields.SmallIntegerField: source
5 >, <django.db.models.fields.related.ForeignKey: referral_from>, <django.db.model
6 s.fields.TextField: consult_content>, <django.db.models.fields.SmallIntegerField
7 : status>, <django.db.models.fields.related.ForeignKey: consultant>, <django.db.
8 models.fields.DateField: date>)
輸出的所有欄位物件

通過get_field(欄位名)獲取當前欄位物件

複製程式碼
>>> a = models.CustumerInfo._meta.get_field("source")
>>> a
<django.db.models.fields.SmallIntegerField: source>

>>> a = models.CustumerInfo._meta.get_field("name")
>>> a
<django.db.models.fields.CharField: name>
複製程式碼

獲取到欄位物件後可以去獲取欄位的屬性(對於我們所需的欄位中就含有choice屬性)

 1 >>> dir(a)
 2 ['__class__', '__copy__', '__deepcopy__', '__delattr__', '__dict__', '__dir__',
 3 '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__ha
 4 sh__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__red
 5 uce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__
 6 subclasshook__', '__weakref__', '_check_backend_specific_checks', '_check_choice
 7 s', '_check_db_index', '_check_deprecation_details', '_check_field_name', '_chec
 8 k_max_length_attribute', '_check_null_allowed_for_primary_keys', '_clear_cached_
 9 lookups', '_description', '_error_messages', '_get_default', '_get_flatchoices',
10  '_get_lookup', '_get_val_from_obj', '_unique', '_unregister_lookup', '_validato
11 rs', '_verbose_name', 'attname', 'auto_created', 'auto_creation_counter', 'blank
12 ', 'cached_col', 'check', 'choices', 'class_lookups', 'clean', 'clone', 'column'
13 , 'concrete', 'contribute_to_class', 'creation_counter', 'db_check', 'db_column'
14 , 'db_index', 'db_parameters', 'db_tablespace', 'db_type', 'db_type_suffix', 'de
15 construct', 'default', 'default_error_messages', 'default_validators', 'descript
16 ion', 'editable', 'empty_strings_allowed', 'empty_values', 'error_messages', 'fl
17 atchoices', 'formfield', 'get_attname', 'get_attname_column', 'get_cache_name',
18 'get_choices', 'get_col', 'get_db_converters', 'get_db_prep_save', 'get_db_prep_
19 value', 'get_default', 'get_filter_kwargs_for_object', 'get_internal_type', 'get
20 _lookup', 'get_lookups', 'get_pk_value_on_save', 'get_prep_value', 'get_transfor
21 m', 'has_default', 'help_text', 'hidden', 'is_relation', 'many_to_many', 'many_t
22 o_one', 'max_length', 'merge_dicts', 'model', 'name', 'null', 'one_to_many', 'on
23 e_to_one', 'pre_save', 'primary_key', 'register_lookup', 'rel', 'rel_db_type', '
24 related_model', 'remote_field', 'run_validators', 'save_form_data', 'select_form
25 at', 'serialize', 'set_attributes_from_name', 'system_check_deprecated_details',
26  'system_check_removed_details', 'to_python', 'unique', 'unique_for_date', 'uniq
27 ue_for_month', 'unique_for_year', 'validate', 'validators', 'value_from_object',
28  'value_to_string', 'verbose_name']
29 
30 dir(欄位物件),獲取欄位物件的所有屬性
dir(欄位物件),獲取欄位物件的所有屬性

==================

複製程式碼
>>> a = models.CustumerInfo._meta.get_field("status")
>>> a.choices
((0, '未報名'), (1, '已報名'), (2, '已退學'))
#對於含有choices,輸出是有值的

>>> a = models.CustumerInfo._meta.get_field("name")
>>> a.choices
[]
#對於不含choices,輸出為空
複製程式碼

可以通過欄位物件獲取與之關聯的表(外來鍵或者多對多)

複製程式碼
>>> a = CustumerInfo._meta.get_field("consult_courses")    #獲取欄位物件

>>> a.rel.to
<class 'repository.models.Course'>    #獲取對應的關聯表

>>> a.related_model
<class 'repository.models.Course'>    #或者使用related_model屬性獲取
複製程式碼

 (3)對於外來鍵,我們想要獲取到像choice一樣的資料,可以使用get_choices()方法

複製程式碼
>>> a = models.CustumerInfo._meta.get_field("consultant")  #consultant是外來鍵
>>> a
<django.db.models.fields.related.ForeignKey: consultant>
>>> a.choices  #其中choices是空,但是我們想要獲取資料,類似於choices,可以用於篩選
[]
>>> a.get_choices()  #使用get_choices()方法用於獲取外來鍵資料,形成類似於select標籤
[('', '---------'), (1, '寧靜致遠'), (2, '三少爺的劍')]
複製程式碼

注意:對於原來的含有choice屬性的欄位,也可以使用get_choices()方法,來獲取。不過就也是在前面多了一個選項(類似於請選擇的意思)

>>> a = models.CustumerInfo._meta.get_field("status")  #status含有choice屬性
>>> a.choices
((0, '未報名'), (1, '已報名'), (2, '已退學'))
>>> a.get_choices()
[('', '---------'), (0, '未報名'), (1, '已報名'), (2, '已退學')]

注意對於其他欄位是不含有get_choices()方法,會報錯。所以不要亂用

複製程式碼
>>> a = models.CustumerInfo._meta.get_field("name")  #CharFields
>>> a.get_choices()
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python35\lib\site-p
ackages\django\db\models\fields\__init__.py", line 811, in get_choices
    rel_model = self.remote_field.model
AttributeError: 'NoneType' object has no attribute 'model'
複製程式碼

(4)獲取欄位物件的型別get_internal_type()

複製程式碼
>>> a = models.CustumerInfo._meta.get_field("name")
>>> a.get_internal_type()
'CharField'


>>> a = models.CustumerInfo._meta.get_field("date")
>>> a.get_internal_type()
'DateField'
複製程式碼

(5)上面是單個欄位的關聯表,那麼如何獲取這張表的外來鍵關聯(一對多,一對一,多對多)?

複製程式碼
>>> a = CustumerInfo._meta  #這張表的元類

>>> for item in a.related_objects:    #是獲取所有由其他表來關聯自己的那些表,也含有多對多關聯資訊  反向關聯_set
...     print(item)
...
<ManyToOneRel: repository.custumerinfo>  #每條都是一個外來鍵欄位資訊,可以使用get_internal_type獲取其前面的型別:ManyToOneRel:注意也會有ManyToManyRel多對多關聯
<ManyToOneRel: repository.custumerfollowup>
<ManyToOneRel: repository.student>

>>> for item in a.fields_map.items():  #不止其他表來關聯自己,還有自己去關聯其他表 ... print(item) ... ('student', <ManyToOneRel: repository.student>) ('CustumerInfo_consult_courses+', <ManyToOneRel: repository.custumerinfo_consult_courses>)  #自己表去關聯其他表,後面有個+ ('custumerfollowup', <ManyToOneRel: repository.custumerfollowup>) ('custumerinfo', <ManyToOneRel: repository.custumerinfo>)
複製程式碼

補充:ManyToOneRel物件

 1 ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__form
 2 at__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__in
 3 it__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__r
 4 educe_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook
 5 __', '__weakref__', 'auto_created', 'concrete', 'db_type', 'editable', 'field',
 6 'field_name', 'get_accessor_name', 'get_cache_name', 'get_choices', 'get_extra_r
 7 estriction', 'get_internal_type', 'get_joining_columns', 'get_lookup', 'get_path
 8 _info', 'get_related_field', 'hidden', 'is_hidden', 'is_relation', 'limit_choice
 9 s_to', 'many_to_many', 'many_to_one', 'model', 'multiple', 'name', 'null', 'on_d
10 elete', 'one_to_many', 'one_to_one', 'parent_link', 'related_model', 'related_na
11 me', 'related_query_name', 'remote_field', 'set_field_name', 'symmetrical', 'tar
12 get_field', 'to']
13 
14 其含有的所有屬性
其含有的所有屬性

===================

複製程式碼
>>> a = CustumerInfo._meta.related_objects
>>> a
(<ManyToOneRel: repository.custumerinfo>, <ManyToOneRel: repository.custumerfoll
owup>, <ManyToOneRel: repository.student>)
>>> a[0]
<ManyToOneRel: repository.custumerinfo>

-------------------------------------------------------------
主要屬性:
>>> a[0].name    #該表的表名  根據這個可以在主表中對這張表進行反向關聯_set
'custumerinfo'

>>> a[0].field_name    #主鍵欄位名
'id'

>>> a[0].field        #field是外來鍵欄位
<django.db.models.fields.related.ForeignKey: referral_from>
>>> a[1].field
<django.db.models.fields.related.ForeignKey: customer>
複製程式碼

注意:上面我們是直接使用類去呼叫元類,其實也是可以使用物件去呼叫元類,一樣

複製程式碼
類呼叫:
>>> a = CustumerInfo._meta
>>> a.related_objects
(<ManyToOneRel: repository.custumerinfo>, <ManyToOneRel: repository.custumerfoll
owup>, <ManyToOneRel: repository.student>)

物件呼叫:
>>> a = CustumerInfo.objects.all()[0]
>>> a
<CustumerInfo: 張三>
>>> a._meta
<Options for CustumerInfo>
>>> a._meta.related_objects
(<ManyToOneRel: repository.custumerinfo>, <ManyToOneRel: repository.custumerfoll
owup>, <ManyToOneRel: repository.student>)
複製程式碼

總結:

_meta.fields 獲取所有欄位

_meta.fields_map/related_objects獲取反向關聯,related_objects中只有反向關聯,fields_map有正向關聯,不過欄位名為(表名_欄位名+).例如:'CustumerInfo_consult_courses+'

_meta.many_to_many/local_many_to_many獲取多對多關聯