Reputation: 957
I need to have "Preview" button in admin create/edit page. When user clicks on this button, form should be saved and redirects to specific url where user can see information about object he just added or edited.
So I have custom ModelAdmin class with needed for me inline formsets:
class InboundAdmin(admin.ModelAdmin, ListView):
model = Inbound
form = InboundForm
change_form_template = 'admin/tour/inbound_form.html'
inlines = [InboundTourDatesInline, InboundProgramInline, InboundFeedbackInline, InboundMedia,
InboundTourSliderPhotoInline, InboundPriceDynamicsInline]
Template extends admin/change_form.html
.
This template has custom button:
<input type="submit" value="{% trans 'Preview' %}" class="default draft-submit" name="_save_as_draft" />
And this script which:
$('.draft-submit').on('click', function(){
$.ajax({
type: "POST",
url: "{% url 'tours:inbound_draft' %}",
data: $("#{{ opts.model_name }}_form").serialize()
});
});
This is inbound_draft
view:
def draft_inbounds(request):
print('inbounds')
form = InboundForm(request.POST or None, request.FILES or None)
if form.is_valid():
print('is_valid')
form.save()
# Here I should return specific url with pk as an attribute.
print('not_valid')
Problem is that when I click on Preview button it saves changes but redirects me back to the list_view in admin. What is the right way to solve my problem?
Upvotes: 2
Views: 2472
Reputation: 957
I have found a nice solution that completely solves my problem.
All you need is to override save_model()
, response_change()
and response_add()
methods of ModelAdmin class.
Here is my class in admin.py file:
class InboundAdmin(admin.ModelAdmin, ListView):
model = Inbound
form = InboundForm
change_form_template = 'admin/tour/inbound_form.html'
inlines = [InboundTourDatesInline, InboundProgramInline, InboundFeedbackInline, InboundMedia,
InboundTourSliderPhotoInline, InboundPriceDynamicsInline]
def save_model(self, request, obj, form, change):
if "_draft" in request.POST:
obj.published = False # If it is a draft, then post should not be published
else:
obj.published = True
super(InboundAdmin, self).save_model(request, obj, form, change)
def response_change(self, request, obj):
if "_draft" in request.POST:
return HttpResponseRedirect(reverse_lazy("tours:inbound_detail", kwargs={'pk': obj.pk}))
else:
return super(InboundAdmin, self).response_change(request, obj)
def response_add(self, request, obj, post_url_continue=None):
if "_draft" in request.POST:
return HttpResponseRedirect(reverse_lazy("tours:inbound_detail", kwargs={'pk': obj.pk}))
else:
return super(InboundAdmin, self).response_add(request, obj, post_url_continue=None)
If request contains "_draft"
then I redirect to needed url, else It uses default method.
In your template you should add button for savins as a draft:
<input type="submit" value="{% trans 'Save as a draft' %}" class="default draft-submit" name="_draft" />
That's all)
Upvotes: 2
Reputation: 5993
As you made your button the submit
input, it submits the form, therefore redirecting you to the changelist. To make that button "js-only", change its type:
<input type="button" value="{% trans 'Preview' %}" class="default draft-submit" name="_save_as_draft" />
Alternatively you could prevent the form submission via JS:
$('.draft-submit').on('click', function(event){
event.preventDefault();
// the rest of your code
});
Upvotes: 1