2

I’m finally tormented with the feedback form. As a result, it worked for me, but it only works on a separate page of the project, and I need to implement it in each page of the site so that it is displayed together with the rest of the content. This is not the first time I have encountered such a problem; I cannot display several models on one page at the same time.

How this is implemented in the case of a separate page:

views.py:

def contact(request):
    form_class = ContactForm

    if request.method == 'POST':
        form = form_class(data=request.POST)

        if form.is_valid():
            contact_name = request.POST.get(
                'contact_name'
            , '')
            contact_email = request.POST.get(
                'contact_email'
            , '')
            form_content = request.POST.get('content', '')

            # Email the profile with the
            # contact information
            template = get_template('app/contact/contact_template.txt')
            context = {
                'contact_name': contact_name,
                'contact_email': contact_email,
                'form_content': form_content,
            }
            content = template.render(context)

            email = EmailMessage(
                "New contact form submission",
                content,
                '', ['mail@mailer.com'],
                headers = {'Reply-To': contact_email }
            )
            email.send()
            return redirect('contact')

    return render(request, 'app/contact.html', {
        'form': form_class,
    })

in urls.py:

...
path('contact/', views.contact, name='contact'),
...

contact.html:

<h1>Contact</h1>
<form role="form" action="" method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Submit</button>
</form>

forms.py:

class ContactForm(forms.Form):
    contact_name = forms.CharField(required=True)
    contact_email = forms.EmailField(required=True)
    content = forms.CharField(
        required=True,
        widget=forms.Textarea
    )

    # the new bit we're adding
    def __init__(self, *args, **kwargs):
        super(ContactForm, self).__init__(*args, **kwargs)
        self.fields['contact_name'].label = "Your name:"
        self.fields['contact_email'].label = "Your email:"
        self.fields['content'].label =
            "What do you want to say?"

Maybe there is some better solution for the form to work on every page?

Shan
  • 23
  • 4

3 Answers3

1

Probably you can create custom context_processor for this. Then add this form template in your footer of the base so that this is being rendered in every page. Here is how you can create custom context processor:

# context processor
# assuming it is in path /project/your_app/context_processors.py

def get_footer_context(request):
    form_class = ContactForm()
    return {
        'contact_form': form_class
    }

Then update the context_processors in settings.py:

TEMPLATES = [
    {
        ...
        'OPTIONS': {
            'context_processors': [
                # rest of the context_processors
                'your_app.context_processors.get_footer_context', # <-- Add your context processor
            ],
        },
    },
]

Replace your_app with the app name where the context processor is residing.

Finally, add this code in the footer(or a common template which being rendered everywhere) of base template:

<h1>Contact</h1>
<form role="form" action="{% url 'app_name:contact' %}" method="POST">
    {% csrf_token %}
    {{ contact_form.as_p }}
    <button type="submit">Submit</button>
</form>

Here you need to replace app_name with the app_name value in your urls.

ruddra
  • 50,746
  • 7
  • 78
  • 101
  • I apologize, the problem is that I can make a link in base.html: {% include "blog / _layouts / contact.html"%} but in this case I only see

    and

    – Shan May 22 '20 at 10:37
  • Well, at the end of the page, it redirects to `return redirect('contact')` in `contact` view. Can you send it to somewhere else to see if its working or not? Also I have updated the answer(in templates), please try it – ruddra May 22 '20 at 10:49
  • Sorry, if you know, tell me, please, how instead of redirecting to the contacts page to make an answer inside the page itself, for example via Ajax, so that the Submit button changes and instead of the send inscription the message Sent appears, or in one of the labels. That is, I am interested in the method itself how to specify this redirect, because redirecting to another page in case of successful sending is completely incorrect. – Shan May 22 '20 at 14:08
  • Um, why not you ask a new question regarding this. :) – ruddra May 22 '20 at 14:27
1

In order to get the form into every page in the way you want you need to add the form model to the context on every page. However when the form responds the view that the particular form is on needs to be able to handle that response.

You could include a javascript file in your base template, that makes and Ajax get request to get the form data and then an ajax post request to send the form data back to a method in your views.py. That way you wouldn't have to modify any of your views, but django won't be able to build the form for you in the same way.

Or another approach might be to add the contact form class into the context of the pages you want the form in:

def some_view(request):
    ....
    return render(request, 'some_page.html', context={....., "form": ContactForm},)

Then and the html template into the pages you want to display the contact form, and use the with statement to pass the context from the parent html into the template:

<div>
    {% include "contact.html" with form=form %}
</div>

This won't help you when the form tries to post back because, unless you change the action of the form, it will try to post back to the view with the url that rendered it. So you may want to figure out a way to get the form to post to the url you want to without redirecting the user away from the page the form is on. This might help

Additionally I would think about renaming the variable from form to something like contact_form so you don't confuse it with anything else.

0

Everything seems okay in your django maybe you have some error in HTML code like wrong link or something