Django - दक्षिण का उपयोग करके एक मॉडल फ़ील्ड का नाम कैसे बदला जाए?


209

मैं एक मॉडल में विशिष्ट क्षेत्रों का नाम बदलना चाहूंगा:

class Foo(models.Model):
    name = models.CharField()
    rel  = models.ForeignKey(Bar)

में बदलना चाहिए:

class Foo(models.Model):
    full_name     = models.CharField()
    odd_relation  = models.ForeignKey(Bar)

दक्षिण का उपयोग करके ऐसा करने का सबसे आसान तरीका क्या है?


7
मॉडल क्षेत्र के बजाय मॉडल का नाम बदलने के लिए stackoverflow.com/questions/2862979/… को भी देखें ।
मेकैनिकल घोंघा में

जवाबों:


230

आप db.rename_columnफ़ंक्शन का उपयोग कर सकते हैं ।

class Migration:

    def forwards(self, orm):
        # Rename 'name' field to 'full_name'
        db.rename_column('app_foo', 'name', 'full_name')




    def backwards(self, orm):
        # Rename 'full_name' field to 'name'
        db.rename_column('app_foo', 'full_name', 'name')

का पहला तर्क db.rename_columnतालिका नाम है, इसलिए यह याद रखना महत्वपूर्ण है कि Django तालिका के नाम कैसे बनाता है :

Django स्वचालित रूप से डेटाबेस तालिका का नाम आपके मॉडल वर्ग और उस ऐप के नाम से प्राप्त करता है जिसमें यह शामिल है। मॉडल के "ऐप लेबल" में शामिल होने से एक मॉडल का डेटाबेस टेबल नाम बनता है - आप ने जो नाम प्रबंधन में शुरू किया था - मॉडल के वर्ग के नाम के लिए, उनके बीच एक अंडरस्कोर के साथ।

उस स्थिति में जहां आपके पास एक बहु-शब्द, ऊंट-आवरण मॉडल नाम है, जैसे कि प्रोजेक्ट इटेम, तालिका का नाम होगा app_projectitem(यानी, एक अंडरस्कोर को बीच project- बीच में नहीं डाला जाएगा और itemभले ही वे ऊंट-आवरण हो)।


2
यह नाम \ full_name पर काम करेगा, लेकिन संबंध क्षेत्र पर नहीं, सही?
जोनाथन

23
महत्वपूर्ण नोट: यदि आप इसका उपयोग करने जा रहे हैं, तो सुनिश्चित करें कि "app_foo" डेटाबेस तालिका का नाम है, इसलिए उदाहरण के लिए: "mainapp_profile", "नाम" डेटाबेस का पुराना स्तंभ नाम है (मॉडल फ़ील्ड नाम नहीं) उदाहरण के लिए: "user_id" और "full_name" वह नया नाम होगा जिसे आप स्तंभ चाहते हैं (फिर से, डेटाबेस कॉलम और फ़ील्ड नाम नहीं)। तो: db.rename_column ('mainapp_profile', 'user_id', 'new_user_id') इसके अलावा, यदि आप विदेशी कुंजी के साथ काम कर रहे हैं, तो आपको नाम बदलने के दौरान उनमें "_id" भाग होना चाहिए।
गीजिम

3
यदि आप मैन्युअल रूप से इस db.rename_column को करते हैं, तो आपको बाद में चीजों को साफ करने के लिए नकली स्कीमा माइग्रेशन करना पड़ सकता है। वह पहले कॉलम का नाम बदलने के साथ परिवर्तन को स्थानांतरित करता है। फिर मॉडल (अपडेट किए गए नाम के लिए) को ठीक करें, और फिर करें ।/manage.py schemam माइग्रेशन ऐप --auto &&//manage.py माइग्रेट ऐप --fake)।
जिम्बॉब

24
आप खाली माइग्रेशन बनाने के लिए /manage.py schemam माइग्रेशन my_app renaming_column_x --empty का उपयोग कर सकते हैं और इसमें कोड डालने के लिए
Ilian Iliev

11
- खाली ज्यादा मदद नहीं करता है, इसके बजाय --ऑटो और संशोधित माइग्रेशन को संशोधित करें। इस तरह यह दावा नहीं करेगा कि मॉडल के अगले माइग्रेशन के लिए फ़ील्ड हटा दी गई है।
yasc

