crispo12
crispo12

Reputation: 21

Send Form back and from two views in Django

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

Preview HTML

{% 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 %}

New Entry HTML


{% 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 %}

Views for Preview and New HTML

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

Answers (1)

moddayjob
moddayjob

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

Related Questions