2008-08-21 15 views
78

में एक MySQL ENUM निर्दिष्ट करना मैं Django मॉडल में ENUM निर्दिष्ट करने और उपयोग करने के बारे में कैसे जा सकता हूं?एक Django मॉडल

+3

स्टीव, यदि आप MySQL ENUM प्रकार का उपयोग करना चाहते हैं, तो आप भाग्य से बाहर हैं, जहां तक ​​मुझे पता है कि Django उस के लिए समर्थन प्रदान नहीं करता है (यह सुविधा Django द्वारा समर्थित सभी डीबी में उपलब्ध नहीं है)। पॉल द्वारा प्रदान किया गया उत्तर काम करता है, लेकिन यह ** ** डीबी में प्रकार को परिभाषित नहीं करेगा। – dguaraglia

उत्तर

90
Django documentation से

:

MAYBECHOICE = (
    ('y', 'Yes'), 
    ('n', 'No'), 
    ('u', 'Unknown'), 
) 

और तुम अपने मॉडल में एक charfield निर्धारित करें: यदि आप में पत्र के लिए पसंद नहीं है

married = models.CharField(max_length=1, choices=MAYBECHOICE) 

आप पूर्णांक क्षेत्रों के साथ भी ऐसा ही कर सकते हैं आपका डीबी

उस मामले में, अपने विकल्पों को फिर से लिखने:

MAYBECHOICE = (
    (0, 'Yes'), 
    (1, 'No'), 
    (2, 'Unknown'), 
) 
+7

यह "झूठी" मानों को सहेजने से नहीं रोकता है अगर पहले साफ नहीं किया गया है, है ना? – Strayer

+0

@Strayer yes, मुझे लगता है कि यह केवल मॉडल रूपों का उपयोग करने के लिए उपयोगी है – Acute

+0

नोट करें कि अनुशंसित Django शैली का तात्पर्य है कि वर्ण स्थिरांक होना चाहिए: https://docs.djangoproject.com/en/dev/internals/contributing/writing-code/कोडिंग-शैली/# मॉडल-शैली –

29

choices पैरामीटर का उपयोग Enum db प्रकार का उपयोग नहीं किया जाएगा; यह सिर्फ एक VARCHAR या INTEGER बनाएगा, इस पर निर्भर करता है कि क्या आप choices का उपयोग CharField या IntegerField के साथ करते हैं। आम तौर पर, यह ठीक है।

  1. उपयोग "./manage.py एसक्यूएल APPNAME" को देखने के लिए एसक्यूएल Django उत्पन्न करता है, मैन्युअल रूप से उपयोग करने के लिए इसे संशोधित: यदि यह आप के लिए महत्वपूर्ण है कि Enum प्रकार डेटाबेस स्तर पर प्रयोग किया जाता है, तो आप तीन विकल्प हैं ENUM प्रकार, और इसे स्वयं चलाएं। यदि आप पहले मैन्युअल रूप से तालिका बनाते हैं, तो "./manage.py syncdb" इसके साथ गड़बड़ नहीं करेगा।
  2. यदि आप अपना डीबी उत्पन्न करते समय हर बार मैन्युअल रूप से ऐसा नहीं करना चाहते हैं, तो उचित वैकल्पिक तालिका कमांड करने के लिए कुछ कस्टम एसक्यूएल एपनाम/एसक्यूएल/modelname.sql में रखें।
  3. custom field type बनाएं और उचित रूप से db_type विधि को परिभाषित करें।

इनमें से किसी भी विकल्प के साथ, क्रॉस-डेटाबेस पोर्टेबिलिटी के प्रभावों से निपटने की आपकी ज़िम्मेदारी होगी। विकल्प 2 में, आप यह सुनिश्चित करने के लिए database-backend-specific custom SQL का उपयोग कर सकते हैं कि आपका वैकल्पिक तालिका केवल MySQL पर चलती है। विकल्प 3 में, आपकी db_type विधि को डेटाबेस इंजन की जांच करने और डीबी कॉलम प्रकार को उस प्रकार में सेट करने की आवश्यकता होगी जो वास्तव में उस डेटाबेस में मौजूद है।