39

यहाँ मैं क्या कर रहा हूँ:

  1. अपने मॉडल में कॉलम का नाम बदलें (इस उदाहरण में यह होगा myapp/models.py)
  2. Daud ./manage.py schemamigration myapp renaming_column_x --auto

नोट renaming_column_xआपको कुछ भी पसंद आ सकता है, यह माइग्रेशन फ़ाइल को एक विवरणात्मक नाम देने का एक तरीका है।

यह आपको एक फाइल उत्पन्न करेगा, myapp/migrations/000x_renaming_column_x.pyजो आपके पुराने कॉलम को हटा देगी और एक नया कॉलम जोड़ेगी।

माइग्रेशन व्यवहार को सरल नाम बदलने के लिए इस फ़ाइल में कोड को संशोधित करें:

class Migration(SchemaMigration):

    def forwards(self, orm):
        # Renaming column 'mymodel.old_column_name' to 'mymodel.new_column_name'
        db.rename_column(u'myapp_mymodel', 'old_column_name', 'new_column_name')

    def backwards(self, orm):
        # Renaming column 'mymodel.new_column_name' to 'mymodel.old_column_name'
        db.rename_column(u'myapp_mymodel', 'new_column_name', 'old_column_name')

आपके आदेश में कॉलम का नाम क्या है? xया column_x?
andilabs

आप जिस कमांड का उल्लेख कर रहे हैं, उसका उपयोग सिर्फ माइग्रेशन को नाम देने के लिए किया जाता है, यह वह हो सकता है जो आपको पसंद हो। जब आप इसे संपादित करते हैं तो कॉलम नाम को माइग्रेशन फ़ाइल में निर्दिष्ट करना होगा।
मतवाला

2
--autoपहले माइग्रेशन बनाना एक शानदार टिप है। यह साउथ ओआरएम फ्रीजर के साथ समस्याओं से बचा जाता है, जो तब होता है जब माइग्रेशन केवल forwardsऔर backwardsतरीके होते हैं, लेकिन इसमें जमी हुई modelवस्तु नहीं होती है ।
mwcz

मैं दक्षिण के प्रश्न का उत्तर कैसे देता हूं 'चूंकि आप इस क्षेत्र को हटा रहे हैं, आप एक डिफ़ॉल्ट निर्दिष्ट करना चाहिए'
ब्रज

3
इस विधि के साथ एक समस्या यह है कि कॉलम से जुड़ी बाधाओं काdb.rename_column नाम नहीं है । माइग्रेशन अभी भी काम करेगा लेकिन आपके पास पुराने कॉलम के नाम पर अड़चनें होंगी। मेरे पास एक विशिष्टता बाधा वाला एक स्तंभ था, इस पद्धति का उपयोग करके इसका नाम बदल दिया गया, परीक्षण किया गया कि विशिष्टता की बाधा अभी भी मौजूद है और उसे एक त्रुटि मिली है लेकिन बाधा का नाम अभी भी पुराने स्तंभ नाम का उपयोग कर रहा था। शायद एक स्पष्ट और यह किया होगा, लेकिन मैंने sjh के समाधान के साथ जाने का फैसला किया। db.delete_uniquedb.create_unique
लुई

15

मुझे db.rename कॉलम के बारे में नहीं पता था, आसान लगता है, हालाँकि पिछले दिनों मैंने नए कॉलम को एक स्कीम माइग्रेशन के रूप में जोड़ा है, फिर नए फ़ील्ड में मानों को स्थानांतरित करने के लिए एक डेटा माइग्रेशन बनाया, फिर पुराने कॉलम को हटाने के लिए दूसरा स्कीमा माइग्रेशन


मैं भी। स्कीमा-डेटा-स्कीमा तकनीक के साथ समस्या यह है कि आप अपने क्षेत्रों / मॉडलों के लिए अलग-अलग नामों से समाप्त होते हैं। कभी-कभी यह एक समस्या है यदि आप डिस्पैचर्स को सक्षम करने के लिए विहित नामों का उपयोग करते हैं ...
जोनाथन

