कहते हैं कि मैं एक मॉडल फू कि SuperFoo से इनहेरिट करते हैं SuperFoo का नाम फ़ील्ड। क्या मैं? यदि नहीं, तो टेम्पलेट में प्रदर्शित होने के लिए मॉडल फॉर्म परिभाषा के अंदर एक लेबल सेट करने का सबसे अच्छा विकल्प है?कैसे Django में एक सुपर क्लास मॉडल क्षेत्र के वर्बोज़ नाम ओवरराइड करने के लिए
उत्तर
एक सरल हैक मैं का इस्तेमाल किया है है:
class SuperFoo(models.Model):
name = models.CharField('name of SuperFoo instance', max_length=50)
...
class Foo(SuperFoo):
... # do something that changes verbose_name of name field of SuperFoo
Foo._meta.get_field('name').verbose_name = 'Whatever'
यह वास्तव में सुपरफू कक्षा के लिए फ़ील्ड के verbose_name को बदलता है। उदाहरण के लिए, यदि आपके पास है: क्लास बार (सुपरफू), 'name' फ़ील्ड के लिए verbose_name भी 'जो भी' है ... भले ही आप Bar._meta.get_field ('name') के साथ एक ही प्रक्रिया का पालन करें।verbose_name = 'जो भी 2' – mtaube
यदि सुपरफू एक सार आधार वर्ग है, तो उपर्युक्त टिप्पणी सत्य नहीं है। यह विधि तब तक अच्छी तरह से काम करती है जब तक सुपरफू क्लास सारणी है, इसलिए कक्षा मेटा: सार = सही – mtaube
क्या यह अभी भी सच है? – Pureferret
आपकी सर्वश्रेष्ठ शर्त फॉर्म में लेबल को सेट/बदलना होगा। name
Foo
मॉडल (उदाहरण के लिए Foo._meta.fields
में इसे देखकर) आपको SuperFoo
के क्षेत्र का संदर्भ देगा, इसलिए verbose_name
बदलकर इसे दोनों मॉडलों में बदल दिया जाएगा।
इसके अलावा, Foo
वर्ग के लिए एक name
क्षेत्र को जोड़ने के लिए, या तो काम नहीं करेगा because ...
एक माता पिता के मॉडल में ओवरराइड क्षेत्रों क्षेत्रों में कठिनाइयों की ओर जाता है इस तरह के रूप नई उदाहरणों initialising (निर्दिष्ट करने
Model.__init__
) और क्रमबद्धरण में कौन सा क्षेत्र अंतर्निहित किया जा रहा है। ये जो सामान्य अजगर वर्ग विरासत काफी उसी तरह से साथ निपटने के लिए नहीं है विशेषताएं हैं, तो Django मॉडल विरासत और अजगर वर्ग विरासत के बीच अंतर केवल मनमाना नहीं है।
कैसे Django-सीएमएस करता है, वे CMSPlugin
से इनहेरिट मॉडल में db_table
क्षेत्र ओवरराइड पर एक नज़र डालें। मूल बातें (जो मैं भी अपने खुद के सामान के लिए उपयोग करें) करने के लिए नीचे उबाल: आप कुछ चेकों जोड़ सकते हैं
class SuperFooMetaClass(ModelBase):
def __new__(cls, name, bases, attrs):
new_class = super(SuperFooMetaClass, cls).__new__(cls, name, bases, attrs)
new_class._meta.verbose_name = "...." # perhaps only if not customized
return new_class
class SuperFoo(models.Model):
__metaclass__ = SuperFooMetaClass
....
, उदा केवल उप-वर्गों के लिए अद्यतन करें (प्रत्यक्ष प्रकार नहीं), या केवल तभी अद्यतन करें जब मान अनुकूलित नहीं किया गया हो।
Foo._meta.fields को संशोधित करने वाली चेतावनी को ध्यान में रखते हुए सुपरक्लास को भी प्रभावित किया जाएगा - और इसलिए सुपरक्लस अमूर्त होने पर ही वास्तव में उपयोगी होता है, मैंने उत्तर @ gerry को पुन: प्रयोज्य वर्ग सजावट के रूप में छोड़ दिया है:
def modify_fields(**kwargs):
def wrap(cls):
for field, prop_dict in kwargs.items():
for prop, val in prop_dict.items():
setattr(cls._meta.get_field(field), prop, val)
return cls
return wrap
इस तरह यह प्रयोग करें:
@modify_fields(timestamp={
'verbose_name': 'Available From',
'help_text': 'Earliest date you can book this'})
class Purchase(BaseOrderItem):
pass
उपरोक्त उदाहरण विरासत में मिला क्षेत्र 'टाइमस्टैम्प' के लिए verbose_name और help_text बदल जाता है। आप कई कीवर्ड तर्कों में गुजर सकते हैं क्योंकि ऐसे फ़ील्ड हैं जिन्हें आप संशोधित करना चाहते हैं।
उत्तर के लिए धन्यवाद! इसलिए हम या तो (i) किसी फ़ॉर्म के अंदर एक लेबल सेट कर सकते हैं, या (ii) _meta.get_fields विधि के माध्यम से कक्षा को परिभाषित करने के बाद verbose_name सेट कर सकते हैं। दोनों को कार्यान्वित करना आसान है, हालांकि मुझे लगता है कि मैं _meta.get_fields विधि का उपयोग करना पसंद करूंगा ताकि मैं मॉडल मॉड्यूल के अंदर सभी मॉडल-प्रासंगिक चीजें रख सकूं। – shanyu