জ্যাঙ্গো মডেলটিতে একটি মাইএসকিউএল ENUM নির্দিষ্ট করে Spec


93

জ্যাঙ্গো মডেলটিতে ENUM নির্দিষ্টকরণ এবং ব্যবহার সম্পর্কে আমি কীভাবে যেতে পারি?


4
স্টিভ, যদি আপনি মাইএসকিউএল এনইউএম টাইপ ব্যবহার করে বোঝাতে চেয়েছিলেন তবে আপনি ভাগ্য থেকে দূরে রয়েছেন, যতদূর আমি জানি যে জাঙ্গো তার পক্ষে সমর্থন সরবরাহ করে না (এই বৈশিষ্ট্যটি জ্যাঙ্গো সমর্থিত সমস্ত ডিবিতে উপলব্ধ নেই)। পল প্রদত্ত উত্তরটি কাজ করে, তবে এটি ডিবিতে প্রকারটি সংজ্ঞায়িত করবে না
dguaraglia

উত্তর:


109

থেকে জ্যাঙ্গো ডকুমেন্টেশন :

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

এবং আপনি আপনার মডেলটিতে একটি চরফিল্ড সংজ্ঞায়িত করেছেন:

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

আপনি যদি আপনার ডিবিতে অক্ষর রাখতে না চান তবে আপনি পূর্ণসংখ্যার ক্ষেত্রগুলির সাথেও এটি করতে পারেন।

সেক্ষেত্রে আপনার পছন্দগুলি পুনরায় লিখুন:

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

8
এটি "মিথ্যা" মানগুলি সংরক্ষণ থেকে বাধা দেয় না যদি আগে পরিষ্কার না করা হয়, তাই না?
স্ট্রেয়ার

@ স্ট্রেয়ার হ্যাঁ, আমি অনুমান করি এটি কেবলমাত্র মডেল ফর্মগুলি ব্যবহারের জন্য কার্যকর
একিউট

উল্লেখ্য যে প্রস্তাবিত জ্যাঙ্গো শৈলীতে বোঝানো হয়েছে যে অক্ষরগুলি ধ্রুবক হওয়া উচিত: ডকস.ডজ্যাঙ্গোপ্রজেক্ট
মাইকেল

13
@ কার্ল মায়ার যেমন তার উত্তরে বলেছিলেন, এটি ডাটাবেসে কোনও ENUM কলাম তৈরি করে না। এটি একটি VARCHAR বা INTEGER কলাম তৈরি করে, সুতরাং এটি সত্যই প্রশ্নের উত্তর দেয় না।
এরিয়েল

আমি কি পূর্ণসংখ্যার ক্ষেত্রের সাথে পছন্দগুলি বৈশিষ্ট্য যুক্ত করতে পারি? @ ফুলমিকোটন
ইলিয়াস করিম

36
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) )

4
জাঙ্গো ১.২ অনুসারে, আপনাকে db_type Def এ একটি দ্বিতীয় প্যারামিটার, সংযোগ যুক্ত করতে হবে।
হ্যান্স লরেনজ

4
কোডেকটলগের যা কিছু হয়েছিল তখন? এটির মতো লোকগুলিও ভাল ধারণা হতে পারে .... আমি এখন একটি 404 পেয়েছি - এমনকি মূল পৃষ্ঠার জন্যও।
ড্যানি স্ট্যাপল

33

ব্যবহার choicesENUM ডিবি টাইপ ব্যবহার করা হবে না পরামিতি; আপনি choicesচার্ফিল্ড বা ইন্টিজারফিল্ড ব্যবহার করেন কিনা তার উপর নির্ভর করে এটি কেবল একটি ভোচারার বা ইন্টিগার তৈরি করবে। সাধারণত, এটি ঠিক আছে। যদি এটি আপনার কাছে গুরুত্বপূর্ণ হয় যে ENUM টাইপটি ডাটাবেস স্তরে ব্যবহৃত হয় তবে আপনার কাছে তিনটি বিকল্প রয়েছে:

  1. এসকিউএল জ্যাঙ্গো জেনারেট করে, ENUM টাইপটি ব্যবহার করার জন্য ম্যানুয়ালি এটি সংশোধন করে দেখুন এবং এটি নিজে চালনা করতে "./manage.py এসকিএল অ্যাপ্লিকেশন" ব্যবহার করুন। আপনি যদি প্রথমে টেবিলটি ম্যানুয়ালি তৈরি করেন তবে "./manage.py syncdb" এতে বিচলিত হবে না।
  2. আপনি নিজের ডিবি তৈরির সময় প্রতিবার যদি ম্যানুয়ালি এটি না করতে চান তবে যথাযথ অল্টার টেবিল কমান্ডটি সম্পাদন করতে অ্যাপ্লিকেশন / এসকিএল / মডেলনাম.এসকিউএলে কিছু কাস্টম এসকিউএল রাখুন।
  3. একটি কাস্টম ফিল্ড প্রকার তৈরি করুন এবং db_type পদ্ধতি যথাযথভাবে সংজ্ঞায়িত করুন।

