আমি কীভাবে একটি জ্যাঙ্গো মডেল উদাহরণ আইটেমটি ক্লোন করে এটি ডাটাবেসে সংরক্ষণ করব?


260
Foo.objects.get(pk="foo")
<Foo: test>

ডাটাবেসে আমি অন্য একটি বস্তু যুক্ত করতে চাই যা উপরের বস্তুর অনুলিপি।

ধরুন আমার টেবিলটিতে একটি সারি রয়েছে। আমি প্রথম সারির অবজেক্টটি অন্য একটি সারিতে অন্য প্রাথমিক কী সহ সন্নিবেশ করতে চাই। আমি এটা কিভাবে করবো?

উত্তর:


437

কেবলমাত্র আপনার অবজেক্টের প্রাথমিক কী পরিবর্তন করুন এবং সেভ () সংরক্ষণ করুন।

obj = Foo.objects.get(pk=<some_existing_pk>)
obj.pk = None
obj.save()

আপনি যদি স্বয়ংক্রিয়ভাবে উত্পন্ন কীটি চান তবে নতুন কীটি কোনওটিতে সেট করুন।

আরো আপডেট / সন্নিবেশের উপর এখানে

মডেল উদাহরণগুলি অনুলিপি করার বিষয়ে সরকারী দস্তাবেজ: https://docs.djangoproject.com/en/2.2/topics/db/queries/#copying-model-inferences


2
এটি লক্ষণীয় যে এই জ্যাঙ্গো 1.2 এর উদ্ধৃতি দিয়েছিল, আমরা এখন জ্যাঙ্গো 1.4 পর্যন্ত আছি। এটি কাজ করে কি না তা পরীক্ষা করে দেখা হয়নি, তবে এটি আপনার জন্য কাজ করে কিনা তা নিশ্চিত হয়ে এই উত্তরটি ব্যবহার করবেন না।
জো

7
1.4.1 এ সূক্ষ্মভাবে কাজ করে এটি সম্ভবত এই জিনিসগুলির মধ্যে একটি যা দীর্ঘ সময়ের জন্য কাজ চালিয়ে যাবে।
frnhr

8
আমি উভয় সেট করতে ছিল obj.pkএবং obj.idজ্যাঙ্গো 1.4 এ এই কাজ করতে
পেত্র Peller

3
@ পেটারপেলার - দস্তাবেজগুলির পরামর্শ দেয় কারণ আপনি মডেল উত্তরাধিকার ব্যবহার করছেন।
ডোমিনিক রজার

12
দ্রষ্টব্য: বিদেশী কীগুলি, ওয়ান টোন এবং এম 2 এম এর সাথে জড়িত থাকলে জিনিসগুলি কিছুটা জটিল হতে পারে (অর্থাত্ আরও জটিল "গভীর অনুলিপি" থাকতে পারে)
বেন রবার্টস

135

ডাটাবেস প্রশ্নের জন্য জ্যাঙ্গো ডকুমেন্টেশনে মডেল উদাহরণগুলি অনুলিপি করার একটি বিভাগ অন্তর্ভুক্ত রয়েছে । আপনার প্রাথমিক কীগুলি স্বয়ংক্রিয়ভাবে উত্পন্ন হয়েছে তা ধরে নিলে আপনি যে বিষয়টিকে অনুলিপি করতে চান সেটি পেয়ে যান None, প্রাথমিক কীটি এতে সেট করুন এবং বস্তুকে আবার সংরক্ষণ করুন:

blog = Blog(name='My blog', tagline='Blogging is easy')
blog.save() # blog.pk == 1

blog.pk = None
blog.save() # blog.pk == 2

এই স্নিপেটে, প্রথমটি save()আসল অবজেক্ট তৈরি করে এবং দ্বিতীয়টি save()অনুলিপি তৈরি করে।

আপনি যদি ডকুমেন্টেশনটি পড়া চালিয়ে যান, তবে আরও দুটি জটিল কেস কীভাবে পরিচালনা করতে হবে তারও উদাহরণ রয়েছে: (1) মডেল সাবক্লাসের উদাহরণ হিসাবে থাকা কোনও বস্তুর অনুলিপি করা এবং (2) বহু-টু-তে অবজেক্টগুলি সহ সম্পর্কিত বস্তুগুলি অনুলিপি করা - অনেক সম্পর্ক।


মিয়ার জবাব সম্পর্কে দ্রষ্টব্য: পিকে সেট করার Noneবিষয়টি মিয়ার উত্তরে উল্লেখ করা হয়েছে, যদিও এটি সামনে এবং কেন্দ্র উপস্থাপন করা হয়নি। সুতরাং আমার উত্তরটি প্রধানত সেই পদ্ধতিটিকে জাজানো-প্রস্তাবিত উপায় হিসাবে জোর দেওয়ার কাজ করে।

Noteতিহাসিক দ্রষ্টব্য: জাজানো ডক্সে এটি সংস্করণ 1.4 পর্যন্ত ব্যাখ্যা করা হয়নি। যদিও এটি 1.4 এর আগে থেকেই সম্ভব ছিল।

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


