Django / दक्षिण का उपयोग कर एक मॉडल का नाम बदलने का सबसे आसान तरीका?


141

मैं दक्षिण की साइट, Google और SO पर इसके उत्तर के लिए शिकार कर रहा हूं, लेकिन ऐसा करने का एक सरल तरीका नहीं खोज सका।

मैं दक्षिण का उपयोग करके एक Django मॉडल का नाम बदलना चाहता हूं। कहो कि आपके पास निम्नलिखित हैं:

class Foo(models.Model):
    name = models.CharField()

class FooTwo(models.Model):
    name = models.CharField()
    foo = models.ForeignKey(Foo)

और आप फू को बार में बदलना चाहते हैं

class Bar(models.Model):
    name = models.CharField()

class FooTwo(models.Model):
    name = models.CharField()
    foo = models.ForeignKey(Bar)

यह सरल रखने के लिए, मैं सिर्फ से नाम बदलने के लिए कोशिश कर रहा हूँ Fooकरने के लिए Bar, लेकिन उपेक्षा fooमें सदस्य FooTwoअब के लिए।

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

  1. मैं शायद एक डेटा माइग्रेशन कर सकता था, लेकिन यह बहुत शामिल लगता है।
  2. एक कस्टम माइग्रेशन लिखें, उदाहरण के लिए db.rename_table('city_citystate', 'geo_citystate'), लेकिन मुझे यकीन नहीं है कि इस मामले में विदेशी कुंजी को कैसे ठीक किया जाए।
  3. एक आसान तरीका जो आप जानते हैं?

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

Django के लिए अनुकूलित समाधान> = 1.8 stackoverflow.com/questions/25091130/…
रासायनिक प्रोग्रामर

जवाबों:


130

आपके पहले प्रश्न का उत्तर देने के लिए, सरल मॉडल / तालिका का नाम बहुत सीधा है। कमांड चलाएँ:

./manage.py schemamigration yourapp rename_foo_to_bar --empty

(अपडेट 2: नीचे दी गई चेतावनी से बचने --autoके --emptyलिए प्रयास करें। टिप के लिए @KFB को धन्यवाद।)

यदि आप दक्षिण के पुराने संस्करण का उपयोग कर रहे हैं, तो आपको startmigrationइसके बजाय आवश्यकता होगी schemamigration

फिर मैन्युअल रूप से इस तरह दिखने के लिए माइग्रेशन फ़ाइल को संपादित करें:

class Migration(SchemaMigration):

    def forwards(self, orm):
        db.rename_table('yourapp_foo', 'yourapp_bar')


    def backwards(self, orm):
        db.rename_table('yourapp_bar','yourapp_foo')   

आप db_tableअपने मॉडल वर्ग में मेटा विकल्प का उपयोग करके इसे और अधिक पूरा कर सकते हैं । लेकिन हर बार जब आप ऐसा करते हैं, तो आप अपने कोडबेस का विरासत वजन बढ़ाते हैं - वर्ग के नाम तालिका के नामों से भिन्न होते हैं, जिससे आपका कोड समझने और बनाए रखने में कठिन हो जाता है। मैं स्पष्टता के लिए इस तरह से सरल रिफ्लेक्टरिंग करने का पूरा समर्थन करता हूं।

(अपडेट) मैंने उत्पादन में सिर्फ यही कोशिश की, और जब मैं माइग्रेशन लागू करने गया तो मुझे एक अजीब चेतावनी मिली। यह कहा:

The following content types are stale and need to be deleted:

    yourapp | foo

Any objects related to these content types by a foreign key will also
be deleted. Are you sure you want to delete these content types?
If you're unsure, answer 'no'.

मैंने जवाब दिया "नहीं" और सब कुछ ठीक लग रहा था।


3
मैं त्रुटि संदेश से बचने में सक्षम था, जोकि --emuto के बजाय - खाली का उपयोग करके स्कीमा माइग्रेशन बनाकर कर रहा था। मैंने तब माइग्रेशन फ़ाइल को संपादित किया, टेबल के विलोपन / निर्माण को db.rename_table () कॉल में बदल दिया। ऐसा लगता है कि बहुत अच्छा काम किया है।
KFB

4
मैंने बिना किसी त्रुटि के 9/2/2011 को इस तकनीक का उपयोग किया। हो सकता है कि दक्षिण के एक नए संस्करण ने त्रुटियों के साथ समस्या को हल किया।
चिप तोल

1
इस अद्यतन रखने के लिए धन्यवाद! नीचे दिए गए जियान के जवाब में कहा गया है कि "send_create_signal" कॉल रखना महत्वपूर्ण है, क्या आपको इसके बारे में कोई जानकारी है? यदि आप सहमत हैं, तो अपने उदाहरण माइग्रेशन को अपडेट करना बहुत अच्छा होगा।
मैरोनी

5
खबरदार कि यह उस तालिका पर अनुक्रमित नाम नहीं बदलेगा। यदि आप भविष्य में पुरानी तालिका के समान नाम से एक नई तालिका बनाते हैं, तो आप अनुक्रमणिका नामों के टकराने से त्रुटियां प्राप्त कर सकते हैं। हम इस तकनीक का उपयोग कर रहे थे, लेकिन अब से हम स्पष्ट रूप से नई तालिका बनाने जा रहे हैं, डेटा को माइग्रेट करते हैं, फिर पुरानी तालिका को हटाते हैं।
जेरेमी बैंक्स

3
स्वचालित रूप से उत्पन्न तालिकाओं में स्तंभ के नाम, जैसे कि मूल मॉडल के लिए M2M तालिकाओं, को भी इस विधि से माइग्रेट नहीं किया जाता है।
spookylukey

66

में परिवर्तन करें models.pyऔर फिर चलाएं

