Django 1.7 और डेटा माइग्रेशन के साथ प्रारंभिक डेटा लोड हो रहा है


95

मैंने हाल ही में Django 1.6 से 1.7 पर स्विच किया, और मैंने माइग्रेशन का उपयोग करना शुरू कर दिया (मैंने कभी दक्षिण का उपयोग नहीं किया)।

1.7 से पहले, मैं एक fixture/initial_data.jsonफ़ाइल के साथ प्रारंभिक डेटा लोड करता था, जिसे python manage.py syncdbकमांड (डेटाबेस बनाते समय) के साथ लोड किया गया था ।

अब, मैंने माइग्रेशन का उपयोग करना शुरू कर दिया है, और यह व्यवहार पदावनत है:

यदि कोई एप्लिकेशन माइग्रेशन का उपयोग करता है, तो जुड़नार का कोई स्वचालित लोड नहीं होता है। चूंकि Django 2.0 में अनुप्रयोगों के लिए माइग्रेशन की आवश्यकता होगी, इसलिए यह व्यवहार पदावनत माना जाता है। यदि आप किसी एप्लिकेशन के लिए प्रारंभिक डेटा लोड करना चाहते हैं, तो उसे डेटा माइग्रेशन में करने पर विचार करें। ( https://docs.djangoproject.com/en/1.7/howto/initial-data/#automatically-loading-initial-data-fixtures )

आधिकारिक दस्तावेज तो मेरे सवाल यह है कि यह कैसे करना है पर एक स्पष्ट उदाहरण नहीं है,:

डेटा माइग्रेशन का उपयोग करके ऐसे प्रारंभिक डेटा को आयात करने का सबसे अच्छा तरीका क्या है:

  1. करने के लिए कई कॉल के साथ अजगर कोड लिखें mymodel.create(...),
  2. JSON स्थिरता फ़ाइल से डेटा लोड करने के लिए Django फ़ंक्शन का उपयोग करें ( जैसे कॉलिंगloaddata ) लिखें ।

मैं दूसरा विकल्प पसंद करता हूं।

मैं दक्षिण का उपयोग नहीं करना चाहता, क्योंकि Django अब इसे मूल रूप से करने में सक्षम हो गया है।


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

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

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

@Serafeim "सवाल जहां एक तीसरे पक्ष के अनुप्रयोग के लिए प्रारंभिक डेटा डाल करने के लिए" आप जुड़नार के बजाय एक डेटा माइग्रेशन का उपयोग करते हैं तो नहीं बदलता है, क्योंकि आप केवल डेटा लोड होने के तरीके को बदलते हैं। मैं इस तरह की चीजों के लिए एक छोटे से कस्टम ऐप का उपयोग करता हूं। यदि तीसरे पक्ष के ऐप को "फू" कहा जाता है, तो मैं अपने साधारण ऐप को डेटा माइग्रेशन / स्थिरता "foo_integration" कहता हूं।
गुएतली

@guettli हाँ, शायद एक अतिरिक्त एप्लिकेशन का उपयोग करना सबसे अच्छा तरीका है!
सेरेफिम

जवाबों:


81

अद्यतन : देखें @ GwynBleidD की टिप्पणी इस समस्या के कारण हो सकती है, और नीचे दिए गए दृष्टिकोण के लिए @ Rockallite का जवाब देखें जो भविष्य के मॉडल परिवर्तनों के लिए अधिक टिकाऊ है।


मान लें कि आपके पास एक फ़िक्चर फ़ाइल है <yourapp>/fixtures/initial_data.json

  1. अपना खाली माइग्रेशन बनाएँ:

    Django में 1.7:

    python manage.py makemigrations --empty <yourapp>

    Django 1.8+ में, आप एक नाम प्रदान कर सकते हैं:

    python manage.py makemigrations --empty <yourapp> --name load_intial_data
  2. अपनी माइग्रेशन फ़ाइल संपादित करें <yourapp>/migrations/0002_auto_xxx.py

    2.1। कस्टम कार्यान्वयन, Django ' loaddata(प्रारंभिक उत्तर) से प्रेरित है :

    import os
    from sys import path
    from django.core import serializers
    
    fixture_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '../fixtures'))
    fixture_filename = 'initial_data.json'
    
    def load_fixture(apps, schema_editor):
        fixture_file = os.path.join(fixture_dir, fixture_filename)
    
        fixture = open(fixture_file, 'rb')
        objects = serializers.deserialize('json', fixture, ignorenonexistent=True)
        for obj in objects:
            obj.save()
        fixture.close()
    
    def unload_fixture(apps, schema_editor):
        "Brutally deleting all entries for this model..."
    
        MyModel = apps.get_model("yourapp", "ModelName")
        MyModel.objects.all().delete()
    
    class Migration(migrations.Migration):  
    
        dependencies = [
            ('yourapp', '0001_initial'),
        ]
    
        operations = [
            migrations.RunPython(load_fixture, reverse_code=unload_fixture),
        ]

    2.2। load_fixture(प्रति @ जूलियोसेर के सुझाव) के लिए एक सरल उपाय :

    from django.core.management import call_command
    
    fixture_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '../fixtures'))
    fixture_filename = 'initial_data.json'
    
    def load_fixture(apps, schema_editor):
        fixture_file = os.path.join(fixture_dir, fixture_filename)
        call_command('loaddata', fixture_file) 

    यदि आप एक कस्टम निर्देशिका का उपयोग करना चाहते हैं तो उपयोगी है।

    2.3। सरल: बुला loaddataके साथ app_labelसे इच्छा लोड जुड़नार <yourapp>की fixturesनिर्देशिका स्वचालित रूप से:

    from django.core.management import call_command
    
    fixture = 'initial_data'
    
    def load_fixture(apps, schema_editor):
        call_command('loaddata', fixture, app_label='yourapp') 

    यदि आप निर्दिष्ट नहीं करते हैं app_label, तो लोडडेटा सभी ऐप्स फिक्स्चर निर्देशिकाओं (जो आप शायद नहीं चाहते हैं) fixtureसे फ़ाइल नाम लोड करने का प्रयास करेंगे ।

  3. चलाओ

    python manage.py migrate <yourapp>

