Reputation: 2336
As a newcomer to Django, I'm struggling to achieve my ultimate aim of submitting a form to the same page on which it's defined and displaying values entered in the form within text elements of an SVG diagram, displayed below the form.
Thus far, I've managed to create a form using a CreateView
and can submit the contents of that form to a separate view which displays the entered values in SVG format...
models.py
class Diagram(models.Model):
val1 = models.FloatField(null=True, blank=True, default=None)
val2 = models.FloatField(null=True, blank=True, default=None)
def get_absolute_url(self):
return reverse('diagram-results', kwargs={'diagram_id': self.pk})
forms.py
class DiagramForm(ModelForm):
class Meta:
model = Diagram
fields = ['val1', 'val2']
views.py
def show(request, diagram_id):
try:
diagram = Diagram.objects.get(pk=diagram_id)
except Diagram.DoesNotExist:
raise Http404("Diagram does not exist")
return render(request, 'calc_app/diagram.svg', {'diagram': diagram})
class DiagramCreateView(CreateView):
model = Diagram
form_class = DiagramForm
urls.py
urlpatterns = [
path('diagram/add/', DiagramCreateView.as_view(), name='diagram-add'),
path('diagram/<int:diagram_id>/', views.show, name='diagram-results'),
]
diagram_form.html
{% extends "calc_app/base_generic.html" %}
{% block content %}
<form action="." method="post">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Submit">
</form>
{% endblock %}
diagram.svg
<svg width="800" height="600" xmlns="http://www.w3.org/2000/svg">
<text id="val1" stroke="#ddd" y="50.0" x="50.0">{{ diagram.val1 }}</text>
<text id="val2" stroke="#ddd" y="50.0" x="50.0">{{ diagram.val2 }}</text>
</svg>
I'd like to take this one step further and submit the entered form values back to the same page (rather than a separate page/view) and show the results within the SVG diagram. It's straightforward enough to combine the HTML form and SVG diagram into a single template by including the following line immediately below the closing form tag in the diagram_form.html template...
{% include "calc_app/diagram.svg" %}
What I'm struggling to do is post the form contents back to the page it originated from. Can anyone shed any light on how best to do this using the aforementioned building blocks (or more appropriate ones)?
Many thanks in advance.
Upvotes: 0
Views: 270
Reputation: 88589
Initially, update your diagram_form.html
file as below, to handle the svg
image
{% extends "calc_app/base_generic.html" %}
{% block content %}
<form action="." method="post">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Submit">
</form>
{% endblock %}
<div>
{% include "calc_app/diagram.svg" %}
</div>
Note that, I have used the include
--[Doc] template tag of Django here to re-use the diagram.svg
Then, update the DiagramCreateView
class by overriding the form_valid(...)
and get_context_data(...)
method and also updating the value of template_name
attribute
class DiagramCreateView(CreateView):
model = Diagram
form_class = DiagramForm
template_name = "sample/diagram_form.html"
def form_valid(self, form):
self.object = form.save()
return render(
request=self.request,
template_name=self.template_name,
context=self.get_context_data()
)
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
ctx["diagram"] = self.object
return ctx
In the end, this would result in a below setup,
Upvotes: 1
Reputation: 783
Modify create view by overriding post method, as following lines of code,
class DiagramCreateView(CreateView):
model = Diagram
form_class = DiagramForm
def post(self, request, *args, **kwargs):
super().post(request,*args,**kwargs)
form = DiagramForm(request.POST)
return render(request,'calc_app/diagram_form.html',{'form':form,'diagram':self.object})
Upvotes: 1