জাজানো 1.7 এবং ডেটা মাইগ্রেশন সহ প্রাথমিক ডেটা লোড হচ্ছে


96

আমি সম্প্রতি জ্যাঙ্গো 1.6 থেকে 1.7 এ পরিবর্তন করেছি এবং আমি মাইগ্রেশন ব্যবহার করতে শুরু করেছি (আমি কখনই দক্ষিণ ব্যবহার করিনি)।

1.7 এর আগে, আমি একটি fixture/initial_data.jsonফাইল দিয়ে প্রাথমিক ডেটা লোড করতাম , যা python manage.py syncdbকমান্ড (ডাটাবেস তৈরি করার সময় ) দিয়ে লোড করা হয়েছিল ।

এখন, আমি মাইগ্রেশন ব্যবহার শুরু করেছি এবং এই আচরণটি অবচিত করা হয়েছে:

যদি কোনও অ্যাপ্লিকেশন মাইগ্রেশন ব্যবহার করে তবে ফিক্সচারগুলির কোনও স্বয়ংক্রিয় লোডিং নেই। যেহেতু জ্যাঙ্গো ২.০ এ অ্যাপ্লিকেশনগুলির জন্য মাইগ্রেশনগুলির প্রয়োজন হবে, তাই এই আচরণটিকে অবহেলা হিসাবে বিবেচনা করা হয়। আপনি যদি কোনও অ্যাপের জন্য প্রাথমিক ডেটা লোড করতে চান তবে ডেটা মাইগ্রেশনে এটি করার বিষয়টি বিবেচনা করুন। ( https://docs.djangoproject.com/en/1.7/howto/initial-data/#automatic-loading-initial-data-fixtures )

সরকারী ডকুমেন্টেশন তাই আমার প্রশ্ন হল কিভাবে এটা করবেন উপর একটি পরিষ্কার উদাহরণ নেই:

ডেটা মাইগ্রেশন ব্যবহার করে এই জাতীয় ডেটা আমদানির সর্বোত্তম উপায়:

  1. একাধিক কল সহ পাইথন কোড লিখুন mymodel.create(...),
  2. JSON ফিক্সার ফাইল থেকে ডেটা লোড করতে একটি জ্যাঙ্গো ফাংশন ( কলloaddata করার মতো ) ব্যবহার বা লিখুন ।

আমি দ্বিতীয় বিকল্প পছন্দ।

আমি দক্ষিণ ব্যবহার করতে চাই না, যেহেতু জ্যাঙ্গো এখন স্থানীয়ভাবে এটি করতে সক্ষম হবে বলে মনে হচ্ছে।


4
এছাড়াও, আমি ওপির মূল প্রশ্নের সাথে আরও একটি প্রশ্ন যুক্ত করতে চাই: আমাদের অ্যাপ্লিকেশনগুলিতে অন্তর্ভুক্ত না থাকা ডেটার জন্য আমাদের কীভাবে ডেটা মাইগ্রেশন করা উচিত। উদাহরণস্বরূপ, যদি কেউ সাইটের ফ্রেমওয়ার্ক ব্যবহার করে থাকে তবে তার অবশ্যই সাইটের ডেটা সহ একটি ফিক্সচার থাকা দরকার। যেহেতু সাইটগুলির কাঠামোটি আমাদের অ্যাপ্লিকেশনগুলির সাথে সম্পর্কিত নয় তাই আমাদের সেই ডেটা মাইগ্রেশনটি কোথায় রাখা উচিত? ধন্যবাদ!
Serafeim

একটি গুরুত্বপূর্ণ বিষয় যা এখানে কারও দ্বারা চিহ্নিত করা যায় নি তা হ'ল যখন আপনার কোনও মাইগ্রেশনকে জালিয়াতিযুক্ত একটি ডাটাবেসে ডেটা মাইগ্রেশনে সংজ্ঞায়িত ডেটা যুক্ত করতে হবে তখনই ঘটে happens যেহেতু মাইগ্রেশনগুলি নকল হয়েছিল, তাই আপনার ডেটা মাইগ্রেশন চলবে না এবং আপনাকে অবশ্যই এটি হাত দ্বারা করতে হবে। এই মুহুর্তে আপনি কেবল একটি ফিক্সিং ফাইলে লোডডাটা কল করতে পারেন।
hekevintran

আর একটি আকর্ষণীয় দৃশ্য হ'ল যদি লেখক তৈরি করতে আপনার কাছে ডেটা মাইগ্রেশন থাকে happens উদাহরণস্বরূপ গোষ্ঠী দৃষ্টান্তগুলি এবং পরে আপনার একটি নতুন গোষ্ঠী থাকে যা আপনি বীজ ডেটা হিসাবে তৈরি করতে চান। আপনাকে একটি নতুন ডেটা মাইগ্রেশন তৈরি করতে হবে। এটি বিরক্তিকর হতে পারে কারণ আপনার গ্রুপ বীজের ডেটা একাধিক ফাইলে থাকবে। এছাড়াও আপনি যে স্থানান্তরগুলি পুনরায় সেট করতে চান সেই ইভেন্টে, আপনাকে বীজ ডেটা সেট আপ করতে এবং সেগুলি পোর্ট করে এমন ডেটা মাইগ্রেশনগুলি সন্ধান করতে হবে।
hekevintran

@ সেরেফেইম "তৃতীয় পক্ষের অ্যাপের জন্য প্রাথমিক ডেটা কোথায় রাখবেন" প্রশ্নটি পরিবর্তিত হয় না যদি আপনি ফিক্সারের পরিবর্তে ডেটা মাইগ্রেশন ব্যবহার করেন, যেহেতু আপনি কেবল ডেটা লোড হওয়ার উপায়টি পরিবর্তন করেন। আমি এই জাতীয় জিনিসগুলির জন্য একটি ছোট কাস্টম অ্যাপ্লিকেশন ব্যবহার করি। যদি তৃতীয় পক্ষের অ্যাপ্লিকেশনটিকে "foo" বলা হয়, আমি ডেটা মাইগ্রেশন / ফিক্সচার "foo_integration" সম্বলিত আমার সাধারণ অ্যাপটিকে কল করি।
guettli

@ গুয়েটলি হ্যাঁ, সম্ভবত একটি অতিরিক্ত অ্যাপ্লিকেশন ব্যবহার করা এটি করার সর্বোত্তম উপায়!
সেরেফেইম

উত্তর:


82

আপডেট : এই সমাধানটি যে সমস্যার সৃষ্টি করতে পারে তার জন্য নীচে @ গুইনব্লেইডডির মন্তব্য দেখুন এবং ভবিষ্যতের মডেল পরিবর্তনের জন্য আরও টেকসই এমন পদ্ধতির জন্য নীচে @ রোকলাইটের উত্তর দেখুন।


ধরে নিচ্ছি আপনার কাছে ফিক্সচার ফাইল রয়েছে <yourapp>/fixtures/initial_data.json

  1. আপনার খালি স্থানান্তর তৈরি করুন:

    জ্যাঙ্গো ১.7 এ:

    python manage.py makemigrations --empty <yourapp>
    

    জাজানো 1.8+ তে আপনি একটি নাম সরবরাহ করতে পারেন:

    python manage.py makemigrations --empty <yourapp> --name load_intial_data
    
  2. আপনার স্থানান্তর ফাইলটি সম্পাদনা করুন <yourapp>/migrations/0002_auto_xxx.py

    2.1। কাস্টম বাস্তবায়ন, জ্যাঙ্গো দ্বারা অনুপ্রাণিত 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>'র fixturesDir স্বয়ংক্রিয়ভাবে:

    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>
    

4
ঠিক আছে, আপনি ঠিক বলেছেন ... এছাড়াও loaddata('loaddata', fixture_filename, app_label='<yourapp>')
কলিংও

15
এই পদ্ধতিটি ব্যবহার করে সিরিয়ালাইজার বর্তমান models.pyফাইলগুলি থেকে মডেলগুলির উপরে কাজ করবে , এতে কিছু অতিরিক্ত ক্ষেত্র বা কিছু অন্যান্য পরিবর্তন থাকতে পারে। মাইগ্রেশন তৈরির পরে যদি কিছু পরিবর্তন করা হয় তবে এটি ব্যর্থ হবে (সুতরাং আমরা সেই স্থানান্তরের পরে স্কিমা মাইগ্রেশনও তৈরি করতে পারি না)। এটি স্থির করার জন্য আমরা অ্যাপ্লিকেশনগুলির রেজিস্ট্রি টেপোরালি পরিবর্তন করতে পারি যে সিরিয়ালাইজার প্রথম প্যারামিটারে মাইগ্রেশন ফিকশনকে সরবরাহ করা রেজিস্ট্রিতে কাজ করছে। পাথের রেজিস্ট্রি অবস্থিত django.core.serializers.python.apps
GwynBleidD

4
কেন আমরা এই করছেন? কেন জাজানো চালানো এবং রক্ষণাবেক্ষণ করা আরও বেশি কঠিন হয়ে উঠল? আমি যদিও এটি যেতে চাই না, আমি একটি সাধারণ কমান্ড লাইন ইন্টারফেস চাই যা আমার জন্য এই সমস্যাটি সমাধান করে, যেমন এটি ফিক্সচারগুলির সাথে ব্যবহৃত হত।
জাজানো এই জিনিসটি

4
@ GwynBleidD এটি আপনি তৈরি করছেন এমন একটি অত্যন্ত গুরুত্বপূর্ণ বিষয় এবং আমি মনে করি এটি গ্রহণযোগ্য উত্তরে প্রদর্শিত হবে। এটি একই মন্তব্য যা ডকুমেন্টেশনের ডেটা মাইগ্রেশন কোড উদাহরণে মন্তব্য হিসাবে উপস্থিত হয় । আপনি কী app registryবিশ্বব্যাপী ভেরিয়েবল পরিবর্তন না করে সরবরাহ করা সিরিয়ালাইজার ব্যবহারের অন্য উপায়টি জানেন (যা সমান্তরাল ডাটাবেস স্থানান্তরের ক্ষেত্রে একটি হাইপোথিটিক ভবিষ্যতে সমস্যা সৃষ্টি করতে পারে)।
বিজ্ঞাপন এন

4
এই উত্তরটি গ্রহণযোগ্যতার পাশাপাশি কাজুতে উত্সাহিত করা হ'ল আমি কেন লোকদের স্ট্যাকওভারফ্লো ব্যবহার না করার পরামর্শ দিই। এখনও এখন পর্যন্ত আমার কাছে মন্তব্য এবং উপাখ্যানগুলি দিয়ে # জাজানোতে এটি উল্লেখ করা হয়েছে।
শ্যাঙ্গজিয়াও

52

সংক্ষিপ্ত সংস্করণ

আপনার সরাসরি ডেটা মাইগ্রেশনে পরিচালনা কমান্ড ব্যবহার করা উচিত নয়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যা মাইগ্রেশন মধ্যে ঐতিহাসিক তথ্য deserialize সবচেয়ে আপ-টু-ডেট মডেল ব্যবহার করে। এটি ভুল আচরণ।

উদাহরণস্বরূপ, মনে করা হয় যে কোনও ডেটা মাইগ্রেশন রয়েছে যা loaddataকোনও ফিক্সচার থেকে ডেটা লোড করার জন্য ম্যানেজমেন্ট কমান্ড ব্যবহার করে এবং এটি ইতিমধ্যে আপনার বিকাশের পরিবেশে প্রয়োগ করা হয়েছে।

পরে, আপনি সংশ্লিষ্ট মডেলটিতে একটি নতুন প্রয়োজনীয় ক্ষেত্র যুক্ত করার সিদ্ধান্ত নিয়েছেন, তাই আপনি এটি করেন এবং আপনার আপডেট হওয়া মডেলের বিপরীতে একটি নতুন মাইগ্রেশন করেন (এবং সম্ভবত ./manage.py makemigrationsআপনাকে অনুরোধ জানানো হলে নতুন ক্ষেত্রে একটি এক-অফ মূল্য প্রদান করবেন )।

আপনি পরবর্তী স্থানান্তর চালান, এবং সবকিছু ঠিক আছে।

অবশেষে, আপনি আপনার জাজানো অ্যাপ্লিকেশনটি বিকাশ সম্পন্ন করেছেন এবং আপনি এটি প্রোডাকশন সার্ভারে স্থাপন করেন। উত্পাদনের পরিবেশের উপর স্ক্র্যাচ থেকে পুরো মাইগ্রেশন চালানোর এখন সময়।

তবে ডেটা মাইগ্রেশন ব্যর্থ হয় । এর কারণ হ'ল loaddataকমান্ড থেকে ডিসরিয়ালাইজড মডেল , যা বর্তমান কোডটি উপস্থাপন করে, আপনার যুক্ত হওয়া নতুন প্রয়োজনীয় ক্ষেত্রের খালি ডেটা দিয়ে সংরক্ষণ করা যাবে না । মূল ফিক্সিং এর জন্য প্রয়োজনীয় ডেটার অভাব রয়েছে!

আপনি যদি নতুন ক্ষেত্রের জন্য প্রয়োজনীয় ডেটা সহ ফিক্সচারটি আপডেট করেন তবে ডেটা মাইগ্রেশনটি এখনও ব্যর্থ হয় । যখন ডেটা মাইগ্রেশন চলমান থাকে, পরবর্তী মাইগ্রেশন যা ডাটাবেসে সংশ্লিষ্ট কলাম যুক্ত করে তা এখনও প্রয়োগ হয় না। আপনি কোনও কলামে ডেটা সংরক্ষণ করতে পারবেন না যা বিদ্যমান নেই!

উপসংহার: একটি ডেটা মাইগ্রেশনে,loaddataকমান্ডটি মডেল এবং ডাটাবেসের মধ্যে সম্ভাব্য অসামঞ্জস্যতার পরিচয় দেয়। আপনার অবশ্যইএটি কোনও ডেটা মাইগ্রেশনে সরাসরি ব্যবহার করাউচিত নয়

সমাধান

loaddataকমান্ডটি django.core.serializers.python._get_modelকোনও ফিক্সিং থেকে সংশ্লিষ্ট মডেলটি পেতে ফাংশনের উপর নির্ভর করে , যা কোনও মডেলের সর্বাধিক আপ-টু-ডেট সংস্করণ প্রদান করবে। আমাদের এটি বানর-প্যাচ করা দরকার যাতে এটি historicalতিহাসিক মডেলটি পায়।

(নিম্নলিখিত কোড জ্যাঙ্গো 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),
    ]

