Reputation: 21
I am making a project that involves users being able to write inside a Form and then save it as a markdown file. I need to find a way to show the user how does the markdown he is currently writing would look already once parsed; this would be shown on a separate static page with a return button to go back to writing.
This last part is giving me problems since I manage to show the user how his file would look like yet I haven't been able to find a way to render it back to the original entry form where it came from
{% extends "encyclopedia/layout.html" %}
{% block title %}
Encyclopedia
{% endblock %}
{% block body %}
<h1>Preview</h1>
<h3>{{title}}</h3>
<hr>
{{preview|safe}}
<form action="{% url 'new_entry' %}" method="POST">
{% csrf_token %}
<input type="submit" name="return" value="Return">
</form>
{% endblock %}
{% block title %}
Encyclopedia
{% endblock %}
{% block body %}
<h1>New Entry</h1>
<div class="form-group">
<form action="{% url 'new_entry' %} " method="POST">
{{form.as_table}}
{% csrf_token %}
<input type="submit" value="Save" name="submit">
<input type="submit" value="Preview" name="preview">
</form>
</div>
{% endblock %}
def preview(request):
#Retrieve data from the request
form = EntryForm(request.POST)
if form.is_valid():
title = form.cleaned_data['title']
body = form.cleaned_data['body']
# Nonfunctioning part
#It's supposed to return the request to the original function
#and letting it know that it has to pre-populate the form
if 'return' in request.POST:
return new_entry(request, fill_form=True)
#Render the contents of the form
return render(request, "encyclopedia/entry_preview.html",
{"title":title,"preview":body})
def new_entry(request, fill_form = False):
#Non functioning part
#Supposedly should get the request that the view 'preview'
#recieved and get the form from there
form = EntryForm()
if fill_form is True:
form = EntryForm(request.POST)
if form.is_valid():
title = form.cleaned_data['title']
body = form.cleaned_data['body']
#If form returned submit then save the file
if 'submit' in request.POST:
util.save_entry(title,body)
return redirect(reverse('new_entry'))
#If form returned preview then call function to display
#users input rendered correctly
elif 'preview' in request.POST:
#Pass the POST request to this other function
return preview(request)
#Else just render an empty form
else:
return render(request,'encyclopedia/new_entry.html',
{'form':form})
The Form is based on a Model, it just contains two basic fields, title
and body
.
Either way is open to other ideas to deal with this, my problem is mostly that when the function preview
is called, it renders the passed values but now the passed parameters are gone, and am unable to return to the new_entry
view.
Also, I thought of passing data through the URL but the body could be thousands of words long.
Upvotes: 0
Views: 642
Reputation: 708
Following up with the comments, I will briefly explain one way of tackling this problem. For this task I would use a very tiny django library called django_htmx. Just take a look at the usage of htmx and in less than ten minutes you will be ready to implement it with ease. Your form will look something like this:
<form action="{% url 'new_entry' %}"
data-hx-post="{% url 'new_entry' %}"
data-hx-target="#your-container-id"
data-hx-swap="innerHTML"
method="POST">
{{form.as_table}}
{% csrf_token %}
<input type="submit" value="Save" name="submit">
<input type="submit" value="Preview" name="
</form>
data-hx-post
specifies the url to post this form via ajax. And data-hx-target
specifies the container where the response from the ajax request will be inserted into. data-hx-swap
tells htmx to insert the response into that container.
Put your encyclopedia/entry_preview.html
template in an include block. And include it in the same page as the form. Don't forget to give the container element an ID so that you can target it in htmx with data-hx-target
.
In your view function, you can say:
def new_entry(request, fill_form = False):
if request.method == "POST":
if request.htmx:
# The request is made with htmx ajax call...
# So we render only one side of the page. The display side.
return render(request, "encyclopedia/entry_preview.html",
{"title":title,"preview":body})
else:
#render the page normally here. both with form and with preview container.
Give it a go and ask if you are stuck. You will have a nice dynamic markdown editing page.
PS: You can use data-hx-trigger
to make it so that it updates even while typing. exactly like Stackoverflow. :)
Upvotes: 1