मैंने सिर्फ यह कोशिश की और यह काम नहीं किया क्योंकि एक नाम संघर्ष था। मैं एक ही FK, लेकिन अलग नाम था। यह मान्य नहीं था। तो, यह मत करो।
गज़िम

2
@ जोनाथन, वह अलग-अलग नाम चाहते हैं! ... @ पिलीग्रिम, कुछ कोड पोस्ट करने के लिए देखभाल? मैंने इस सप्ताह कई बार ऐसा किया है, यदि आपके मॉडल मान्य नहीं हैं तो दक्षिण अभ्यारण्य माइग्रेशन नहीं बनाते हैं।
sjh

यह काम करेगा, लेकिन अन्य लोगों द्वारा सुझाए गए 'rename_column' की तुलना में शायद धीमा होगा। मुझे पता है कि MySQL एक "ALTER TABLE ... नाम बदलें कॉलम" (या जो कुछ भी है) काफी तेज़ी से कर सकता है।
रॉरी

1
@ रोरी db.rename_columnआपके लिए बाधाओं का नाम नहीं बदलेगा, इसलिए आपको इसे मैन्युअल रूप से संभालना होगा। यदि आप इसे करना भूल जाते हैं, तो माइग्रेशन काम करेगा, सिवाय इसके कि आपके पास जाने के बाद भी पुराने कॉलम नाम का उपयोग करने में अड़चन हो सकती है। यह मेरे लिए स्पष्ट नहीं है कि क्या यह मुद्दा महज कॉस्मेटिक है या भविष्य के प्रवास में जहां बाधा को जोड़ दिया जाना चाहिए या दक्षिण छोड़ दिया जाना चाहिए, यह पता नहीं चल पाएगा। किसी भी दर पर, यहाँ ऐसा करना जैसे कि एसजेएच सुझाव देता है कि ऐसा करने का सुरक्षित तरीका है: आप दक्षिण का पता लगा सकते हैं कि इसका क्या पता लगाना चाहिए।
लुई

10

Django 1.7 ने माइग्रेशन शुरू किया इसलिए अब आपको अपने माइग्रेशन को प्रबंधित करने के लिए अतिरिक्त पैकेज स्थापित करने की आवश्यकता नहीं है।

अपने मॉडल का नाम बदलने के लिए आपको पहले खाली माइग्रेशन बनाने की आवश्यकता है:

$ manage.py makemigrations <app_name> --empty

फिर आपको अपना माइग्रेशन कोड इस तरह संपादित करना होगा:

from django.db import models, migrations

class Migration(migrations.Migration):

dependencies = [
    ('yourapp', 'XXXX_your_previous_migration'),
]

operations = [
    migrations.RenameField(
        model_name='Foo',
        old_name='name',
        new_name='full_name'
    ),
    migrations.RenameField(
        model_name='Foo',
        old_name='rel',
        new_name='odd_relation'
    ),
]

और इसके बाद आपको चलाने की आवश्यकता है:

$ manage.py migrate <app_name>

5

बस मॉडल बदलें और makemigrations1.9 में चलाएं

Django स्वचालित रूप से पता लगाता है कि आपने हटा दिया है और एक एकल फ़ील्ड बनाया है, और पूछता है:

Did you rename model.old to model.new (a IntegerField)? [y/N]

हां कहो, और सही माइग्रेशन बन जाता है। जादू।


0
  1. southप्रोजेक्ट सेटिंग फ़ाइल में अपने इंस्टॉल किए गए ऐप्स में जोड़ें ।
  2. जोड़ा / संशोधित क्षेत्र / तालिका बाहर टिप्पणी करें।
  3. $ manage.py Schemamigration <app_name> --initial
  4. $ manage.py migrate <app_name> --Fake
  5. फ़ील्ड को अन-कमेंट करें और संशोधित एक लिखें
  6. $ manage.py Schemamigration --auto
  7. $ manage.py migrate <app_name>

यदि आप 'pycharm' का उपयोग कर रहे हैं, तो आप 'manage.py' के बजाय 'ctrl + shift + r' का उपयोग कर सकते हैं, और मापदंडों के लिए 'shift' का उपयोग कर सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.