4
রোকালাইট, আপনি একটি খুব দৃ point় পয়েন্ট। আপনার উত্তরটি আমাকে ভাবতে ছাড়ল যদিও, @ n__o / @ মিলিসনারের উত্তর objects = serializers.deserialize('json', fixture, ignorenonexistent=True)থেকে একই সমস্যা থেকে ভোগার উপর নির্ভর করে ২.১ সমাধান করবে loaddata? বা ignorenonexistent=Trueসমস্ত সম্ভাব্য বিষয় কভার করে ?
ডারিও

7
আপনি যদি উত্সটি দেখেন তবে আপনি খুঁজে পাবেন যে ignorenonexistent=Trueযুক্তির দুটি প্রভাব রয়েছে: 1) এটি এমন কোনও ফিক্সারের মডেলগুলিকে উপেক্ষা করে যা সর্বাধিক মডেলের সংজ্ঞাগুলিতে নেই, ২) এটি কোনও ফিক্সচারের মডেলের ক্ষেত্রগুলিকে উপেক্ষা করে যা অবৈধ নয় সর্বাধিক বর্তমান সম্পর্কিত মডেল সংজ্ঞাতে। তাদের মধ্যে কেউই নতুন-প্রয়োজনীয়-ফিল্ড-ইন-মডেল পরিস্থিতিটি পরিচালনা করে না। সুতরাং, হ্যাঁ, আমি মনে করি এটি সাধারণ হিসাবে একই সমস্যা ভোগাচ্ছে loaddata
রকাল্লাইট

