Django form not rendering properly - python

I am following the documentation of the Django Forms but I do not know why my form does not want to show up !
I am creating a form that will get an email en create invitation for user to sign in using this app :https://github.com/bee-keeper/django-invitations
My forms.py:
class InviteForm(forms.Form):
email1 = forms.EmailField(label='Email 1')
My Views.py:
from django.shortcuts import render
from django.views.generic import TemplateView
from .forms import InviteForm
class candidateIndex(TemplateView):
template_name= 'candidateIndex.html'
class HRIndex(TemplateView):
template_name= 'HRindex.html'
def create_invite(request):
if request.method == 'POST':
form = InviteForm(request.POST)
if form.is_valid:
email = form.cleaned_data['email1']
invite = Invitation.create('form.email1')
invite.send_invitation(request)
print("The mail was went")
else:
print("Your form is not valid")
else:
form = InviteForm()
return render(request, 'HRindex.html', {'form': form})
My HTML:
{% extends 'base.html' %}
{% block body %}
<div class="jumbotron">
<h1>Welcome to SoftScores.com</h1>
<h2>Team analytics platfom</h2>
<h3>Welcome to {{user.username}}, it is your Page</h3>
</div>
<div class="container">
<p>
<a class="btn btn-primary" data-toggle="collapse" href="#collapseExample" aria-expanded="false" aria-controls="collapseExample">
Create a new team
</a>
</p>
<div class="collapse" id="collapseExample">
<div class="card card-body">
In order to create a new team please invite new members. A link will be sent to them in order to give the access to the application
</div>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
</div>
</div>
urls.py:
from django.conf.urls import url
from website import views
app_name = 'website'
urlpatterns = [
url(r'^candidateIndex/$', views.candidateIndex.as_view(), name='candidate_index'),
url(r'^HRIndex/$', views.HRIndex.as_view(), name='HR_index'),
]
When it render the page I get only the button but the form does not seems to work
Do you habe any idea ?

You HR_index url is being handled by the HRIndex view, but this does not have any code to handle the form.
url(r'^HRIndex/$', views.HRIndex.as_view(), name='HR_index'),
Since a TemplateView is not really suited to handling a form, it would be better to modify the URL pattern to use the create_invite view instead:
url(r'^HRIndex/$', views.create_invite, name='HR_index'),

Related

Django - show bootstrap modal after successful save data to db

I'm new to Django and at this point , I set up a very simple post article page, I hope that when I successfully save the article, it will show the message of the bootstrap modal style.
model.py
from django.db import models
from django.utils import timezone
class Article(models.Model):
title = models.CharField(max_length=100,blank=False,null=False)
slug = models.SlugField()
content = models.TextField()
cuser = models.CharField(max_length=100)
cdate = models.DateField(auto_now_add=True)
mdate = models.DateField(auto_now=True)
forms.py
from .models import Article
from django.forms import ModelForm
class ArticleModelForm(ModelForm):
class Meta:
model = Article
fields = [
'title',
'content',
]
views.py
from django.shortcuts import render
from .forms import ArticleModelForm
from django.contrib.auth.decorators import login_required
from .models import Article
#login_required
def create_view(request):
form = ArticleModelForm(request.POST or None)
context={
'form':form
}
if form.is_valid():
article_obj = Article(cuser=request.user)
form = ArticleModelForm(request.POST,instance=article_obj)
form.save()
context['saved']=True
context['form']=ArticleModelForm()
return render(request,'article/create.html',context= context)
my template > article/create.html
{% extends 'base.html' %}
{% block content %}
<form method="POST">
{% csrf_token %}
{{form.as_p}}
<div><button data-bs-toggle="modal" data-bs-target="#saveModal" type="submit">create</button></div>
</form>
{% if saved %}
<div class="modal fade" id="saveModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h3>save successfully!</h3>
<button type="button" class="btn-close" data-bs-dismiss="modal">
</button>
</div>
</div>
</div>
</div>
{% endif %}
{% endblock content %}
I use the saved variable in views.py to determine whether the content of the article has been successfully saved, and if so, set it in the context
In the template if saved exists, the modal related code will be presented, but this way
unsuccessful.
The problem is with modal itself, whenever you are submitting the form the form gets submitted but when it comes with saved=True then also there is a need for clicking the button of modal to display the message saved successfully which is not possible. So the other alternative is to use alert classes of boostrap (you are free to apply your own styling to it but below is just an example), so try this template:
<form method="POST">
{% csrf_token %}
{{form.as_p}}
<div><button type="submit">create</button></div>
</form>
{% if saved %}
<div class="alert alert-success alert-dismissible fade show" role="alert">
<strong>Saved successfully.</strong>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
{% endif %}
You should maintain separate conditions for GET and POST request and also do re-render the template with saved=True so try this view:
#login_required
def create_view(request):
if request.method == "POST":
article_obj = Article(cuser=request.user)
form = ArticleModelForm(request.POST, instance=article_obj)
if form.is_valid():
form.save()
context = {
"form": ArticleModelForm(),
"saved": "yes"
}
return render(request, "article/create.html", context)
else:
print("form is not valid")
else: # GET method
form = ArticleModelForm()
return render(request, 'article/create.html', {"form": form})

