Redirecting into another page in Django - html

I am working in a project in Django where someone tries to fill the info of some patients and after hitting the submit button i would like o redirect it into a page with the list of all the existing patients, i am trying using a action tag in the html but it seems not to work, i would like to know what i am doing wrong.
html
{%extends 'base.html'%}
{%load staticfiles%}
{%block body_block%}
<link rel="stylesheet" href="{%static 'patients/css/patientform.css'%}">
<form action="{% url 'patients'%}" method="POST">
<div class="wrapper">
{%csrf_token%}
<div class="Patient">
<h3>Informacion del Paciente</h3>
{{patientinfo.as_p}}
</div>
<div class="Medical">
<h3>Informacion Medica</h3>
{{medicalinfo.as_p}}
</div>
<div class="Insurance">
<h3>Informacion de Seguro</h3>
{{insuranceinfo.as_p}}
</div>
<div class="FirstRelative">
<h3>Antecedentes Familiares</h3>
<h5>Primer Caso</h5>
{{first_relative.as_p}}
<h5>Segundo Caso</h5>
{{second_relative.as_p}}
</div>
</div>
<input id="submit" type="submit" value="Agregar">
</form>
{%endblock%}
Url patterns
from django.urls import path
from .views import *
urlpatterns = [
path('',PatientsList.as_view(),name='patients'),
path('addpatient',PatientFormView,name='addpatient'),
]

Redirection should be made after Post request retrieval in your views.py
# AT POST REQUEST END
return redirect("patients")
Django Docs:
https://docs.djangoproject.com/en/3.0/topics/http/shortcuts/#redirect

In the end of your PatientFormView you should redirect with use of:
return redirect("patients")
For more details check Django documentation: docs.djangoproject.com/en/3.0/topics/http/shortcuts/#redirect

Related

Getting Django CSRF error with raw html form

I'm trying to set up a raw html form where a user can make a suggestion and then save it on a database with a POST method, but I keep getting a Forbidden (403) CSRF verification failed. Request aborted. even after following the steps in the Help section.
I have found that I don't get the error if I add csrf_exempt on top of my view like this:
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def suggest_ptags(request):
context = {}
print("Form is submitted.")
return render(request, "partials/search_form.html", context)
But I was made aware that It removes completly the CSRF protection and I don't want that.
So what should I do?
Here's my search_form.html form in a partials folder in templates:
<!-- Suggestion Form in popup -->
<div class="prop-modal">
<div class="prop-content">
<a class="btn-close-prop">×</a>
<img src="{% static 'images/pyramids.svg' %}">
<form action="/suggest_ptags/" class="feedback-form" method="POST" enctype="text/plain">
{% csrf_token %}
<h5 class="title-prop">Suggestion</h5>
<input class="input-prop" name="suggest" rows="3" cols="37" placeholder="suggest something..."></input>
<input class="button-prop" type="submit" value="Envoyez"></input>
</form>
</div>
</div>
My current Views.py:
from django.views.decorators.csrf import ensure_csrf_cookie
#ensure_csrf_cookie
def suggest_ptags(request):
context = {}
print("Form is submitted.")
return render(request, "partials/search_form.html", context)
And in my Urls:
from django.conf.urls import url
from django.contrib import admin
from search.views import HomeView, ProductView, FacetedSearchView, autocomplete, suggest_ptags
from .settings import MEDIA_ROOT, MEDIA_URL
from django.conf.urls.static import static
urlpatterns = [
url(r'^$', HomeView.as_view(), name='home'),
url(r'^admin/', admin.site.urls),
url(r'^suggest_ptags/$', suggest_ptags, name='suggest_ptags'), #Suggestions
url(r'^product/(?P<slug>[\w-]+)/$', ProductView.as_view(), name='product'),
url(r'^search/autocomplete/$', autocomplete),
url(r'^search/', FacetedSearchView.as_view(), name='haystack_search'),
] + static(MEDIA_URL, document_root=MEDIA_ROOT)
Any solutions?
You shouldn't use enctype="text/plain". You can remove it (which is the same as enctype="multipart/form-data"), or use enctype="multipart/form-data" if you are uploading files.

HTML how to structure form-groups and bootstrap classes to catch single form data, pass to Python Flask

I have a "GET" / "POST" split on my html page courtesy of a python flask script:
def home(name=None):
if request.method == "GET":
return render_template('home.html', name=name)
if request.method == "POST":
files = request.form["file[]"]
do things with the files
On my home.html page, I have added in some bootstrap code to make everything pretty, but the flask module is now not taking in the form data properly. Here's my html code:
<form id="uploadbanner" enctype="multipart/form-data" method="post" action="{{ url_for('home') }}">
<div class="form-group">
<div class="container">
<div class="page-header">
<br>
<h1>Title</h1>
<br>
<br>
</div>
<div class="row">
<div class="col-lg-6 col-md-6 col-s-6 col-xs-12">
<h4>File Control</h4>
<div class="jumbotron">
And my form data is here:
<input type="file" name="file[]" id="inputnameid" multiple=""/>
</div>
</div>
Second Column
</div>
New Row, etc etc
Each new row has buttons and inputs that I want to match with the form data using the name field.
I know I'm not structuring this properly, but I can't seem to find any info on how to mesh bootstrap and forms.
I think in order to get the files, you should use request.files["file[]"] instead of request.form["file[]"] .

Populating multiple plotly offline plots<div> of HTML page using flask