46

এখানে সাবধান। আপনি যদি কোনও ধরণের লুপে থাকেন এবং আপনি একে একে অবজেক্টগুলি পুনরুদ্ধার করেন তবে এটি অত্যন্ত ব্যয়বহুল হতে পারে। আপনি যদি ডাটাবেসে কলটি না চান তবে কেবল করুন:

from copy import deepcopy

new_instance = deepcopy(object_you_want_copied)
new_instance.id = None
new_instance.save()

এটি অন্যান্য অন্যান্য উত্তরের মতো একই কাজ করে তবে এটি কোনও বস্তু পুনরুদ্ধারে ডাটাবেস কল করে না। এটি ডাটাবেসে এখনও বিদ্যমান নেই এমন কোনও অনুলিপি তৈরি করতে চাইলে এটিও কার্যকর।


1
এটি দুর্দান্ত কাজ করে যদি আপনার কোনও অবজেক্ট থাকে, আপনি নতুন অবজেক্টে পরিবর্তন আনার আগে এটির মূল বিষয়টিকে গভীরভাবে অনুলিপি করতে পারবেন এবং সংরক্ষণ করতে পারবেন। তারপরে আপনি কিছু শর্ত যাচাই করতে পারেন এবং যদি তারা উত্তীর্ণ হয় তার উপর নির্ভর করে, বস্তুটি অন্য টেবিলে রয়েছে যা আপনি যাচাই করছেন, আপনি new_instance.id = original_instance.id সেট করতে পারেন এবং সংরক্ষণ করুন :) ধন্যবাদ!
র‌্যাডটেক

2
মডেলটির একাধিক উত্তরাধিকারের স্তর থাকলে এটি কাজ করে না।
ডেভিড চেউং

1
আমার ক্ষেত্রে আমি মডেলটির জন্য একটি ক্লোন পদ্ধতি তৈরি করতে চেয়েছিলাম, যা "স্ব" পরিবর্তনশীল ব্যবহার করবে এবং আমি কেবলমাত্র সেলফ.পি.কে কিছুই সেট করতে পারি না, সুতরাং এই সমাধানটি কবজির মতো কাজ করেছিল। আমি নীচে মডেল_ট_ডিক্ট সমাধান সম্পর্কে ভেবেছিলাম, তবে এটির জন্য একটি অতিরিক্ত পদক্ষেপের প্রয়োজন এবং সম্পর্কের মাধ্যমে এটি একই সমস্যা হতে পারে, যা আমাকে যেভাবেই ম্যানুয়ালি মোকাবেলা করতে হবে তাই এটি আমার পক্ষে কোনও বড় প্রভাব ফেলবে না।
অ্যান্ডারসন সান্টোস

32

নীচের কোডটি ব্যবহার করুন:

from django.forms import model_to_dict

instance = Some.objects.get(slug='something')

kwargs = model_to_dict(instance, exclude=['id'])
new_instance = Some.objects.create(**kwargs)

8
model_to_dictএকটি excludeপ্যারামিটার নেয় , যার অর্থ আপনার আলাদা করার দরকার নেই pop:model_to_dict(instance, exclude=['id'])
জর্জিবারক

20

এখানে একটি ক্লোন স্নিপেট রয়েছে , যা আপনি আপনার মডেলটিতে এটি যুক্ত করতে পারেন যা এটি করে:

def clone(self):
  new_kwargs = dict([(fld.name, getattr(old, fld.name)) for fld in old._meta.fields if fld.name != old._meta.pk]);
  return self.__class__.objects.create(**new_kwargs)

@ ব্যবহারকারী 426975 - আহা, ভাল (আমি আমার উত্তর থেকে এটি সরিয়েছি)।
ডমিনিক রজার

নিশ্চিত না এই একটি জ্যাঙ্গো সংস্করণ জিনিস, কিন্তু ifএখন করা প্রয়োজন if fld.name != old._meta.pk.name, অর্থাত্, nameসম্পত্তির _meta.pkউদাহরণস্বরূপ।
ক্রিস

20

এটি কীভাবে জাজানো ১.৪ এর অফিসিয়াল জ্যাঙ্গো ডক্সে যুক্ত করা হয়েছিল

https://docs.djangoproject.com/en/1.10/topics/db/queries/#copying-model-instances

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


আপনি লিঙ্কটি খুললে এটিতে পৃষ্ঠায় সন্ধান পাওয়া যায়নি
অমৃত

জাজানো ১.৪ এর জন্য দস্তাবেজগুলি আর বিদ্যমান নেই। আমি উত্তরটি সর্বশেষতম ডক্সে নির্দেশ করার জন্য আপডেট করব।
মাইকেল বাইলস্ট্রা