Django - Not passing id from template to views

In my ToDoApp, I couldn't send the ID to my function. Not sure what mistake I'm making.
Seems my function is correct because when I tested the form action with "datechange/1". It worked.
Here is my code:
Index.html
{% extends 'base.html' %}
{% block content %}
<h3 style = "margin-bottom: 20px"><strong>To Do List App</strong></h3>
<form method="POST" action="datechange/{{task.id}}">
{%csrf_token%}
<ul class="list-group">
{% for task in tasklist %}
<li class="list-group-item d-flex justify-content-between align-items-center">
<input type='hidden' name = {{task.id}}>{{task.tasks}}
<span class="badge bg-primary rounded-pill">{{task.duedate}}
<input type="date" name="datepick"/>
<input type='submit' value = 'Update'>
</span>
</li>
{% endfor %}
</form>
Views.py
def index(request):
tasklist = Task.objects.all()
return render(request, 'index.html', {'tasklist':tasklist})
def datechange(request,id):
# taskid = request.POST.get(id='task.id')
# task = Task.objects.get(id=taskid)
task = Task.objects.get(id=id)
datepick = request.POST.get('datepick')
task.duedate = datepick
task.save()
return HttpResponseRedirect(reverse('index'))
Urls.py
from django.contrib import admin
from django.urls import path
from . import views
urlpatterns = [
path('admin/', admin.site.urls),
path('',views.index,name='index'),
path('datechange/<int:id>',views.datechange,name='datechange'),
]
Don't use action in form like that, Django has a better behaviour for such simple forms. The view datechange is also not needed. Just put everything from that view into if request.method == "POST" like that:
def index(request):
if request.method == "POST":
task_id = request.POST.get("task_id")
task = Task.objects.get(id=task_id)
datepick = request.POST.get('datepick')
task.duedate = datepick
task.save()
tasklist = Task.objects.all()
return render(request, 'index.html', {'tasklist':tasklist})
And delete action from your form in template:
<form method="POST">
{%csrf_token%}
<input type="hidden" name="task_id" value="{{ task.id }}">
...
Submitting the form will render index again, but also will process everything in POST you have inside that view. If you just open it (GET method) it will ignore that processing opening the view in a standard way.

Post method in django

