I am using a based view class to update an article in my app named article. I am implementing it just like how UpdateView works however i can't seem to make it redirect it after validating the form. I called success_url method to redirect into the detail view, but it doesn't work. Am I missing something?
I set get_absolute_url in models,
#models.py
class Article(models.Model):
def get_absolute_url(self):
return reverse('articles:article-detail', kwargs={"id": self.id})
and in urls
#urls.py
app_name = 'articles'
urlpatterns = [
path('<int:id>/edit/', ArticleUpdateView.as_view(), name='article-edit'),
path('<int:id>/', ArticleDetailView.as_view(), name='article-detail'),
]
and on views:
#views.py
class ArticleUpdateView(View):
template_name = 'articles/article_edit.html'
def get_success_url(self):
id = self.kwargs.get('id')
return reverse('articles:article-detail', kwargs={'id': id})
def get_object(self):
id = self.kwargs.get('id')
obj = None
if id is not None:
obj = get_object_or_404(Article, id=id)
return obj
def get(self, request, id=None, *args, **kwargs):
context = {}
obj = self.get_object()
if obj is not None:
form = ArticleModelForm(instance=obj)
context['article'] = obj
context['form'] = form
return render(request, self.template_name, context)
def post(self, request, id=None, *args, **kwargs):
context = {}
obj = self.get_object()
if obj is not None:
form = ArticleModelForm(request.POST, instance=obj)
if form.is_valid():
form.save()
context['article'] = obj
context['form'] = form
return render(request, self.template_name, context)
I tried using it on UpdateView class and redirect seems to work fine, i'd like to use it on based view class.
CodePudding user response:
The django base View class will not call something like get_success_url()
automatically, that is something that is added in to the functionality of a generic class based view like UpdateView
from another class that it inherits. If you want to redirect in a base View then you will need to actually put in a redirect call.
In your views.py file you can import from django.http import HttpResponseRedirect
and then in your if form.isvalid():
statement in your view you can add in the line return HttpResponseRedirect(self.get_success_url())
. Just calling get_success_url()
does nothing on its own with how you have defined it because the reverse()
shortcut just generates the url based on the name and arguments that you pass into the function.
CodePudding user response:
Chack this, first you need to import reverse_lazy
class ArticleUpdateView(UpdateView):
.....
def get_success_url(self):
return reverse_lazy('article-detail', kwargs={'pk': self.object.pk})
CodePudding user response:
If you are using a form you can proceed the redirection by setting a pull or get method for the form and set the action value to the url you want to redirect directly in your template in html. Here's an exemple :
<form id="contactForm" name="updateArticle" action="{% url 'article-detail' %}" method="post">
{% csrf_token %}
{% for field in form %}
/* Your code */
{% endfor %}
<button type="submit">Update Post</button>
</form>
Then in your ArticleDetailView you can set your post() method to render the details page:
class ArticleDetailsView(View):
template_name = 'articles/article_details.html'
post(self, request, *args, **kwargs):
# Your code
return render(request, self.template_name, context)
You can also use the redirect() method instead of the render(). You can find the documentation here.
CodePudding user response:
from django.views.generic.edit import FormMixin
class ArticleUpdateView(View, FormMixin):
...
FormMixin
contains the magic you seek.