এই বিকল্পগুলির যে কোনওটির সাথে, ক্রস-ডাটাবেস বহনযোগ্যতার জন্য জড়িতদের মোকাবেলা করা আপনার দায়িত্ব হবে। বিকল্প 2-এ, আপনার অ্যালটার টেবিলটি কেবল মাইএসকিউএলে চালিত হয়েছে তা নিশ্চিত করতে আপনি ডাটাবেস-ব্যাকেন্ড-নির্দিষ্ট কাস্টম এসকিউএল ব্যবহার করতে পারেন । বিকল্প 3-তে, আপনার db_type পদ্ধতিতে ডাটাবেস ইঞ্জিনটি পরীক্ষা করে ডিবি কলামের ধরণটি এমন একটি ধরণের সেট করতে হবে যা সেই ডাটাবেজে আসলে বিদ্যমান।

আপডেট : যেহেতু মাইগ্রেশন ফ্রেমওয়ার্কটি জ্যাঙ্গো ১.7 এ যুক্ত করা হয়েছিল, উপরোক্ত 1 এবং 2 বিকল্পগুলি সম্পূর্ণ অপ্রচলিত। বিকল্প 3 সর্বদা সর্বোত্তম বিকল্প ছিল যাইহোক। বিকল্পগুলির 1/2 নতুন সংস্করণটি ব্যবহার করে একটি জটিল কাস্টম মাইগ্রেশন জড়িত SeparateDatabaseAndState- তবে সত্যই আপনি চান বিকল্প 3।


10

http://www.b-list.org/weblog/2007/nov/02/handle-choice-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 বাস্তবায়নের আরেকটি দুর্দান্ত এবং সহজ উপায় যদিও এটি ডেটাবেজে সত্যই এনামগুলিকে সংরক্ষণ করে না।

তবে এটি আপনাকে 'লেবেল' রেফারেন্স দেয় যখনই আপনি জিজ্ঞাসা করছেন বা যখন আপনাকে 'মান' (যা একটি সংখ্যা হতে পারে) ব্যবহার করতে হবে শীর্ষ-উত্তরের উত্তরের বিপরীতে ডিফল্ট নির্দিষ্ট করে spec


9

choicesক্ষেত্রটিতে সেট করা জাঙ্গো প্রান্তে কিছু বৈধতা আনতে অনুমতি দেবে, তবে এটি ডাটাবেসের শেষে কোনও গণিতের কোনও ফর্ম সংজ্ঞায়িত করবে না

অন্যরা যেমন উল্লেখ করেছে, সমাধানটি হ'ল db_typeএকটি কাস্টম ক্ষেত্রে নির্দিষ্ট করা।

যদি আপনি কোনও এসকিউএল ব্যাকএন্ড ব্যবহার করেন (উদাঃ মাইএসকিউএল), আপনি এটি এর মতো করতে পারেন:

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    |                |
+--------+-----------------------------+------+-----+---------+----------------+

খুব সহায়ক উত্তর! তবে এটি পোস্টগ্র্যাসকিউএল এর জন্য কাজ করবে না। কারণ পোস্টগ্রিসকিউএল এনইউএম ডিফল্ট সমর্থন করে না। পোস্টগ্রেএসকিউএল-এ প্রথমে আমাদের তৈরি করতে হবে ক্রিম্যাট DOMAIN বা ক্রিয়েট টাইপ। রেফ 8.7। অঙ্কিত প্রকারগুলি আমি ডেভিডের কৌশলটিকে চেষ্টা করেছি এবং এটি মাইএসকিউএল দিয়ে ভাল কাজ করছে তবে পোস্টগ্র্যাসকিউএল ওয়ার্কে একটি ত্রুটি রয়েছে 'type "enum" does not exist LINE 1: ....tablename" ADD COLUMN "select_user" ENUM('B', ...'
গ্রিজেশ চৌহান

6

আপনি যদি সত্যিই আপনার ডাটাবেসগুলি ENUM টাইপ ব্যবহার করতে চান তবে:

  1. জাজানো 1.x ব্যবহার করুন
  2. আপনার অ্যাপ্লিকেশনটি সনাক্ত করুন কেবলমাত্র কিছু ডেটাবেজে কাজ করবে।
  3. এই ডকুমেন্টেশন পৃষ্ঠার মাধ্যমে ধাঁধা: http://docs.djangoproject.com/en/dev/howto/custom-model-fields/#howto-custom-model-fields

শুভকামনা!


3

এগুলি যুক্ত করার উপর ভিত্তি করে দুটি গিথুব প্রকল্প রয়েছে, যদিও আমি কীভাবে সেগুলি বাস্তবায়িত করছি তা আমি খতিয়ে দেখিনি:

  1. জ্যাঙ্গো-এনামফিল্ড :
    পুনরায় ব্যবহারযোগ্য এনামস এবং ট্রানজিশনের বৈধতা সহ একটি গণনা জ্যাঙ্গো মডেল ফিল্ড (ইন্টিজারফিল্ড ব্যবহার করে) সরবরাহ করে।
  2. জ্যাঙ্গো-এনামফিল্ডস :
    এই প্যাকেজটি আপনাকে জ্যাঙ্গোর সাথে বাস্তব পাইথন (পিইপি 435-স্টাইল) এনাম ব্যবহার করতে দেয়।

আমি মনে করি না হয় ডিবি এনাম প্রকারগুলি ব্যবহার করুন, তবে তারা প্রথমটির জন্য কাজ করছে।


1

জাজানো 3.0 এ এনমসের জন্য অন্তর্নির্মিত সমর্থন করেছে

ডকুমেন্টেশন থেকে :

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")
        ]

-2

আপনার মডেল.পি ফাইলের শীর্ষস্থানীয়, আপনি আপনার আমদানি করার পরে এই লাইনটি যুক্ত করুন:

    enum = lambda *l: [(s,_(s)) for s in l]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.