1
ठीक है, आप सही कह रहे हैं ... साथ ही कॉलिंग loaddata('loaddata', fixture_filename, app_label='<yourapp>')भी सीधे ऐप
फ़िक्चर

15
उस पद्धति का उपयोग करते हुए, धारावाहिक वर्तमान models.pyफ़ाइलों से मॉडल स्थिति पर काम करेगा , जिसमें कुछ अतिरिक्त क्षेत्र या कुछ अन्य परिवर्तन हो सकते हैं। यदि माइग्रेशन बनाने के बाद कुछ बदलाव किए गए थे, तो यह विफल हो जाएगा (इसलिए हम उस माइग्रेशन के बाद स्कीमा माइग्रेशन भी नहीं बना सकते)। यह तय करने के लिए कि हम ऐप रजिस्ट्री को बदल सकते हैं रजिस्ट्री जो कि सीरियलएजर रजिस्ट्री पर काम कर रहा है, पहले पैरामीटर पर माइग्रेशन फ़क्शन को प्रदान करता है। पथ पर रजिस्ट्री स्थित है django.core.serializers.python.apps
GwynBleidD

3
हम यह क्यों कर रहे हैं? ऐसा क्यों है कि Django चलाने और बनाए रखने के लिए अधिक से अधिक कठिन हो जाता है? मैं हालांकि यह नहीं जाना चाहता, मैं एक साधारण कमांड लाइन इंटरफ़ेस चाहता हूं जो मेरे लिए इस समस्या को हल करता है अर्थात जैसे यह जुड़नार के साथ हुआ करता था। Django इस सामान को आसान बनाने वाला है, कठिन नहीं है :(
CpILL

1
@GwynBleidD यह एक बहुत ही महत्वपूर्ण बिंदु है जिसे आप बना रहे हैं, और मुझे लगता है कि इसे इस स्वीकृत उत्तर में प्रकट होना चाहिए। यह वही टिप्पणी है जो दस्तावेज़ के डेटा माइग्रेशन कोड उदाहरण में टिप्पणी के रूप में प्रकट होती है । क्या आप प्रदान app registryकिए गए धारावाहिकों का उपयोग करने का एक और तरीका जानते हैं , एक वैश्विक चर को बदले बिना (जो समानांतर डेटाबेस पलायन के साथ एक काल्पनिक भविष्य में समस्याएं पैदा कर सकता है)।
विज्ञापन एन

3
यह उत्तर स्वीकृति के साथ-साथ काज़ू तक उकेरा जा रहा है, यही कारण है कि मैं लोगों को स्टैकओवरफ्लो का उपयोग नहीं करने की सलाह देता हूं। अब भी टिप्पणियों और उपाख्यानों के साथ मैं अभी भी #django में लोगों को इस का जिक्र कर रहा हूं।
शांक्सीओओ

50

लघु संस्करण

आपको डेटा माइग्रेशन में सीधे प्रबंधन कमांड का उपयोग नहीं करना चाहिए loaddata

# Bad example for a data migration
from django.db import migrations
from django.core.management import call_command


def load_fixture(apps, schema_editor):
    # No, it's wrong. DON'T DO THIS!
    call_command('loaddata', 'your_data.json', app_label='yourapp')


class Migration(migrations.Migration):
    dependencies = [
        # Dependencies to other migrations
    ]

    operations = [
        migrations.RunPython(load_fixture),
    ]

दीर्घ संस्करण

loaddataउपयोग करता है, django.core.serializers.python.Deserializerजो एक माइग्रेशन में ऐतिहासिक डेटा को डीरिशियल करने के लिए सबसे अद्यतित मॉडल का उपयोग करता है। वह गलत व्यवहार है।

उदाहरण के लिए, माना जाता है कि एक डेटा माइग्रेशन है जो loaddataएक फ़िक्चर से डेटा लोड करने के लिए प्रबंधन कमांड का उपयोग करता है , और यह आपके विकास के वातावरण पर पहले से ही लागू है।

बाद में, आप संबंधित मॉडल में एक नया आवश्यक फ़ील्ड जोड़ने का निर्णय लेते हैं , इसलिए आप इसे करते हैं और अपने अपडेट किए गए मॉडल के विरुद्ध एक नया माइग्रेशन करते हैं (और संभवत: नए फ़ील्ड में एक-बार का मूल्य प्रदान करते हैं जब ./manage.py makemigrationsआप संकेत देते हैं)।

आप अगला माइग्रेशन चलाते हैं, और सब ठीक है।

अंत में, आप अपना Django एप्लिकेशन विकसित कर रहे हैं, और आप इसे उत्पादन सर्वर पर तैनात करते हैं। अब आपके लिए उत्पादन वातावरण पर खरोंच से पूरे पलायन को चलाने का समय है।

हालाँकि, डेटा माइग्रेशन विफल रहता है । ऐसा इसलिए है क्योंकि loaddataकमांड से डिसेररलाइज्ड मॉडल , जो वर्तमान कोड का प्रतिनिधित्व करता है, आपके द्वारा जोड़े गए नए आवश्यक फ़ील्ड के लिए खाली डेटा के साथ सहेजा नहीं जा सकता है । मूल स्थिरता में इसके लिए आवश्यक डेटा का अभाव है!

लेकिन भले ही आप नए क्षेत्र के लिए आवश्यक डेटा के साथ स्थिरता को अपडेट करते हैं, लेकिन डेटा माइग्रेशन अभी भी विफल रहता है । जब डेटा माइग्रेशन चल रहा होता है, तो अगला माइग्रेशन जो डेटाबेस में संबंधित कॉलम जोड़ता है, अभी तक लागू नहीं होता है। आप उस कॉलम के डेटा को सहेज नहीं सकते जो मौजूद नहीं है!

निष्कर्ष: डेटा माइग्रेशन में,loaddataकमांड मॉडल और डेटाबेस के बीच संभावित असंगति का परिचय देता है। आपकोडेटा माइग्रेशन में सीधे इसका उपयोग नहीं करना चाहिए।

समाधान

loaddataआदेश django.core.serializers.python._get_modelएक स्थिरता से संबंधित मॉडल को प्राप्त करने के लिए फ़ंक्शन पर निर्भर करता है , जो एक मॉडल के सबसे अद्यतित संस्करण को वापस कर देगा। हमें इसे बंदर-पैच करने की आवश्यकता है ताकि इसे ऐतिहासिक मॉडल मिल सके।

(निम्नलिखित कोड Django 1.8.x के लिए काम करता है)

# Good example for a data migration
from django.db import migrations
from django.core.serializers import base, python
from django.core.management import call_command


def load_fixture(apps, schema_editor):
    # Save the old _get_model() function
    old_get_model = python._get_model

    # Define new _get_model() function here, which utilizes the apps argument to
    # get the historical version of a model. This piece of code is directly stolen
    # from django.core.serializers.python._get_model, unchanged. However, here it
    # has a different context, specifically, the apps variable.
    def _get_model(model_identifier):
        try:
            return apps.get_model(model_identifier)
        except (LookupError, TypeError):
            raise base.DeserializationError("Invalid model identifier: '%s'" % model_identifier)

    # Replace the _get_model() function on the module, so loaddata can utilize it.
    python._get_model = _get_model

    try:
        # Call loaddata command
        call_command('loaddata', 'your_data.json', app_label='yourapp')
    finally:
        # Restore old _get_model() function
        python._get_model = old_get_model


class Migration(migrations.Migration):
    dependencies = [
        # Dependencies to other migrations
    ]

    operations = [
        migrations.RunPython(load_fixture),
    ]

1
रॉकलाईट, आप एक बहुत मजबूत बिंदु बनाते हैं। आपके उत्तर ने मुझे आश्चर्यचकित कर दिया, हालांकि, @ n__o / @ mlissner के जवाब से 2.1 का समाधान होगा जो objects = serializers.deserialize('json', fixture, ignorenonexistent=True)उसी मुद्दे से पीड़ित है loaddata? या ignorenonexistent=Trueसभी संभावित मुद्दों को कवर करता है ?
दारियो

7
यदि आप स्रोत को देखते हैं , तो आप पाएंगे कि ignorenonexistent=Trueतर्क के दो प्रभाव हैं: 1) यह एक स्थिरता के मॉडल को अनदेखा करता है जो सबसे वर्तमान मॉडल परिभाषाओं में नहीं हैं, 2) यह एक स्थिरता के मॉडल के क्षेत्रों की उपेक्षा करता है जो कि नहीं हैं सबसे मौजूदा इसी मॉडल परिभाषा में। उनमें से कोई भी नई-आवश्यक-फ़ील्ड-इन-द-मॉडल स्थिति को संभालता है। तो, हाँ, मुझे लगता है कि यह सादे के रूप में एक ही मुद्दा ग्रस्त है loaddata
रॉकलाईट