আমি যখন বুঝতে পেরেছিলাম যে আমার পুরানো জসনের একটি মডেল ব্যবহার করে অন্যান্য মডেলগুলি রেফারেন্স করেছে natural_key(), যা এই পদ্ধতিটি সমর্থন করে বলে মনে হচ্ছে না - আমি কেবলমাত্র রেফারেন্সড মডেলের আসল আইডি দিয়ে প্রাকৃতিক_কি মানটি প্রতিস্থাপন করেছি।
dsummersl

4
সম্ভবত গ্রহণযোগ্য উত্তর হিসাবে এই উত্তরটি আরও সহায়ক হবে, কারণ পরীক্ষার ক্ষেত্রে একটি নতুন ডাটাবেস তৈরি হয় এবং সমস্ত মাইগ্রেশন স্ক্র্যাচ থেকে প্রয়োগ করা হয়। এই সমাধানটি সমস্যার সমাধান করে যা ইউনিটেস্টযুক্ত একটি প্রকল্প ডেটা মাইগ্রেশনে _get_model প্রতিস্থাপন না করার ক্ষেত্রে सामना করতে পারে। টিএনএক্স
মোহাম্মদ আলি বাগেরশেমিরানী

আপডেট এবং ব্যাখ্যার জন্য ধন্যবাদ, @ রোকলাইট। আমার প্রাথমিক উত্তরটি জ্যাঙ্গো ১.7 এ মাইগ্রেশন চালু হওয়ার কয়েক সপ্তাহ পরে পোস্ট করা হয়েছিল এবং কীভাবে এগিয়ে যাওয়া যায় সে সম্পর্কে ডকুমেন্টেশনটি অস্পষ্ট ছিল (এবং এখনও শেষ বার যাচাই করেছিলাম)। আশা করি জাজানো কোনও দিন মডেল ইতিহাস বিবেচনায় নিতে তাদের লোডডেটা / মাইগ্রেশন প্রক্রিয়াটি আপডেট করবে।
n__o