1
@MichaelBylstra একটি ভাল উপায় চিরহরিৎ লিঙ্ক আছে ব্যবহার করা stable: URL- এ সংস্করণ সংখ্যা পরিবর্তে মত এই docs.djangoproject.com/en/stable/topics/db/queries/...
Flimm

8

আমি গৃহীত উত্তর দিয়ে কয়েকটা গোটাচায় ছড়িয়েছি। এখানে আমার সমাধান।

import copy

def clone(instance):
    cloned = copy.copy(instance) # don't alter original instance
    cloned.pk = None
    try:
        delattr(cloned, '_prefetched_objects_cache')
    except AttributeError:
        pass
    return cloned

দ্রষ্টব্য: এটি সমাধানগুলি ব্যবহার করে যা জ্যাঙ্গো ডক্সে আনুষ্ঠানিকভাবে অনুমোদিত নয় এবং তারা ভবিষ্যতের সংস্করণগুলিতে কাজ করা বন্ধ করতে পারে। আমি এটি পরীক্ষা করেছি 1.9.13 এ।

প্রথম উন্নতি হ'ল এটি আপনাকে ব্যবহার করে মূল দৃষ্টান্তটি ব্যবহার চালিয়ে যাওয়ার অনুমতি দেয় copy.copy। এমনকি আপনি যদি উদাহরণটি পুনঃব্যবহারের উদ্দেশ্যে নাও করেন তবে আপনি যে ক্লোনিং করছেন সেটি কোনও ফাংশনের আর্গুমেন্ট হিসাবে পাস করা হলে এই পদক্ষেপটি করা আরও নিরাপদ। যদি তা না হয় তবে ফাংশনটি ফিরে আসার সাথে কলারের অপ্রত্যাশিতভাবে আলাদা ঘটনা ঘটবে।

copy.copyপছন্দসই উপায়ে জ্যাঙ্গো মডেলের উদাহরণের অগভীর অনুলিপি তৈরি করেছে বলে মনে হচ্ছে। এটি এমন একটি জিনিস যা আমি নথিভুক্ত পাইনি, তবে এটি পিকিং এবং আন-পিক্লিংয়ের মাধ্যমে কাজ করে, সুতরাং এটি সম্ভবত ভাল-সমর্থিত।

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

মুছে ফেলা _prefetched_objects_cacheসমস্ত প্রিফেসকে সরিয়ে ফেলার একটি দ্রুত এবং নোংরা উপায়। পরবর্তীকালে অনেকগুলি অ্যাক্সেসগুলি এমনভাবে কাজ করে যেন কোনও প্রিফেচ ছিল না। আন্ডারস্কোর দিয়ে শুরু হওয়া একটি অননুমোদিত সম্পত্তি ব্যবহার করা সম্ভবত সামঞ্জস্যের সমস্যার জন্য জিজ্ঞাসা করছে, তবে এটি আপাতত কাজ করে।


আমি এটি কাজ করতে সক্ষম হয়েছি, তবে মনে হচ্ছে এটি ইতিমধ্যে 1.11-এ পরিবর্তিত হয়েছে, যেমন আমার একটি সম্পত্তি বলা হয়েছিল _[model_name]_cache, যা একবার মুছে ফেলা হয়েছিল, আমি সেই সম্পর্কিত মডেলের জন্য একটি নতুন আইডি বরাদ্দ করতে সক্ষম হয়েছি, তারপরে কল করুন save()। এখনও নির্ধারিত হয়নি এমন পার্শ্ব প্রতিক্রিয়া থাকতে পারে।
trpt4 Him 19

ক্লাস / মিক্সিনে কোনও ফাংশনে ক্লোনিং করা যদি এটি করা হয় তবে এটি অত্যন্ত গুরুত্বপূর্ণ তথ্য, কারণ এটি অন্যথায় 'স্ব' গন্ডগোল করবে এবং আপনি সমস্ত বিভ্রান্ত হবেন।
Andreas Bergström

5

কারও কাছে পিকে সেট করা ভাল নয়, সাইনজ জ্যাঙ্গো আপনার জন্য সঠিকভাবে একটি পিকে তৈরি করতে পারে

object_copy = MyObject.objects.get(pk=...)
object_copy.pk = None
object_copy.save()

3

এটি মডেল উদাহরণটিকে ক্লোন করার আরও একটি উপায়:

d = Foo.objects.filter(pk=1).values().first()   
d.update({'id': None})
duplicate = Foo.objects.create(**d)

0

একাধিক উত্তরাধিকারের স্তরের সাথে মডেলটিকে ক্লোন করতে, অর্থাৎ> = 2 বা নীচে মডেলসি

class ModelA(models.Model):
    info1 = models.CharField(max_length=64)

class ModelB(ModelA):
    info2 = models.CharField(max_length=64)

class ModelC(ModelB):
    info3 = models.CharField(max_length=64)

প্রশ্ন এখানে উল্লেখ করুন


হ্যাঁ হ্যাঁ, তবে সেই প্রশ্নের কোনও স্বীকৃত উত্তর নেই! যাওয়ার পথে!
বোবার্ট

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