जब मैंने अपने पुराने जोंस मॉडल का उपयोग करके अन्य मॉडलों को संदर्भित किया natural_key(), जो कि इस विधि का समर्थन नहीं करता है, तो मैंने यह पता लगा लिया - मैंने अभी-अभी संदर्भित मॉडल की वास्तविक आईडी के साथ natural_key मान को प्रतिस्थापित किया है।
dsummersl

1
संभवतः यह उत्तर स्वीकृत उत्तर के रूप में अधिक सहायक होगा, क्योंकि रनिंग टेस्टेसिस में एक नया डेटाबेस बनाया जाता है और सभी माइग्रेशन खरोंच से लागू होते हैं। यह समाधान उन समस्याओं को ठीक करता है, जो डेटा माइग्रेशन में _get_model को प्रतिस्थापित न करने की स्थिति में एक परियोजना के साथ सामना करेगी। Tnx
मोहम्मद अली बैगशेरमिरानी

अपडेट और स्पष्टीकरण के लिए धन्यवाद, @Rockallite। Django 1.7 में माइग्रेशन शुरू होने के कुछ हफ्तों बाद मेरा प्रारंभिक उत्तर पोस्ट किया गया था, और आगे बढ़ने के बारे में प्रलेखन अस्पष्ट था (और अभी भी, पिछली बार जब मैंने जाँच की थी)। उम्मीद है कि Django किसी दिन अपने मॉडल इतिहास को ध्यान में रखने के लिए अपने लोडडेटा / माइग्रेशन तंत्र को अपडेट करेगा।
n__o

