2012-01-18 5 views
6

Próbuję utworzyć pełną kopię instancji ankiety, która ma kilka sekcji, a każda sekcja ma kilka pytań, a na końcu każde pytanie ma kilka opcji. Używam standardowego django 1.3.1, z MySQL. Muszę mieć możliwość utworzenia pełnej kopii wszystkich tych elementów, dla innego właściciela ankiety. Co obecnie mam w widoku jest:Jak utworzyć głęboki klon obiektu DB w Django?

survey_new = survey 
    survey_new.title = survey.title + ' -- Copy' 
    survey_new.owner = str(new_owner_id) 
    survey_new.created = datetime.now() 
    survey_new.pk = None 
    survey_new.save() 

    for sec in survey.sections.all().order_by('order'): 
     sec_n = sec 
     sec_n.survey_id = survey_new.id 
     sec_n.pk = None 
     sec_n.save() 

     for q in sec.questions.all().order_by('order'): 
      q_n = q 
      q_n.section_id = sec_n.id 
      q_n.pk = None 
      q_n.save() 

      for op in q.options.all().order_by('order'): 
       op_n = op 
       op_n.question_id = q_n.id 
       op_n.pk = None 
       op_n.save() 

to jednak wydaje się działać na wszystkich pętlach bez żadnych błędów, a tylko tworzenie kopii badania. Miałem nadzieję, że skopiuje to ankietę, sekcje, pytania, opcje dla tej instancji ankiety. Po prostu nie mogę zrozumieć, co robię źle tutaj.

+1

Kilka uwag: 1. Powinieneś przeczytać ['select_related()'] (https://docs.djangoproject.com/en/1.3/ref/models/querysets/#select-related) i sprawdzić, czy wygląda ciekawie. 2. Zachowaj ostrożność podczas kopiowania wartości id lub możesz przypadkowo nadpisać element * original * w DB. –

+0

Dlaczego nie używasz 'Options.objects.create (...)' i 'Section.objects.create (...)' itp.? Dlaczego próbujesz wygłupiać się z PK? –

+0

@Peter: Dzięki za wskaźnik do select_related(). To powinno zoptymalizować mój kod nieco :) – Priyeshj

Odpowiedz

9

Googling „django głęboką kopię "zwraca to na pierwszej stronie: http://www.nerdydork.com/copy-model-object-in-django.html

Co Próbka jest podana:

from copy import deepcopy 
old_obj = deepcopy(obj) 
old_obj.id = None 
old_obj.save() 

Jeśli dobrze rozumiem twoje pytanie, przed zapisaniem będziesz chciał zmienić kilka pól.

+7

Żadna gra słów nie jest zamierzona, ale czy nazwa "old_obj" nie powinna być odpowiednio nazwana "new_obj"? Widzę od kiedy, próbujemy zrobić kopię obiektu i tym samym zrobić nowy obiekt? Po prostu ciekawy. – tilaprimera

+1

@tilaprimera Nie ma żadnej różnicy w funkcjonalności. Jest tak nazwany, ponieważ 'old_obj' jest, oprócz identyfikatora, wartością identyczną z obj w punkcie kopiowania. – Marcin

+3

Po prostu uwaga, to nie skopiuje relacji obiektu, który klonujesz. Które może, ale nie musi być pożądane zachowanie, ale było dla mnie, więc muszę zrobić coś innego. :) – bwest87

1

myślę, że to się dzieje, ponieważ survey przypisany survey_new na tej linii kodu

survey_new = survey 

wtedy gdy survey_new zapisane

survey_new.title = survey.title + ' -- Copy' 
survey_new.owner = str(new_owner_id) 
survey_new.created = datetime.now() 
survey_new.pk = None 
survey_new.save() 

survey stała równa survey_new. Na przykład można sprawdzić to tak

id(survey) 
# 50016784 
id(survey_new) 
# 50016784 

lub Django równoważne

survey.id 
# 10 
survey_new.id 
# 10 

Aby dowiedzieć się problem, wszystkie wymagane przedmioty mają być zbierane przed cesją

survey_section = survey.sections.all().order_by('order') 
# ... all other questions and options 

survey_new = survey 
survey_new.title = survey.title + ' -- Copy' 
survey_new.owner = str(new_owner_id) 
# ... your remaining code