2012-12-11 17 views
7

Mam kreatora formularzy Django, który ładnie pracuje, tworząc zawartość jednego z moich modeli. Chcę użyć tego samego kreatora do edycji danych istniejącej treści, ale nie mogę znaleźć dobrego przykładu, jak to zrobić.Kreator formularzy Django do edycji modelu

Tutaj jest uproszczoną wersją mojego kodu projektu:

forms.py

class ProjectEssentialsForm(forms.ModelForm): 
    class Meta: 
     model = Project 
     fields = [ 
      'title', 
      'short_description', 
      'who_description', 
      'problem_description', 
      'solution_description' 
     ] 

class ProjectYourInfoForm(forms.ModelForm): 
    class Meta: 
     model = Project 
     fields = [ 
      'gender', 
      'location', 
      'post_code', 
      'sector', 
     ] 

views.py

TEMPLATES = { 
    'project_essentials': 'projects/essentials-form.html', 
    'project_your_info': 'projects/your-info-form.html', 
} 


class ProjectWizard(SessionWizardView): 
    instance = None 

    def get_form_instance(self, step): 
     """ 
     Provides us with an instance of the Project Model to save on completion 
     """ 
     if self.instance is None: 
      self.instance = Project() 
     return self.instance 

    def done(self, form_list, **kwargs): 
     """ 
     Save info to the DB 
     """ 
     project = self.instance 
     project.save() 

    def get_template_names(self): 
     """ 
     Custom templates for the different steps 
     """ 
     return [TEMPLATES[self.steps.current]] 

urls.py

FORMS = [ 
    ('project_essentials', ProjectEssentialsForm), 
    ('project_your_info', ProjectYourInfoForm), 
] 

urlpatterns = patterns('', 
    (r'^projects/add$', ProjectWizard.as_view(FORMS)), 
) 

widzę że istnieje ta funkcja https://docs.djangoproject.com/en/dev/ref/contrib/formtools/form-wizard/#django.contrib.formtools.wizard.views.WizardView.get_form_instance do ustawiania instancji formularza, ale nie jestem pewien, w jaki sposób chciałbyś uzyskać identyfikator modeli, aby wykonać tu wyszukiwanie i dokładnie w jaki sposób kod będzie działał.

Przykład kodu lub link do jednego byłby najbardziej doceniony.

Dzięki Pete

Odpowiedz

10

Mam tylko ten działa więc pisać odpowiedź w przypadku pomaga ktoś inny.

można przekazać identyfikator elementu, który chcesz edytować w urls.py tak:

(r'^projects/edit/(?P<project_id>[-\d]+)$', ProjectWizard.as_view(FORMS)), 

Następnie można spojrzeć na rzecz z następującego kodu w

views.py :

class ProjectWizard(SessionWizardView): 
    def get_form_initial(self, step): 
     if 'project_id' in self.kwargs and step == 'project_essentials': 
      project_id = self.kwargs['project_id'] 
      project = Project.objects.get(id=project_id) 
      from django.forms.models import model_to_dict 
      project_dict = model_to_dict(project) 
      return project_dict 
     else: 
      return self.initial_dict.get(step, {}) 

Musisz przekonwertować model na dyktando, aby można było ustawić go jako dane początkowe.

+0

Próbuję wprowadzić kreatorów formularzy, utknąłem z problemem. Czy możesz pomóc: tutaj jest post: http://stackoverflow.com/questions/24173367/form-wizard-initial-data-for-edit-not-loading-properly-in-django –

+0

Jestem w stanie załadować początkowe dane na pierwszym formularzu, ale po przesłaniu pierwszego formularza, kieruje on do stworzenia adresu URL np. z:/Item/edit/1 do/Item/create po kliknięciu submit –

1

Dodawanie do odpowiedzi pxg, w get_form_instance powinno być tak, inaczej nie będzie edycję modelu lecz utworzyć nową instancję nim: Odpowiedź

def get_form_instance(self, step): 
    if not self.instance: 
     if 'initial_id' in self.kwargs: 
      initial_id = self.kwargs['initial_id'] 
      self.instance = Project.objects.get(id=initial_id) 
     else: 
      self.instance = Project() 

    return self.instance 
2

pxg jest niewystarczająca. Jak zauważył emin-buğra-saral, tworzy on nową instancję modelu zamiast go edytować. A odpowiedź emin-buğra-saral sama w sobie nie wystarcza. Nie należy zastępować metody get_form_initial i nie należy ustawiać wartości initial_dict ani używać implementacji podanej w tej odpowiedzi. W ten sposób należy połączyć swoje odpowiedzi:

w urls.py:

(r'^projects/edit/(?P<project_id>[-\d]+)$', ProjectWizard.as_view(FORMS)),

w views.py:

class ProjectWizard(SessionWizardView): 
    def get_form_initial(self, step): 
     if 'project_id' in self.kwargs: 
      return {} 
     return self.initial_dict.get(step, {}) 

    def get_form_instance(self, step): 
     if not self.instance: 
      if 'project_id' in self.kwargs: 
       project_id = self.kwargs['project_id'] 
       self.instance = Project.objects.get(id=project_id) 
      else: 
       self.instance = Project() 
     return self.instance 

Choć wersja pxg z dnia get_form_initial faktycznie działa (tak długo, jak dodajesz zmienne get_form_instance), nie jest konieczne wyszukiwanie instancji, wyodrębnianie jej danych i tworzenie początkowej wartości Słownik e. Wszystko to odbywa się automatycznie przez ModelForm przed zainicjowaniem instancji z initial_dict.Zwracając pusty słownik początkowej wartości będziesz mieć prostszy, bardziej efektywny kod.

+0

Jakiej wersji Django używasz? Podejrzewałem, że to mogło się zmienić w nowszych wersjach, kiedy korzystałem z tego problemu, używałem Django 1.4.2. Z przyjemnością wypróbuję Twoje rozwiązanie i zaktualizuję moją odpowiedź, jeśli moja odpowiedź jest już nieaktualna. Oczywiście nie wykluczam również możliwości twojego rozwiązania w pracy z wersją 1.4.2, niezależnie od tego, czy zaktualizuję swoją odpowiedź, jeśli Twoje rozwiązanie działa. – pxg

+0

Używam Django 1.4.16 – nmgeek

0

Musiałem to trochę zmodyfikować, aby działało w Django 1.11 z django-formtools 2.1.

class ProjectWizard(SessionWizardView): 
    def get_form_initial(self, step): 
     if 'project_id' in self.kwargs: 
      return {} 
     return self.initial_dict.get(step, {}) 

    def get_form_instance(self, step): 
     if not self.instance_dict: 
      if 'project_id' in self.kwargs: 
       project_id = self.kwargs['project_id'] 
       return Project.objects.get(id=project_id) 
     return None 

Sposób get_form_instance teraz oczekuje either an object or None to be returned.

Powiązane problemy