6

कुछ टिप्पणियों (अर्थात् n__o के) और इस तथ्य से प्रेरित कि मेरे पास बहुत सारी initial_data.*फाइलें हैं, जो मैंने कई ऐप्स पर फैलाई हैं, मैंने एक Django ऐप बनाने का फैसला किया है जो इन डेटा माइग्रेशन के निर्माण की सुविधा प्रदान करेगा।

Django- माइग्रेशन-फ़िक्चर का उपयोग करके आप केवल निम्न प्रबंधन कमांड चला सकते हैं और यह फ़ाइलों के INSTALLED_APPSलिए आपके सभी माध्यमों से खोज करेगा initial_data.*और उन्हें डेटा माइग्रेशन में बदल देगा।

./manage.py create_initial_data_fixtures
Migrations for 'eggs':
  0002_auto_20150107_0817.py:
Migrations for 'sausage':
  Ignoring 'initial_data.yaml' - migration already exists.
Migrations for 'foo':
  Ignoring 'initial_data.yaml' - not migrated.

स्थापित / उपयोग के निर्देशों के लिए django- माइग्रेशन-स्थिरता देखें ।


2

अपने डेटाबेस को कुछ प्रारंभिक डेटा देने के लिए, डेटा माइग्रेशन लिखें डेटा माइग्रेशन में, अपने डेटा को लोड करने के लिए RunPython फ़ंक्शन का उपयोग करें ।