I am trying to embed multiple plotly offline plots into an HTML page at different locations on the page. I am using flask at the back-end. Currently I am unable to change the properties of the returned by plotly offline plot to change the location, width, height on the HTML page. I am new to the front-end development concept so pardon my ignorance.
I am using the below test code to create div plot.
from plotly.offline import plot
import plotly.graph_objs as go
def plot_test():
months = ['Jan', 'Feb', 'Mar']
user = [10,50,30]
t20h = [17, 46, 39]
trace1 = go.Scatter(x= months, y=user, mode='lines+markers', name="OHR")
trace2 = go.Scatter(x= months, y=t20h, mode='lines+markers', name="T20H")
data = [trace1, trace2]
layout = go.Layout(title='Test', xaxis=dict(title='Months'), yaxis=dict(title='Test'))
fig = go.Figure(data=data, layout=layout)
div_output = plot(fig, output_type='div', include_plotlyjs=False)
return div
And below code to render the results in my HTML
from plot_test import plot_test
#app.route('/')
def home():
plotly_graph = plot_test()
return render_template("index.html", plotly_graph=Markup(plotly_graph))
And below is my HTML. Currently the plot gets crated but at the top of everything else. All my other buttons.
<!DOCTYPE html>
<html>
<head>
<title>Intro</title>
<link href="static/index_style.css" rel="stylesheet">
</head>
<body>
<div id="home">
<form action="/" method="GET">
<input type="submit" class="btn btn-default>" value="HOME" id="home-btn">
</form>
</div>
<div id="logout">
<form action="/logout" method="GET">
<input type="submit" class="btn btn-default>" value="LOGOUT" id="logout-btn">
</form>
</div>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
{{ plotly_graph }}
<!-- errors -->
<!-- {% if error %}
<p class="error"><strong>Error:</strong> {{ error }}</p>
{% endif %}
-->
<!-- messages -->
<!-- {% for message in get_flashed_messages() %}
{{ message }}
{% endfor %} -->
</body>
</html>
I used a slightly different approach :
(simplified)
In my python code, I returned fig instead of the plot itself
In the HTML, I created a div with id( 'div_name'
In Javascript, through the API call received the data to recreate the plot
and then I only had to add Javascript: Plotly.plot("div_name",fig[("data],fig["layout"].
This way you have more flexibility trying out different sizing methods for either your div or the width-height arguments of the layout itself.

Django URL mapping for different apps

Im trying to link a button in HTML to another html in my project folder for my django project. Lets say its
MyApp
-Polls
-templates
-index
-Votes
-templates
-main
-truths
-rigged
I have a a button on main that uses rigged and truths so in main it has this button
<form action="{% url 'Votes:rigged' %}">
<input type="submit" value="rigged votes" />
</form>
now i want to add another button that would link polls->index into it. Is there a way to do that without copying everything from Polls into the folder Votes?
UPDATE*
main.html
<form action="{% url 'Polls:Index' %}">
<input type="submit" value="Index" />
</form>
Polls.url
urlpatterns=[
url(r'^Index/', Index.as_view(), name="Index"),
]
Index.views
class IndexView(TemplateView):
# template location
template_name = "Polls/Index.html"
# post logic must be defined
def post(self, request, *args, **kwargs):
return redirect(reverse_lazy("Polls:Index"))
Please refer to https://docs.djangoproject.com/en/1.10/topics/http/urls/#url-namespaces
Please understand how the namespaces and named urls work. You should have a urls.py file in your 'MyApp' folder where other files like 'settings.py' and 'wigs.py' are there.
For referring to an url by namespaces you need to first register the namespace associated with url.py of your Polls app. Example from the documentation:
from django.conf.urls import include, url
urlpatterns = [
url(r'^polls/', include('polls.urls', namespace='Polls')),
]
Furthermore you must also name your url in 'polls.urls' like
url(r'^index/$', Whatever_view,name='index'),
then you can call the url as "Polls:index"

Uploading to a Django DataBase from a template

I am trying to create a webpage where you can upload questions to the Questions database. I was wondering is there any easy way to do this in Django? Can I upload it so it will be accessible from the Django admin? Here is what I have.
#Models
class Question(models.Model):
question = models.CharField(max_length=400)
answer = models.CharField(max_length=400)
def __unicode__(self):
return self.question + "?"
class QuestionForm(ModelForm):
class Meta:
model = Question
fields = ['question', 'answer']
#Question Template
<div class="container" align="center">
<div class="hero-unit3" align="center">
<h3>
Feel free to post some questions, and a DarKnight representative will answer them for you.
</h3>
</div>
</div>
</div>
<div class="row">
<div class="span6">
<h4>
<form action="<!-- NO IDEA WHAT TO DO -->" method="post">
<input type="text" name="question" />
</div>
</div>
</div>
#views.py
class question(generic.ListView):
template_name = 'users/question.html'
context_object_name = 'Question_list'
def get_queryset(self):
return Question.objects.order_by('question')
The easiest way to achieve what you need is to use CreateView.
In views.py:
from django.views.generic.edit import CreateView
from yourapp.models import Question
class QuestionCreate(CreateView):
model = Question
fields = ['question', 'answer']
Create a new template name question_form.html:
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Create" />
</form>
Hope it helps!
To make a model available to django admin you have to register the model to admin by
from django.contrib import admin
class Question(models.Model):
...
admin.site.register(Question)
Also for doing this from custom template you can use a model form
The form can be displayed in the template as a table or as a paragraph.
Suppose you render the form to the template as f, use it in template as follows
<form action='..' method='post'>
{{ f.as_t }} //or f.as_p for paragraph
</form>