问题
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.
Any suggests?
回答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')
来源:https://stackoverflow.com/questions/44259552/django-updateview-object-to-update-has-no-values