2016-03-14 10 views
5

से Django मॉडल फ़ील्ड का प्रकार बदलें मुझे CharField से ForeignKey से मेरे Django मॉडल में से किसी एक फ़ील्ड के प्रकार को बदलने की आवश्यकता है। फ़ील्ड पहले ही डेटा के साथ आबादी में हैं, इसलिए मैं सोच रहा था कि ऐसा करने का सबसे अच्छा या सही तरीका क्या है। क्या मैं सिर्फ फ़ील्ड प्रकार को अपडेट कर सकता हूं और माइग्रेट कर सकता हूं, या क्या कोई संभावित 'गॉथचास' जागरूक हो सकता है? एनबी: मैं सिर्फ वेनिला डीजेगो प्रबंधन संचालन (makemigrations और migrate) का उपयोग करता हूं, दक्षिण में नहीं।चारफ़ील्ड से विदेशीकी

+2

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

+1

मुझे लगता है कि यह वही है जो आप खोज रहे हैं। http://stackoverflow.com/questions/5373906/changing-the-django-data-type-in-models-without-droping-the-table – Vibhu

उत्तर

25

यह संभवतः एक ऐसा मामला है जहां आप बहु-चरण प्रवासन करना चाहते हैं। इसके लिए मेरी सिफारिश निम्नलिखित की तरह कुछ दिखाई देगी।

पहले, मान लेते हैं यह अपने प्रारंभिक मॉडल है, अंदर एक आवेदन discography कहा जाता है:

from django.db import models 

class Album(models.Model): 
    name = models.CharField(max_length=255) 
    artist = models.CharField(max_length=255) 

अब, आप महसूस करते हैं कि आप के बजाय कलाकार के लिए एक ForeignKey उपयोग करना चाहते हैं। वैसे, जैसा कि बताया गया है, यह सिर्फ इसके लिए एक सरल प्रक्रिया नहीं है। इसे कई चरणों में किया जाना है।

चरण 1, ForeignKey के लिए एक नए क्षेत्र जोड़ने के लिए, अशक्त के रूप में चिह्नित करने के लिए सुनिश्चित कर रही है:

from django.db import models 

class Album(models.Model): 
    name = models.CharField(max_length=255) 
    artist = models.CharField(max_length=255) 
    artist_link = models.ForeignKey('Artist', null=True) 

class Artist(models.Model): 
    name = models.CharField(max_length=255) 

... और इस बदलाव के लिए एक प्रवास पैदा करते हैं।

./manage.py makemigrations discography 

चरण 2, अपने नए क्षेत्र को पॉप्युलेट करें। ऐसा करने के लिए, आपको एक खाली माइग्रेशन बनाना होगा।

./manage.py makemigrations --empty --name transfer_artists discography 

एक बार जब आप इस खाली प्रवास है, तो आप के लिए अपने रिकॉर्ड को लिंक करने के लिए यह करने के लिए एक एकल RunPython आपरेशन जोड़ना चाहते हैं। इस मामले में, यह कुछ इस तरह दिख सकता है:

def link_artists(apps, schema_editor): 
    Album = apps.get_model('discography', 'Album') 
    Artist = apps.get_model('discography', 'Artist') 
    for album in Album.objects.all(): 
     artist, created = Artist.objects.get_or_create(name=album.artist) 
     album.artist_link = artist 
     album.save() 

अब जब कि अपने डेटा नए क्षेत्र के लिए स्थानांतरित कर रहा है, आप वास्तव में किया जाता है और सब कुछ के लिए नए क्षेत्र का उपयोग कर सब कुछ छोड़ देते हैं, के रूप में किया जा सकता है। या, यदि आप थोड़ा सा सफाई करना चाहते हैं, तो आप दो और माइग्रेशन बनाना चाहते हैं।

अपने पहले माइग्रेशन के लिए, आप अपना मूल फ़ील्ड, artist हटाना चाहेंगे। अपने दूसरे माइग्रेशन के लिए, नया क्षेत्र artist_link से artist का नाम बदलें।

यह सुनिश्चित करने के लिए कई चरणों में किया जाता है कि Django संचालन को सही ढंग से पहचानता है। आप इसे संभालने के लिए मैन्युअल रूप से माइग्रेशन बना सकते हैं, लेकिन मैं इसे समझने के लिए आपको छोड़ दूंगा।

+0

आपके त्वरित और व्यापक प्रतिक्रिया के लिए धन्यवाद। इसने मुझे अंततः बैठने और Django माइग्रेशन के बारे में अच्छी तरह से सीखने के लिए प्रोत्साहित किया है! – ChrisM

+0

यह '.manman.py makemigrations --empty ... नहीं होना चाहिए, हालांकि? चरण 2 में 'makemigration' (एकवचन) है। – ChrisM

+0

आह, हाँ, टाइपो को पकड़ने के लिए धन्यवाद! –

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