इस तरह से पदावनत होने पर कोई भी लोडडाटा कमांड न लिखें।

आपका डेटा माइग्रेशन केवल एक बार चलाया जाएगा। माइग्रेशन माइग्रेशन का एक क्रमबद्ध क्रम है। जब 003_xxxx.py माइग्रेशन चलाया जाता है, तो django के माइग्रेशन डेटाबेस में लिखते हैं कि यह ऐप इस (003) तक माइग्रेट है, और केवल निम्नलिखित माइग्रेशन चलाएगा।


इसलिए आप मुझे myModel.create(...)रनपाइथन फ़ंक्शन में कॉल (या लूप का उपयोग करके) दोहराने के लिए प्रोत्साहित करें ?
मिकाल

बहुत बहुत हाँ। Transaactionnal डेटाबेस इसे पूरी तरह से संभाल लेंगे :)
FlogFR

1

ऊपर प्रस्तुत समाधान मेरे लिए दुर्भाग्य से काम नहीं किया। मैंने पाया कि हर बार जब मैं अपने मॉडल बदलता हूं तो मुझे अपने फिक्स्चर को अपडेट करना होगा। आदर्श रूप में मैं इसके बजाय बनाए गए डेटा और स्थिरता-लोड किए गए डेटा को संशोधित करने के लिए डेटा माइग्रेशन लिखूंगा।

इसे सुविधाजनक बनाने के लिए मैंने एक त्वरित कार्य लिखा, जो fixturesवर्तमान ऐप की निर्देशिका में दिखेगा और एक फ़र्क को लोड करेगा। इस फ़ंक्शन को माइग्रेशन इतिहास के उस बिंदु पर माइग्रेशन में डालें जो माइग्रेशन में फ़ील्ड से मेल खाता है।


इसके लिए धन्यवाद! मैंने एक संस्करण लिखा है जो पायथन 3 के साथ काम करता है (और हमारे सख्त पाइलिंट पास करता है)। आप इसे एक कारखाने के रूप में उपयोग कर सकते हैं RunPython(load_fixture('badger', 'stoat'))gist.github.com/danni/1b2a0078e998ac080111
डेनिएल

1

मेरी राय में जुड़नार थोड़े खराब हैं। यदि आपका डेटाबेस बार-बार बदलता है, तो उन्हें अद्यतित रखना जल्द ही एक बुरा सपना होगा। वास्तव में, यह केवल मेरी राय नहीं है, "टू स्कोप्स ऑफ जिंगो" पुस्तक में इसे बहुत बेहतर तरीके से समझाया गया है।

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

यदि आपको कुछ डेटा माइग्रेट करने की आवश्यकता है, तो आपको डेटा माइग्रेशन का उपयोग करना चाहिए ।

वहाँ भी है "आपका फिक्स्चर, उपयोग मॉडल कारखानों बर्न" जुड़नार का उपयोग कर के बारे में।


1
मैं आपकी बात पर सहमत हूं कि "अगर लगातार बदलाव हो तो बनाए रखने के लिए कड़ी मेहनत", लेकिन यहाँ स्थिरता केवल परियोजना को स्थापित करते समय प्रारंभिक (और न्यूनतम) डेटा प्रदान करने का लक्ष्य रखती है ...
मिकैल

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

0

