python - Django / South का उपयोग कर मॉडल का नाम बदलने का सबसे आसान तरीका?




model rename django-south (5)

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

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

मैं दक्षिण की साइट, 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 में नाम बदलने की कोशिश कर रहा हूं, लेकिन अभी के लिए FooTwo में foo सदस्य को अनदेखा कर रहा हूं।

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

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

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 बना देगा। लेकिन यह केवल बेहतर है कि आपके पास पहले से मौजूद सामग्री प्रकार GenericForeignKey , यदि डेटाबेस ऑब्जेक्ट्स इंगित कर रहे हैं (उदाहरण के लिए, GenericForeignKey माध्यम से)।

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

db.rename_column(myapp_model, foo_id, bar_id)

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

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


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

./manage.py schemamigration yourapp rename_foo_to_bar --empty

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

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

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

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'.

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


  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' का उपयोग कर सकते हैं।





python django model rename django-south