मैं Django मॉडल में ENUM का उपयोग करने और निर्दिष्ट करने के बारे में कैसे जा सकता हूं?
मैं Django मॉडल में ENUM का उपयोग करने और निर्दिष्ट करने के बारे में कैसे जा सकता हूं?
जवाबों:
से Django प्रलेखन :
MAYBECHOICE = (
('y', 'Yes'),
('n', 'No'),
('u', 'Unknown'),
)
और आप अपने मॉडल में एक charfield परिभाषित करते हैं:
married = models.CharField(max_length=1, choices=MAYBECHOICE)
यदि आप अपने db में अक्षर रखना पसंद नहीं करते हैं तो आप पूर्णांक फ़ील्ड के साथ भी ऐसा कर सकते हैं।
उस मामले में, अपनी पसंद को फिर से लिखें:
MAYBECHOICE = (
(0, 'Yes'),
(1, 'No'),
(2, 'Unknown'),
)
from django.db import models
class EnumField(models.Field):
"""
A field class that maps to MySQL's ENUM type.
Usage:
class Card(models.Model):
suit = EnumField(values=('Clubs', 'Diamonds', 'Spades', 'Hearts'))
c = Card()
c.suit = 'Clubs'
c.save()
"""
def __init__(self, *args, **kwargs):
self.values = kwargs.pop('values')
kwargs['choices'] = [(v, v) for v in self.values]
kwargs['default'] = self.values[0]
super(EnumField, self).__init__(*args, **kwargs)
def db_type(self):
return "enum({0})".format( ','.join("'%s'" % v for v in self.values) )
का उपयोग करते हुए choices
Enum db प्रकार का उपयोग नहीं होगा पैरामीटर; यह सिर्फ एक VARCHAR या choices
INTEGER का निर्माण करेगा, जो इस बात पर निर्भर करता है कि आप एक CharField या IntegerField का उपयोग करते हैं या नहीं। आम तौर पर, यह ठीक है। यदि आपके लिए यह महत्वपूर्ण है कि डेटाबेस स्तर पर ENUM प्रकार का उपयोग किया जाए, तो आपके पास तीन विकल्प हैं:
इनमें से किसी भी विकल्प के साथ, क्रॉस-डेटाबेस पोर्टेबिलिटी के निहितार्थों से निपटना आपकी ज़िम्मेदारी होगी। विकल्प 2 में, आप डेटाबेस-बैकएंड-विशिष्ट कस्टम SQL का उपयोग कर सकते हैं ताकि यह सुनिश्चित हो सके कि आपका TABLE केवल MySQL पर चलता है। विकल्प 3 में, आपकी db_type विधि को डेटाबेस इंजन की जाँच करने और db स्तंभ प्रकार को उस डेटाबेस में सेट करने की आवश्यकता होगी जो वास्तव में उस डेटाबेस में मौजूद है।
अद्यतन : चूंकि Django 1.7 में माइग्रेशन फ्रेमवर्क जोड़ा गया था, इसलिए विकल्प 1 और 2 ऊपर पूरी तरह से अप्रचलित हैं। विकल्प 3 वैसे भी हमेशा सबसे अच्छा विकल्प था। विकल्प 1/2 के नए संस्करण में एक जटिल कस्टम माइग्रेशन शामिल होगा SeparateDatabaseAndState
- लेकिन वास्तव में आप विकल्प 3 चाहते हैं।
http://www.b-list.org/weblog/2007/nov/02/handle-choices-right-way/
class Entry(models.Model): LIVE_STATUS = 1 DRAFT_STATUS = 2 HIDDEN_STATUS = 3 STATUS_CHOICES = ( (LIVE_STATUS, 'Live'), (DRAFT_STATUS, 'Draft'), (HIDDEN_STATUS, 'Hidden'), ) # ...some other fields here... status = models.IntegerField(choices=STATUS_CHOICES, default=LIVE_STATUS) live_entries = Entry.objects.filter(status=Entry.LIVE_STATUS) draft_entries = Entry.objects.filter(status=Entry.DRAFT_STATUS) if entry_object.status == Entry.LIVE_STATUS:
यह enums लागू करने का एक और अच्छा और आसान तरीका है, हालांकि यह वास्तव में डेटाबेस में enums को सहेजता नहीं है।
हालाँकि, यह आपको 'लेबल' को संदर्भित करने की अनुमति देता है जब भी टॉप-रेटेड उत्तर के विरोध के रूप में डिफॉल्ट को क्वेरी या निर्दिष्ट करता है जहां आपको 'मूल्य' (जो एक संख्या हो सकती है) का उपयोग करना होगा।
choices
फ़ील्ड पर सेट करने से Django के अंत पर कुछ सत्यापन की अनुमति मिल जाएगी, लेकिन यह डेटाबेस के अंत पर किसी भी प्रकार के किसी भी प्रकार को परिभाषित नहीं करेगा ।
जैसा कि दूसरों ने उल्लेख किया है, समाधान db_type
एक कस्टम फ़ील्ड पर निर्दिष्ट करना है।
यदि आप SQL बैकएंड (जैसे MySQL) का उपयोग कर रहे हैं, तो आप ऐसा कर सकते हैं:
from django.db import models
class EnumField(models.Field):
def __init__(self, *args, **kwargs):
super(EnumField, self).__init__(*args, **kwargs)
assert self.choices, "Need choices for enumeration"
def db_type(self, connection):
if not all(isinstance(col, basestring) for col, _ in self.choices):
raise ValueError("MySQL ENUM values should be strings")
return "ENUM({})".format(','.join("'{}'".format(col)
for col, _ in self.choices))
class IceCreamFlavor(EnumField, models.CharField):
def __init__(self, *args, **kwargs):
flavors = [('chocolate', 'Chocolate'),
('vanilla', 'Vanilla'),
]
super(IceCreamFlavor, self).__init__(*args, choices=flavors, **kwargs)
class IceCream(models.Model):
price = models.DecimalField(max_digits=4, decimal_places=2)
flavor = IceCreamFlavor(max_length=20)
ठीक से बनाया गया था, syncdb
यह देखने के लिए अपनी तालिका को चलाएं और निरीक्षण करें ENUM
।
mysql> SHOW COLUMNS IN icecream;
+--------+-----------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-----------------------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| price | decimal(4,2) | NO | | NULL | |
| flavor | enum('chocolate','vanilla') | NO | | NULL | |
+--------+-----------------------------+------+-----+---------+----------------+
'type "enum" does not exist LINE 1: ....tablename" ADD COLUMN "select_user" ENUM('B', ...'
।
यदि आप वास्तव में अपने डेटाबेस ENUM प्रकार का उपयोग करना चाहते हैं:
सौभाग्य!
वर्तमान में इन्हें जोड़ने के आधार पर दो गितुब परियोजनाएं हैं, हालांकि मैंने इस बात पर ध्यान नहीं दिया है कि वे कैसे कार्यान्वित की जाती हैं:
मुझे नहीं लगता कि या तो DB enum प्रकारों का उपयोग करें, लेकिन वे पहले एक के लिए काम कर रहे हैं ।
से प्रलेखन :
from django.utils.translation import gettext_lazy as _
class Student(models.Model):
class YearInSchool(models.TextChoices):
FRESHMAN = 'FR', _('Freshman')
SOPHOMORE = 'SO', _('Sophomore')
JUNIOR = 'JR', _('Junior')
SENIOR = 'SR', _('Senior')
GRADUATE = 'GR', _('Graduate')
year_in_school = models.CharField(
max_length=2,
choices=YearInSchool.choices,
default=YearInSchool.FRESHMAN,
)
अब, ध्यान रखें कि यह एक डेटाबेस स्तर पर विकल्पों को लागू नहीं करता है यह पायथन केवल निर्माण है। यदि आप डेटाबेस में उन मानों को लागू करना चाहते हैं जिन्हें आप डेटाबेस की कमी के साथ जोड़ सकते हैं:
class Student(models.Model):
...
class Meta:
constraints = [
CheckConstraint(
check=Q(year_in_school__in=YearInSchool.values),
name="valid_year_in_school")
]