6

কয়েকটি মন্তব্যে (যথা n__o এর) এবং আমার initial_data.*অনেকগুলি অ্যাপ্লিকেশনে ছড়িয়ে থাকা আমার কাছে প্রচুর ফাইল রয়েছে তা থেকে অনুপ্রাণিত হয়ে আমি সিদ্ধান্ত নিয়েছিলাম যে একটি জ্যাঙ্গো অ্যাপ্লিকেশন তৈরি করা হবে যা এই ডেটা মাইগ্রেশন তৈরিতে সহায়তা করবে।

জ্যাঙ্গো-মাইগ্রেশন-ফিক্সচার ব্যবহার করে আপনি কেবল নিম্নলিখিত ম্যানেজমেন্ট কমান্ডটি চালাতে পারেন এবং এটি ফাইলগুলির 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.

ইনস্টল / ব্যবহারের নির্দেশাবলীর জন্য জাঙ্গো-মাইগ্রেশন-ফিক্সচার দেখুন ।


2

আপনার ডাটাবেসটিকে কিছু প্রাথমিক ডেটা দেওয়ার জন্য, একটি ডেটা মাইগ্রেশন লিখুন ডেটা মাইগ্রেশনে আপনার ডেটা লোড করতে রানপাইথন ফাংশনটি ব্যবহার করুন ।