Django 2.1 पर, मैं प्रारंभिक आंकड़ों के साथ कुछ मॉडल (उदाहरण के लिए देश के नाम) को लोड करना चाहता था।

लेकिन मैं चाहता था कि प्रारंभिक माइग्रेशन के निष्पादन के बाद यह स्वचालित रूप से सही हो।

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

फिर उस sql/फ़ोल्डर के भीतर मैं .sqlसंबंधित डेटा को संबंधित मॉडल में लोड करने के लिए आवश्यक डीएमएल के साथ फाइल करूंगा, उदाहरण के लिए:

INSERT INTO appName_modelName(fieldName)
VALUES
    ("country 1"),
    ("country 2"),
    ("country 3"),
    ("country 4");

अधिक वर्णनात्मक होने के लिए, यह एक ऐसा ऐप है जिसमें sql/फ़ोल्डर दिखाई देगा: यहां छवि विवरण दर्ज करें

इसके अलावा मुझे कुछ मामले मिले जहां मुझे sqlएक विशिष्ट क्रम में निष्पादित होने वाली स्क्रिप्ट की आवश्यकता थी । इसलिए मैंने एक निरंतर संख्या के साथ फ़ाइल नामों को उपसर्ग करने का फैसला किया जैसा कि ऊपर की छवि में देखा गया है।

फिर मुझे किसी SQLsभी एप्लिकेशन फ़ोल्डर के अंदर उपलब्ध किसी भी तरह से लोड करने के लिए एक तरीका चाहिए python manage.py migrate

इसलिए मैं नामक एक अन्य आवेदन बनाया initial_data_migrationsऔर फिर मैं की सूची में इस ऐप को जोड़ INSTALLED_APPSमें settings.pyफ़ाइल। फिर मैंने migrationsअंदर एक फ़ोल्डर बनाया और एक फ़ाइल जोड़ी, जिसे run_sql_scripts.py( वास्तव में एक कस्टम माइग्रेशन है ) कहा जाता है । जैसा कि नीचे की छवि में देखा गया है:

यहां छवि विवरण दर्ज करें

मैंने बनाया run_sql_scripts.pyताकि यह sqlप्रत्येक एप्लिकेशन के भीतर उपलब्ध सभी लिपियों को चलाने का ध्यान रखे। यह तब निकाल दिया जाता है जब कोई चलाता है python manage.py migrate। यह रिवाज migrationभी शामिल अनुप्रयोगों को निर्भरता के रूप में जोड़ता है, इस तरह से यह sqlआवश्यक है कि बयानों को चलाने के बाद ही आवश्यक अनुप्रयोग अपने 0001_initial.pyमाइग्रेशन को निष्पादित करें (हम एक गैर-मौजूद तालिका के खिलाफ SQL कथन चलाने का प्रयास नहीं करना चाहते हैं)।

यहाँ उस स्क्रिप्ट का स्रोत है:

import os
import itertools

from django.db import migrations
from YourDjangoProjectName.settings import BASE_DIR, INSTALLED_APPS

SQL_FOLDER = "/sql/"

APP_SQL_FOLDERS = [
    (os.path.join(BASE_DIR, app + SQL_FOLDER), app) for app in INSTALLED_APPS
    if os.path.isdir(os.path.join(BASE_DIR, app + SQL_FOLDER))
]

SQL_FILES = [
    sorted([path + file for file in os.listdir(path) if file.lower().endswith('.sql')])
    for path, app in APP_SQL_FOLDERS
]


def load_file(path):
    with open(path, 'r') as f:
        return f.read()


class Migration(migrations.Migration):

    dependencies = [
        (app, '__first__') for path, app in APP_SQL_FOLDERS
    ]

    operations = [
        migrations.RunSQL(load_file(f)) for f in list(itertools.chain.from_iterable(SQL_FILES))
    ]

मुझे आशा है कि किसी को यह उपयोगी लगता है, यह मेरे लिए ठीक काम किया !. यदि आपका कोई सवाल है, तो कृपया मुझे बताएं।

ध्यान दें: यह सबसे अच्छा समाधान नहीं हो सकता है क्योंकि मैं अभी django के साथ शुरू कर रहा हूं, हालांकि अभी भी आप सभी के साथ इस "हाउ-टू" को साझा करना चाहते थे क्योंकि मुझे इस बारे में जानकारी नहीं मिली।

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