अद्यतन: चूंकि माइग्रेशन फ्रेमवर्क Django 1.7 में जोड़ा गया था, ऊपर विकल्प 1 और 2 पूरी तरह से अप्रचलित हैं। वैसे भी विकल्प 3 हमेशा सबसे अच्छा विकल्प था। विकल्पों 1/2 के नए संस्करण SeparateDatabaseAndState का उपयोग कर एक जटिल कस्टम माइग्रेशन शामिल होगा - लेकिन वास्तव में आप चाहते हैं विकल्प 3.

6

तुम सच में अपने डेटाबेस Enum प्रकार का उपयोग करना चाहते हैं:

  1. उपयोग Django 1। एक्स
  2. अपने एप्लिकेशन को पहचानें केवल कुछ डेटाबेस पर काम करेगा।
  3. इस दस्तावेज़ पेज के माध्यम से पहेली: http://docs.djangoproject.com/en/dev/howto/custom-model-fields/#howto-custom-model-fields

गुड लक!

34
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)) 
+1

धन्यवाद। यहां पुन: प्रयोज्य कोड के रूप में सूचीबद्ध http://www.codecatalog.net/407/ – luqui

+2

django 1.2 के रूप में, आपको db_type def में दूसरा पैरामीटर, कनेक्शन जोड़ने की आवश्यकता होगी। –

+2

तब भी कोडकेलॉग के साथ जो भी हुआ? इस तरह के लोको एक अच्छा विचार हो सकता था .... मुझे अब 404 मिल गया है - रूट पेज के लिए भी। –

8

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 को लागू करने का एक और अच्छा और आसान तरीका है।

हालांकि यह आपको 'लेबल' का संदर्भ देने के लिए अनुमति देता है, जब भी आपको 'मान' (जो कि एक संख्या हो सकती है) का उपयोग करने के लिए शीर्ष-रेटेड उत्तर के विपरीत डिफ़ॉल्ट रूप से पूछताछ या निर्दिष्ट करना है।

9

मैदान पर choices स्थापना Django अंत पर कुछ सत्यापन की अनुमति देगा, लेकिन यह डेटाबेस अंत पर एक enumerated प्रकार के किसी भी रूप को परिभाषित नहीं होंगे।

जैसा कि अन्य ने उल्लेख किया है, समाधान कस्टम क्षेत्र पर 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 |    | 
+--------+-----------------------------+------+-----+---------+----------------+ 
+0

बहुत उपयोगी उत्तर! लेकिन यह PostgreSQL के लिए काम नहीं करेगा। कारण PostgreSQL ENUM डिफ़ॉल्ट का समर्थन नहीं करता है। PostgreSQL में पहले हमें CREATE DOMAIN बनाना या प्रकार बनाना बनाना है। रेफ [8.7। समेकित प्रकार] (http://www.postgresql.org/docs/9.2/static/datatype-enum.html) मैंने @ डेविड की चाल की कोशिश की और यह MySQL के साथ ठीक काम कर रहा है लेकिन PostgrSQL में एक त्रुटि के साथ काम समाप्त हो गया है ' प्रकार "enum" मौजूद नहीं है लाइन 1: .... tablename "जोड़ें COLUMN" select_user "ENUM ('B', ... '' –

-2

एक अपने models.py फ़ाइल के शीर्ष, इस पंक्ति जोड़ें:

enum = lambda *l: [(s,_(s)) for s in l] 
+0

यह कैसे काम करता है? – Pureferret

3

वर्तमान में दो GitHub इन जोड़ने के आधार पर परियोजनाओं वहाँ रहे हैं, हालांकि मैं नहीं है वास्तव में देखा कि वे किस तरह से लागू किया जाता है:

  1. Django-EnumField:
    पुन: प्रयोज्य enums और संक्रमण valida के साथ एक गणन Django मॉडल क्षेत्र (IntegerField का प्रयोग करके) प्रदान करता है tion।
  2. Django-EnumFields:
    यह पैकेज आपको Django के साथ असली पायथन (पीईपी 435-शैली) enums का उपयोग करने देता है।

मुझे नहीं लगता कि या तो डीबी एनम प्रकार का उपयोग करें, लेकिन वे पहले के लिए in the works हैं।

संबंधित मुद्दे