কোনও লোডডাটা কমান্ড লিখবেন না কারণ এইভাবে হ্রাস করা হয়েছে।

আপনার ডেটা মাইগ্রেশন কেবল একবার চালানো হবে। স্থানান্তর হ'ল স্থানান্তরের একটি আদেশযুক্ত ক্রম। 003_xxxx.py মাইগ্রেশন চালিত হলে, জাঙ্গো মাইগ্রেশন ডাটাবেসে লিখেছে যে এই অ্যাপ্লিকেশনটি এই (003) পর্যন্ত স্থানান্তরিত হয়েছে এবং কেবল নিম্নলিখিত স্থানান্তরগুলি চালিত করবে।


সুতরাং আপনি আমাকে myModel.create(...)রানপিথন ফাংশনে কলগুলি পুনরায় (বা একটি লুপ ব্যবহার করে) পুনরাবৃত্তি করতে উত্সাহিত করেছেন ?
মিকৈল

হ্যাঁ বেশ। লেনদেনের ডাটাবেসগুলি এটি পুরোপুরি পরিচালনা করবে :)
FlogFR

1

উপরোক্ত সমাধানগুলি আমার জন্য দুর্ভাগ্যজনকভাবে কার্যকর হয়নি। আমি দেখতে পেয়েছি যে প্রতিবার আমি আমার মডেলগুলি পরিবর্তন করি আমাকে আমার ফিক্সারগুলি আপডেট করতে হবে। আদর্শভাবে আমি পরিবর্তিত ডেটা এবং ফিক্সচার-লোডড ডেটা একইভাবে সংশোধন করতে ডেটা মাইগ্রেশন লিখতে চাই।

এটির সুবিধার্থে আমি একটি দ্রুত ফাংশন লিখেছি যা fixturesবর্তমান অ্যাপের ডিরেক্টরিতে প্রদর্শিত হবে এবং একটি ফিক্সিশন লোড করবে। মডেল ইতিহাসের পয়েন্টে এই ফাংশনটিকে মাইগ্রেশনে রাখুন যা মাইগ্রেশনের ক্ষেত্রগুলির সাথে মেলে।