I had a tutorial in django with forms and I tried to do exactly what is taught , but I found that either my form in not sending the post method or django can't realize that the request sent is a POST request
here is my file named "register.html":
{% extends "blog/base.html" %}
{% block content %}
<div class="content-section">
<form role="form" method="post">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Join Today</legend>
{{ form.as_p }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Sign Up</button>
</div>
</form>
<div class="border-top pt-3">
<small class="text-muted">
Already Have An Account? <a class="ml-2" href="#">Sign In</a>
</small>
</div>
</div>
{% endblock content %}
and here the django side views.py:
from django.shortcuts import render , redirect
from django.contrib.auth.forms import UserCreationForm
from django.contrib import messages
def register (request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
messages.success(request, f'Account created for {username}!')
return redirect('blog-home')
else:
form = UserCreationForm()
return render(request, 'users/register.html' , {'form': form})
the result is when I click submit , the POST method is not working , I tried to pass a get request and it worked , so the problem only appears when I try to send the POST request , so where is problem ?
In the django's views.py or in the html file ?
Add action url to your form
<form role="form" action="/url/" method="post">
refer this
I agree with #c.grey's comment, If the form has errors, then the view will just return the form with form-data pre-filled and error messages associated with the fields and form (your errors might be not visible due to some CSS).
You can also try to see the execution path using a debugger like pdb or ipdb. for example
import ipdb; ipdb.set_trace()
from django.shortcuts import render , redirect
from django.contrib.auth.forms import UserCreationForm
from django.contrib import messages
def register (request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
username = form.cleaned_data.get('username')
messages.success(request, f'Account created for {username}!')
return redirect('blog-home')
else:
print("Request is not == POST")
return render(request, 'users/register.html' , {'form': form})

Can't display the data entered in form in database

The user enters the data in the form. But the data entered in the form doesn't get displayed in the Database.
views.py
def add(request):
if request.method=='POST':
form=FilesCreate(request.POST)
if form.is_valid():
form.save()
return render(request,'plagiarism/page1.html',{'form':FilesCreate()})
def add2(request):
if request.method=='POST':
form2=FilesCreate2(request.POST)
if form2.is_valid():
form2.save()
return render(request,'plagiarism/page2.html',{'form':FilesCreate2})
models.py
from django.db import models
class File1(models.Model):
#user=models.ForeignKey(User)
firstfile=models.CharField(max_length=1000, default="")
#secondfile=models.CharField(max_length=1000)
def __str__(self):
return self.firstfile
plagiarism/page1.html
<h1>Enter your first file</h1>
<form action="file2/" method="post">
{% csrf_token %}
{% for field in form %}
{{field}}
<input type="submit" value="Submit file1"/>
{% endfor %}
</form>
plagiarism/page2.html (displays page after clicking submit in page 1)
<h1>Enter your second file</h1>
<form action="plagiarism/file2/result/" method="post">
{% csrf_token %}
{% for field in form %}
{{field}}
<input type="submit" value="Get Results"/>
{% endfor %}
</form>
{% block h1 %}
{% endblock %}
<body>
plagiarism/page3.html (displays page after clicking submit in page 2)
<h1> Here is your Result </h1>
<h2>
{{data}}
</h2>
</body>
forms.py
from django.forms import ModelForm
from django import forms
from plagiarism.models import File1,File2
class FilesCreate(ModelForm):
class Meta:
model=File1
exclude=()
widgets={'firstfile':forms.Textarea(attrs={'cols':50,'rows':100})}
example.py
from django.shortcuts import render
def getresult(request):
data=95.5
return render(request,'plagiarism/page3.html',{'data': data})
urls.py
from django.conf.urls import url
from . import views
from . import example3
urlpatterns=[
url(r'^$',views.add,name='add'),
url(r'file2/$',views.add2,name='add2'),
url(r'file2/result/$',example3.getresult,name='getresult')
]
You seem to want a kind of wizard, where you process a form and it redirects you to the next, but you're not doing the basics of form processing well. For simple form handling, you can do this:
urls.py
from django.conf.urls import url
from . import views
from . import example3
urlpatterns=[
url(r'^$',views.add,name='add'),
url(r'file2/result/$', example3.getresult, name='getresult')
]
In the template, you are calling file2 with the form's action, but you really want to call the same page, to process the form with the add view:
plagiarism/page1.html
<h1>Enter your first file</h1>
<form method="post">
{% csrf_token %}
{% for field in form %}
{{field}}
{% endfor %}
<input type="submit" value="Submit file1"/>
</form>
Note the missing action attribute in the <form> element.
When you visit the root of the website, the add view will be called with a GET request. When you submit the form, the same add view will be called, with a POST request, which will then be processed:
views.py
def add(request):
if request.method == 'POST':
form = FilesCreate(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('getresult'))
else:
form = FilesCreate()
return render(request,'plagiarism/page1.html',{'form': form})
Note the HttpResponseRedirect, which redirects to a new page on success, and the else, which creates an empty form for the first time you visit the page (i.e. request.method is not POST, it is GET). This way, if the form isn't valid, the last line will render it bound to the data that was submitted and display the errors.
This should get you the data into the database, which was your first goal. If you want to go to another form upon submission, you can redirect there (instead of the result page) and do the same as above in the view add2.
There used to be a Django Form Wizard, but you can see this project to do multi-step forms.

Passing variable with POST in django

Hi im trying to pass a name from a form to a view in django using POST. There are no errors in the execution but its passing nothing from the template and dont know if i doing something wrong here. Im starting with django so i can have newbie errors. If u need more information tell me pls.
Views.py
def crear_pdf(request):
empresa_selec = ""
form = EmpModelForm()
if request.method == 'POST':
form = EmpModelForm(data=request.POST)
if form.is_valid():
empresa_selec = form.cleaned_data['nombre']
#"empresa_selec" that's the empty variable
Models.py
class Empresa_modelo(models.Model):
nombre = models.CharField(max_length=100,blank=True,null=True)
Forms.py
class EmpModelForm(forms.ModelForm):
class Meta:
model = Empresa_modelo
fields = ["nombre"]
template.html
<div class="container-fluid">
<form method="POST" enctype="multipart/form-data" action="{% url 'crear_pdf' %}">{% csrf_token %}
<p>Empresa</p>
<input type="text" name="empresa">
<br>
<button type="submit">Subir</button>
</form>
<br>
<a class="btn btn-primary" href="{% url 'crear_pdf' %}">Atras</a>
</div>
You haven't got a field called nombre in your template; you only have empresa.
That's presumably because you don't ouput your EmpModelForm in the template. You don't show your render call in the view, but assuming you pass it as form, you should just do {{ form.as_p }} in the template.
Try using:
<input type="text" name="nombre">
There is no field named empresa.
Had a look at your code,there are a couple of issues.First you are not using the model form defined in your forms.py file in your template. Second you have defined an input text box with the name that you are not referring in your views. Either use the model form or use the same name of your input text box in your views.
def crear_pdf(request):
empresa_selec = ""
form = EmpModelForm()
if request.method == 'POST':
form = EmpModelForm(data=request.POST)
if form.is_valid():
empresa_selec = form.cleaned_data['nombre']
else:
return render(request,"template.html",{"form":form})
And in your template you can edit as such:
<div class="container-fluid">
<form method="POST" enctype="multipart/form-data" action="{% url 'crear_pdf' %}">{% csrf_token %}
{{ form.as_p }}
<br>
<button type="submit">Subir</button>
</form>
<br>
<a class="btn btn-primary" href="{% url 'crear_pdf' %}">Atras</a>
</div>
Hope this helps.

Categories