./manage.py schemamigration --auto myapp

जब आप माइग्रेशन फ़ाइल का निरीक्षण करते हैं, तो आप देखेंगे कि यह एक तालिका को हटाता है और एक नया बनाता है

class Migration(SchemaMigration):

    def forwards(self, orm):
        # Deleting model 'Foo'                                                                                                                      
        db.delete_table('myapp_foo')

        # Adding model 'Bar'                                                                                                                        
        db.create_table('myapp_bar', (
        ...
        ))
        db.send_create_signal('myapp', ['Bar'])

    def backwards(self, orm):
        ...

यह काफी नहीं है कि आप क्या चाहते हैं। इसके बजाय, माइग्रेशन संपादित करें ताकि ऐसा लगे:

class Migration(SchemaMigration):

    def forwards(self, orm):
        # Renaming model from 'Foo' to 'Bar'                                                                                                                      
        db.rename_table('myapp_foo', 'myapp_bar')                                                                                                                        
        if not db.dry_run:
            orm['contenttypes.contenttype'].objects.filter(
                app_label='myapp', model='foo').update(model='bar')

    def backwards(self, orm):
        # Renaming model from 'Bar' to 'Foo'                                                                                                                      
        db.rename_table('myapp_bar', 'myapp_foo')                                                                                                                        
        if not db.dry_run:
            orm['contenttypes.contenttype'].objects.filter(app_label='myapp', model='bar').update(model='foo')

updateबयान की अनुपस्थिति में , db.send_create_signalकॉल ContentTypeनए मॉडल के नाम के साथ एक नया निर्माण करेगा । लेकिन यह बेहतर है updateकि ContentTypeआप पहले से ही मामले में डेटाबेस ऑब्जेक्ट्स इसे इंगित कर रहे हैं (जैसे, a के माध्यम सेGenericForeignKey )।

इसके अलावा, यदि आपने कुछ कॉलम का नाम बदला है, जो नामांकित मॉडल के लिए विदेशी कुंजी हैं, तो मत भूलना

db.rename_column(myapp_model, foo_id, bar_id)

2
मुझे त्रुटि मिलती है, KeyError: "मॉडल 'contenttype' ऐप से सामग्री 'सामग्री' इस माइग्रेशन में उपलब्ध नहीं है।" इसके अलावा, मेरे पास एक django_content_type तालिका है, लेकिन कोई सामग्री तालिका नहीं है। (Django 1.6)
सेठ

2
@ सेठ मैंने इसके लिए अलग-अलग डेटा माइग्रेशन में ContentType मॉडल का अद्यतन contenttypes.ContentTypeकरके और --frozenध्वज का उपयोग करके जमे हुए मॉडल में मॉडल जोड़कर काम किया ./manage.py datamigration। उदाहरण के लिए ./manage.py datamigration --frozen contenttypes myapp update_contenttypes:। फिर ऊपर बताए अनुसार सामग्री प्रकार अद्यतन कोड के साथ myapp_migrations / NNNN_update_contenttypes.py संपादित करें।
ज्यॉफ्री हिंग

@GeoffreyHing मुझे लगता है कि पैरामीटर फ्रीज नहीं है। south.readthedocs.io/en/latest/ormfreezing.html लेकिन आपकी मदद के लिए बहुत बहुत धन्यवाद, यह वास्तव में मददगार था।
ccsakuweb

5

साउथ खुद नहीं कर सकता - यह कैसे पता चलता है Bar किस चीज का प्रतिनिधित्वFoo है? यह उस तरह की चीज़ है जिसके लिए मैं एक कस्टम माइग्रेशन लिखूंगा। आप अपने को बदल सकते हैंForeignKeyजैसा कि आपने ऊपर किया है, आप कोड को , और फिर यह उपयुक्त क्षेत्रों और तालिकाओं का नाम बदलने का एक मामला है, जिसे आप किसी भी तरह से चाहते हैं।

अंत में, क्या आपको वास्तव में ऐसा करने की आवश्यकता है? मुझे अभी तक मॉडल का नाम बदलने की आवश्यकता नहीं है - मॉडल नाम सिर्फ एक कार्यान्वयन विवरण हैं - विशेष रूप से verbose_nameमेटा विकल्प की उपलब्धता को देखते हुए ।


7
वैकल्पिक रूप से, कोड में मॉडल का नाम बदलें लेकिन db_tableडेटाबेस तालिका का नाम समान रखने के लिए मेटा विकल्प का उपयोग करें ।
डैनियल रोजमैन

@ डैनियल - क्या आप जानते हैं कि db_tableविदेशी कुंजी नामों को प्राप्त करने के लिए उपयोग किया जाता है?
डोमिनिक रॉगर

मुझे विश्वास है कि यह है यदि आप मॉडल का नाम बदलते हैं और db_table सेट करते हैं तो सब कुछ अभी भी उम्मीद के मुताबिक काम करना चाहिए।
डावोर Lucic

1
@DanielRoseman यह पूरे धागे में सबसे अच्छा समाधान है!
जॉयरिक

-1

मैंने ऊपर तेंदुए के समाधान का पालन किया। लेकिन, इससे मॉडल के नाम नहीं बदले। मैंने इसे कोड में मैन्युअल रूप से बदल दिया (संबंधित मॉडलों में भी जहां इसे एफके के रूप में संदर्भित किया जाता है)। और एक और दक्षिण प्रवास किया, लेकिन - विकल्प के साथ। यह मॉडल नाम और तालिका नाम समान बनाता है।

बस एहसास हुआ, कोई पहले मॉडल नामों को बदल सकता है, फिर उन्हें लागू करने से पहले माइग्रेशन फ़ाइल को संपादित कर सकता है। बहुत सफाई वाला।

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