This is my updateview which is called by a URL with slug field, e.g.
/mymodel/update/<model_name_slug>/
MyModel
have two fields, name
and slug
. The slug field <model_name_slug>
is automatically generated from MyModel.name
. If the user update it, a new slug field will be automatically generated. Then, I want to redirect to this new URL with the newly generated slug field.
The slug field auto-generation is working. It is implemented in the MyModelEditForm
. However, the code below won't work. The reason is:
1) User typed this URL to update the existing model
/mymodel/update/example-model
2) User changes the Name attribute to "example model changed"
. Then slug field will be generated as "example-model-changed"
in MyModel
.
3) But the URL is not redirected to the "/mymodel/update/example-model-changed"
, as get_object()
will return None. get()
will not be able to compare the newly generated URL "example-model-changed"
with original "example-model"
What am I missing in below code? I tried to access the newly update object using self.object
, but have following error:
MyModelUpdateView object has no attribute 'object'
Here is the code snippet:
class MyModelUpdateView(LoginRequiredMixin, UpdateView):
model = MyModel
form_class = MyModelUpdateForm
template_name = 'mymodel/update_mymodel.html'
def get_success_url(self):
view_name = 'update_mymodel'
return reverse_lazy(view_name, kwargs={'model_name_slug': self.kwargs.get('model_name_slug','')})
def get_form_kwargs(self):
'''
This injects form with keyword arguments.
'''
kwargs = super(MyModelUpdateView, self).get_form_kwargs()
#Update the kwargs with the user_id
kwargs['user'] = self.request.user
return kwargs
def get(self, request, *args, **kwargs):
# self.object = self.get_object()
if self.request.path != self.object.get_absolute_url():
return HttpResponseRedirect(self.object.get_absolute_url())
else:
return super(MyModelUpdateView, self).get(request,*args, **kwargs)
# context = self.get_context_data(object=self.object)
# return self.render_to_response(context)
def get_object(self, queryset=None):
instance = MyModel.objects.get(slug=self.kwargs.get('model_name_slug',''))
return instance
Even if the get_success_url() is correctly updated, the get_object() seems to have two conflicting requirements: 1) Be able to fetch the correct object using existing "example-model" slug field; 2) Be able to fetch the updated object using newly generated "example-model-changed" before the existing URL is not redirected.
You don't have to use self.get_object
in the get_success_url
method. The form_valid()
sets self.object
when saving the form, so you can use self.object.slug
to get the new url.
def get_success_url(self):
view_name = 'update_mymodel'
# No need for reverse_lazy here, because it's called inside the method
return reverse(view_name, kwargs={'model_name_slug': self.object.slug})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With