2010-05-19 11 views
138

मैं दक्षिण की साइट, Google और SO पर इसका उत्तर देने का शिकार कर रहा हूं, लेकिन ऐसा करने का एक आसान तरीका नहीं मिला।Django/South का उपयोग कर मॉडल का नाम बदलने का सबसे आसान तरीका?

मैं दक्षिण का उपयोग कर एक Django मॉडल का नाम बदलना चाहता हूं। , मैं सिर्फ Foo से Bar के नाम बदलने के लिए कोशिश कर रहा हूँ,

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 सदस्य FooTwo में सदस्य को अनदेखा करें।

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

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

एक * मॉडल * के बजाए * मॉडल फ़ील्ड * नाम बदलने के लिए http://stackoverflow.com/questions/3235995/django-how-to-rename-a-model-field-using-outh देखें। –

+0

Django के लिए अनुकूलित समाधान> = 1.8 http://stackoverflow.com/questions/25091130/django- माइग्रेशन-स्ट्रेटी-for-renaming-a-model-and-relationship-fields –

उत्तर

128

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

./manage.py schemamigration yourapp rename_foo_to_bar --empty 

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

आप दक्षिण के एक पुराने संस्करण का उपयोग कर रहे हैं, तो आपको schemamigration के बजाय 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'. 

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

+0

जब मैं ऐसा करता हूं, तो मैं foo में सभी पंक्तियां खो देता हूं। मैं क्या गलत कर रहा हूं? – jMyles

+0

@ जस्टिन - बहुत अधिक विस्तार के बिना कहना मुश्किल है। यहां एक टिप्पणी में एक नया SO प्रश्न लिखें और उससे लिंक करें? – Leopd

+0

ऐसा लगता है कि पुराने माइग्रेशन तोड़ते हैं जो 'फू' पर निर्भर थे। – luqui

5

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

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

+7

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

+0

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

+0

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

65

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

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

db.rename_column(myapp_model, foo_id, bar_id) 
+8

+1 सामग्री सामग्री तालिका में मॉडल का नाम बदलने के लिए – ACGray

+2

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

+2

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

-1

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

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

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