এর জন্য ধন্যবাদ! আমি একটি সংস্করণ লিখেছিলাম যা পাইথন 3 এর সাথে কাজ করে (এবং আমাদের কঠোর পাইলিন্টটি পাস করে)। আপনি এটি কারখানা হিসাবে ব্যবহার করতে পারেন RunPython(load_fixture('badger', 'stoat'))gist.github.com/danni/1b2a0078e998ac080111
ড্যানিয়েল

1

আমার মতে ফিক্সচারগুলি কিছুটা খারাপ। যদি আপনার ডাটাবেস ঘন ঘন পরিবর্তিত হয় তবে এগুলিকে আপ টু ডেট রাখাই শীঘ্রই একটি দুঃস্বপ্ন হবে। আসলে, এটি আমার মতামতই নয়, "জাঙ্গোর দুটি স্কুপস" বইতে এটি আরও ভালভাবে ব্যাখ্যা করা হয়েছে।

পরিবর্তে আমি প্রাথমিক সেটআপ সরবরাহ করতে পাইথন ফাইলটি লিখব। আপনার যদি আরও কিছু প্রয়োজন হয় তবে আমি আপনাকে ফ্যাক্টরি ছেলেটির দিকে নজর দেওয়ার পরামর্শ দেব ।

আপনার যদি কিছু ডেটা মাইগ্রেট করতে হয় তবে আপনার ডেটা মাইগ্রেশন ব্যবহার করা উচিত ।

এর রয়েছে "আপনার রাজধানী, ব্যবহার করুন মডেল কারখানা বার্ন ' রাজধানী ব্যবহার সম্পর্কে।


4
আমি আপনার বক্তব্য "ঘন ঘন পরিবর্তন হলে বজায় রাখা শক্ত" এর সাথে একমত, তবে এখানে প্রকল্পটি ইনস্টল করার সময় কেবলমাত্র প্রাথমিক (এবং সর্বনিম্ন) ডেটা সরবরাহ করা ...
মিকৈল

4
এটি এক সময়ের ডেটা লোডের জন্য, যা যদি এটি মাইগ্রেশন প্রসঙ্গে হয় তবে তা বোঝা যায়। যেহেতু এটি কোনও মাইগ্রেশনের মধ্যে রয়েছে তাই জসন ডেটাতে কোনও পরিবর্তন করা উচিত নয়। রাস্তার আরও নিচে ডেটাতে পরিবর্তনগুলির প্রয়োজন হয় এমন কোনও স্কিমা পরিবর্তনগুলি অন্য স্থানান্তরের মাধ্যমে হ্যান্ডেল করা উচিত (সেই সময়ে সম্ভবত ডেটাবেজে অন্যান্য ডেটাও যা পরিবর্তন করতে হবে)।
এমটিএনপল

0

জাঙ্গো ২.১-তে, আমি প্রাথমিক তথ্য সহ কয়েকটি মডেল (উদাহরণস্বরূপ দেশের নামগুলি) লোড করতে চেয়েছিলাম।

তবে আমি চাইছিলাম প্রাথমিক মাইগ্রেশন কার্যকর হওয়ার পরে এটি স্বয়ংক্রিয়ভাবে ঘটুক।

সুতরাং আমি ভেবেছিলাম যে 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মাইগ্রেশন সম্পাদন করার পরেই এটি বিবৃতি চালানোর চেষ্টা করে (আমরা অস্তিত্বহীন টেবিলের বিরুদ্ধে এসকিউএল বিবৃতি চালানোর চেষ্টা করতে চাই না)।

এই স্ক্রিপ্টের উত্স এখানে:

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))
    ]

আমি আশা করি যে কেউ এই সহায়ক পেয়েছেন, এটি আমার পক্ষে ঠিক কাজ করেছে! যদি আপনার কোন প্রশ্ন থাকে, তাহলে আমাকে দয়া করে জানান.

দ্রষ্টব্য: আমি সম্ভবত জাজানো দিয়ে শুরু করার পরে এটি সর্বোত্তম সমাধান হতে পারে না, তবে এখনও এই "কীভাবে" আপনার সকলের সাথে ভাগ করে নিতে চেয়েছিলাম কারণ এই সম্পর্কে গুগল করার সময় আমি খুব বেশি তথ্য পাইনি find

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.