0

I'd like to update an object with generic view updateview. The problem arises when I edit an object. Instead of reaching a prefilled form, I reach a blank form.
My template for this:

    {% extends 'base.html' %}
    {% block content %}
    <div class="container">
    <form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <input class="btn btn-danger" type="submit" value="Update" />
    <a  href="{% url 'display_targetbehavior' %}" class="btn btn-default">Take me back</a>
    </form>
    </div>
    {% endblock %}

In my views.py

class HabitUpdate(UpdateView):
    model = Habit
    form_class = HabitForm
    #fields = ('title', 'trigger', 'existingroutine', 'targetbehavior', 'image')
    success_url = reverse_lazy('display_habits')
    template_name = 'habits/update_habit.html'

my model:

class Habit(models.Model):
    AFTER = 'After I'
    WHEN = 'When I'
    WHENEVER = 'Whenever I'
    BEFORE = 'Before I'
    MEANWHILE = 'Meanwhile I'

    TRIGGER_CHOICES = (
      (AFTER, 'After I'),
      (WHEN, 'When I'),
      (WHENEVER, 'Whenever I'),
      (BEFORE, 'Before I'),
      (MEANWHILE, 'Meanwhile I'),
    )

    title = models.CharField(max_length=200)
    trigger = models.CharField(max_length=15, choices=TRIGGER_CHOICES, default=AFTER)
    existingroutine = models.ForeignKey(
      'Existingroutine',
      on_delete=models.SET_NULL,
      blank=True,
      null = True,
    )
    targetbehavior = models.ForeignKey(
      'Targetbehavior',
      on_delete=models.SET_NULL,
      blank=True,
      null = True,
    )

    image = models.ImageField(upload_to='habit_image', blank=True)

    created_by = models.ForeignKey(UserProfile, on_delete=models.SET_NULL, null=True)


    created_at = models.DateTimeField(default=datetime.now, blank=True)

    def __str__(self):
         habitpresentation = self.title# + '\n ' + self.trigger + '\n ' + str(self.existingroutine) + '\n ' + str(self.targetbehavior)
    return habitpresentation

    def image_url(self):
        #print(self.image.url)
        if self.image and hasattr(self.image, 'url'):
            return self.image.url
        else:
            return None;

..and in my forms.py

class HabitForm(forms.ModelForm):
    class Meta:
        model = Habit
        fields = ( 'title', 'trigger', 'existingroutine', 'targetbehavior', 'image')


    def save(self, commit=True):
        habit = super(HabitForm, self).save(commit=False)
        habit.title = self.cleaned_data['title']
        habit.trigger = self.cleaned_data['trigger']
        habit.existingroutine = self.cleaned_data['existingroutine']
        habit.targetbehavior = self.cleaned_data['targetbehavior']
        habit.image = self.cleaned_data['image']

        if commit:
            habit.save()

EDIT urls.py:

from django.conf.urls import include, url

from habits import views as habits_views

urlpatterns = [
    url(r'^$', habits_views.display_habits, name='display_habits'),
    url(r'^habit/details/(?P<id>\w{0,50})/$', habits_views.display_habit_details, name='display_habit_details'),
    url(r'^habit/details/(?P<id>\w{0,50})/delete/$', habits_views.delete_habit, name='delete_habit'),
    #url(r'^habit/details/update/(?P<id>\w{0,50})/$', habits_views.update_habit, name='update_habit'),
    url(r'^habit/details/update/(?P<pk>\w{0,50})/$', habits_views.HabitUpdate.as_view(), name='update_habit'),
    url(r'^habit/create-habit/$', habits_views.create_habit, name='create_habit'),
    url(r'^existingroutines/$', habits_views.display_existing_routines, name='display_existing_routines'),
    url(r'^existingroutines/create/$', habits_views.create_existing_routine, name='create_existing_routine'),
    url(r'^existingroutines/select/(?P<id>\w{0,50})/$', habits_views.select_existing_routine, name='select_existing_routine'),
    url(r'^existingroutines/update/(?P<pk>\w{0,50})/$', habits_views.ExistingroutineUpdate.as_view(), name='update_existing_routine'),
    url(r'^existingroutines/delete/(?P<pk>\w{0,50})/$', habits_views.ExistingroutineDelete.as_view(), name='delete_existing_routine'),
    url(r'^targetbehavior/$', habits_views.display_targetbehavior, name='display_targetbehavior'),
    url(r'^targetbehavior/create/$', habits_views.create_targetbehavior, name='create_targetbehavior'),
    url(r'^targetbehavior/select/(?P<id>\w{0,50})/$', habits_views.select_targetbehavior, name='select_targetbehavior'),
    url(r'^targetbehavior/update/(?P<pk>\w{0,50})/$', habits_views.TargetbehaviorUpdate.as_view(), name='update_targetbehavior'),
    url(r'^targetbehavior/delete/(?P<pk>\w{0,50})/$', habits_views.TargetbehaviorDelete.as_view(), name='delete_targetbehavior'),
]

With this url I'm going to update the habit:

url(r'^habit/details/update/(?P<pk>\w{0,50})/$', habits_views.HabitUpdate.as_view(), name='update_habit'),

EDIT get_object delivers object. enter image description here

Any suggests?

Texas
  • 559
  • 2
  • 6
  • 18
  • Your `save` method is pointless, but that is not the cause of your problem. Can you post your urls, and show which URL you are going to to display the form? – Daniel Roseman May 30 '17 at 10:31

1 Answers1

1

I think your UpdateView is not returning the right object for your template. Have you tried this:

class HabitUpdate(UpdateView):
    model = Habit
    form_class = HabitForm
    template_name = 'habits/update_habit.html'
    success_url = reverse_lazy('display_habits')

    def get_initial(self):
        initial = super(HabitUpdate, self).get_initial()
        print('initial data', initial)

        # retrieve current object
        habit_object = self.get_object()

        initial['field1'] = habit_object.field1
        initial['field2'] = habit_object.field2
        ....
        ....
        return initial


    def get_object(self, *args, **kwargs):
        habit = get_object_or_404(Habit, pk=self.kwargs['pk'])

        return habit

And you only need this in your forms.py file:

class HabitForm(forms.ModelForm):
    class Meta:
        model = Habit
        fields = ( 'title', 'trigger', 'existingroutine', 'targetbehavior', 'image')
Nathan
  • 449
  • 1
  • 7
  • 23
Sijan Bhandari
  • 2,941
  • 3
  • 23
  • 36
  • Great.Glad that it helps you out. – Sijan Bhandari May 30 '17 at 10:58
  • Okay, sry I was a bit overhasty. It seems that pretty rare the form is filled with the right values. And most of the case values are not populated and the form fields are blank. Rare means 2 times were given the right values of perceived 100 trys/refreshs. get_object gets the right object/habit. So whats wrong with them? – Texas May 30 '17 at 11:12
  • Can you try override ```get_initial``` method and load the initial object like above? For each object, the get_initial will be called and there should be data for that object. – Sijan Bhandari May 30 '17 at 11:28
  • Are you sure there is data in the database for that particular object? Have you checked in `shell` ? – Sijan Bhandari May 30 '17 at 11:39
  • My url http://localhost:8000/overview/habit/details/update/3/ implicit that pk=self.kwargs['pk'] --> pk = 3 (already tested). Edit question above contains screenshot of db. – Texas May 30 '17 at 11:48
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/145453/discussion-between-sijan-bhandari-and-texas). – Sijan Bhandari May 30 '17 at 11:57