Reputation: 3751
Here I am using CreateView to create item and after that i am redirecting user to update other fields of currently created object.
Here my code:
Views.py
class DynamicCreate(CreateView):
model = Dynamic
form_class = DynamicForm
template_name = 'book/dynamic_create.html'
def form_valid(self, form):
book = form.save(commit=False)
book.user = User.objects.get(pk=(self.request.user.pk))
book.save()
return reverse('book:dynamicupdate', args=(self.object.id))
Urls.py
url(r'^book/create/$', views.DynamicCreate.as_view(), name='dynamiccreate'),
url(r'^book/delete/(?P<pk>[\w]+)/$', views.DynamicDelete.as_view(), name='dynamicdelete'),
url(r'^book/update/(?P<pk>[\w]+)/$', views.DynamicUpdate.as_view(), name='dynamicupdate'),
But Here I am getting error:
Exception Type: AttributeError
Exception Value: 'NoneType' object has no attribute 'id'
I go through other previously asked question like This, But I don't know What I am missing here. My CreateView is able to create/save data in Table but it is not able to redirect me to update View Page.
Upvotes: 4
Views: 4701
Reputation: 141
By defining get_absolute_url
in model you can redirect to "book:dynamicupdate" with pk of created/updated instance.
models.py
from django.db import models
from django.urls import reverse
class Dynamic(models.Model):
...
def get_absolute_url(self):
return reverse("book:dynamicupdate", kwargs={"pk": self.pk})
urls.py
app_name = 'book'
urlpatterns = [
path('/path/<int:pk>/', views.YourUpdateView.as_view(), name='dynamicupdate'),
]
See https://docs.djangoproject.com/en/4.2/topics/class-based-views/generic-editing/#model-forms
Upvotes: 0
Reputation: 691
As explained by solarissmoke 'form_valid' must return a response object not a url!
I would then write:
class DynamicCreate(CreateView):
model = Dynamic
form_class = DynamicForm
template_name = 'book/dynamic_create.html'
success_url = reverse("dynamic_list")
def form_valid(self, form):
# Catch an instance of the object
book = form.save(commit=False)
book.user_id = self.request.user.id
book.save()
self.success_url = reverse('book:dynamic_detail', args=[str(book.id)])
return super(DynamicCreate, self).form_valid(form)
Note: book.user.id = self.request.user.id
instead of the user instance
Even cleaner, add get_absolute_url in model.py
def get_absolute_url(self):
return reverse('dynamic_detail', args=[str(self.id)])
And refer to this function in the view:
class DynamicCreate(CreateView):
model = Dynamic
form_class = DynamicForm
template_name = 'book/dynamic_create.html'
success_url = reverse("book_list")
def form_valid(self, form):
# Catch an instance of the object
book = form.save(commit=False)
book.user_id = self.request.user.id
book.save()
self.success_url = self.model.get_absolute_url(book)
return super(DynamicCreate, self).form_valid(form)
Upvotes: 1
Reputation: 667
The form_valid method inherited from ModelFormMixin includes logic to set self.object to the newly created object, but your overriding method uses the book variable instead. Changing the args to reference book as mentioned above works fine.
Another option would be to replace the book variable with self.object, if only to follow the example set by the default method.
Upvotes: 3
Reputation: 3751
I Fixed it by changing
from return reverse('book:dynamicupdate', args=(self.object.id))
to return redirect('book:dynamicupdate', book.id)
reverse need ViewName not url so i changed reverse
to redirect
and here my object was book so i replaced self.object
with book
Thanks @Daniel Roseman for help
Upvotes: 1
Reputation: 11878
Try changing that line to:
return reverse('book:dynamicupdate', args=(book.id))
self.object is not defined anywhere in your code.
Upvotes: 0