I am building a registration form. I want the users to review their filled-up forms to confirm their submissions. But in my code the form is submitted twice (overwritten not duplicated). Once when they hit the submit button after filling their form and overwritten after hitting the submit button on the review page. As a result if they close the browser in the review page their page is still submitted, which I don't want to allow.
views.py
from django.shortcuts import render, redirect
from .models import *
from .forms import *
# Create your views here.
def index(request):
form = RegisterForm()
print('hi')
if request.method == 'POST':
form = RegisterForm(request.POST, request.FILES)
if form.is_valid():
z = form.cleaned_data
if (Register.objects.filter(email=z['email']).exists()):
print('already exist')
return redirect('/')
else:
print('xx')
return redirect('preview', pk=z.get('id'))
context = {'form':form}
return render(request, 'event/index.html', context)
def preview(request, pk):
prev = Register.objects.get(id=pk)
if request.method == 'POST':
prev.save()
print('overwrite')
return redirect('/')
print('yy')
context = { 'prev':prev,'id':pk}
return render(request, 'event/preview.html', context)
index.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Event Registration</title>
<link rel="stylesheet" href="{% static 'css/style.css' %}">
<script src="{% static 'js/script.js' %}"></script>
</head>
<body>
<div class="mobile-screen">
<div class="header">
</div>
<div class="logo"></div>
<form id="login-form" method="POST" action="" enctype="multipart/form-data">
{% csrf_token %}
{{form.name}}
{{form.email}}
<input class="btn btn-sm btn-primary" type="submit" value="Register" name="Register">
</form>
</div>
</body>
</html>
models.py
from django.db import models
from phonenumber_field.modelfields import PhoneNumberField
# Create your models here.
class Register(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField(max_length=254,null=True)
def __str__(self):
return self.name
Related
I am building a registration form. Whenever a user fills the form and clicks the register button I want them to see the preview of their submissions. I am having problems with the arguments. Here goes my code:
models.py
from django.db import models
from phonenumber_field.modelfields import PhoneNumberField
# Create your models here.
class Register(models.Model):
regChoice = (
('Self', 'Self'),
('Group', 'Group'),
('Corporate', 'Corporate'),
('Others', 'Others'),
)
name = models.CharField(max_length=50)
email = models.EmailField(max_length=254,null=True)
phoneNumber = PhoneNumberField(null=True)
idCard = models.ImageField(null=True)
regType = models.CharField(max_length=25, choices=regChoice,null=True)
ticketNo = models.IntegerField(default=1)
def __str__(self):
return self.name
forms.py
from django import forms
from django.forms import ModelForm
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from .models import *
class RegisterForm(ModelForm):
name = forms.CharField(widget=forms.TextInput(attrs={'placeholder':'Your full name...'}))
email = forms.CharField(widget=forms.TextInput(attrs={'placeholder':'Your email...'}))
phoneNumber = forms.CharField(widget=forms.TextInput(attrs={'placeholder':'Your phone number...'}))
class Meta:
model = Register
fields = '__all__'
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='home'),
path('preview.html/<str:pk>', views.preview, name="preview")
]
views.py
from django.shortcuts import render, redirect
from .models import *
from .forms import *
# Create your views here.
def index(request):
form = RegisterForm()
if request.method == 'POST':
form = RegisterForm(request.POST, request.FILES)
if form.is_valid():
form.save()
context = {'form':form}
return render(request, 'event/index.html', context)
def preview(request, pk):
reg = Register.objects.get(id=pk)
prev = RegisterForm(instance=reg)
if request.method == 'POST':
form = RegisterForm(request.POST, instance=reg)
if form.is_valid():
form.save()
return redirect('/')
context = {'reg':reg, 'prev':prev}
return render(request, 'event/preview.html', context)
index.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Event Registration</title>
<link rel="stylesheet" href="{% static 'css/style.css' %}">
<script src="{% static 'js/script.js' %}"></script>
</head>
<body>
<div class="mobile-screen">
<div class="header">
</div>
<div class="logo"></div>
<form id="login-form" method="POST" action="{% url 'preview' form.id %}" enctype="multipart/form-data">
{% csrf_token %}
{{form.name}}
{{form.email}}
{{form.phoneNumber}}
<legend style="color: aliceblue;">Upload ID card: </legend>{{form.idCard}}
<div style="text-align: center; color: aliceblue;">Registration Type: {{form.regType}}</div>
{{form.ticketNo}}
<input class="btn btn-sm btn-primary" type="submit" value="Register" name="Register">
</form>
</div>
</body>
</html>
preview.html
Hello {{prev.name}},
your email is {{prev.email}}
your phone number is {{prev.phoneNumber}}
your idCard photo is {{prev.idCard.url}}
your registration type is {{prev.regType}}
your number of tickets is {{prev.ticketNo}}
The error I am having is:
NoReverseMatch at /
Reverse for 'preview' with arguments '('',)' not found. 1 pattern(s) tried: ['preview\.html/(?P[^/]+)$']
When someone reaches your index page and enters the form we need to
Submit the form as a POST request to index view
Save the form thereby creating a model in the DB
Redirect the user to preview view using the above id
To do that the code needs to be somewhat like this, I have not tested it, but you should get the idea.
from django.shortcuts import redirect
def index(request):
form = RegisterForm()
if request.method == 'POST':
form = RegisterForm(request.POST, request.FILES)
if form.is_valid():
instance = form.save()
return redirect('preview', pk=instance.id)
context = {'form':form}
return render(request, 'event/index.html', context)
Inside your index.html change
action="{% url 'preview' form.id %}"
to
action=""
as we want it to post to the INDEX view as that is where out POST handling logic is.
The index view then redirects to preview using the newly generated object.
Also as mentioned by #Snir in the other answer, having .html in URLS is not a standard practice. It would be better to simple make it something like:
path('preview/<str:pk>', views.preview, name="preview")
The URL patterns are regexes, so you'll have to escape special regex characters, like the dot. Try (add r) or remove the dot:
path(r'preview.html/<str:pk>', views.preview,
name="preview")
from django import forms
from django.core import validators
class FormName(forms.Form):
name = forms.CharField()
email = forms.EmailField()
verify_email = forms.EmailField(label = "enter your email Again")
text = forms.CharField(widget = forms.Textarea)
def clean(self):
all_clean_data = super().clean()
email = all_clean_data['email']
vmail = all_clean_data['verify_email']
if email != vmail:
raise forms.ValidationError("Error i Email matching")
views.py
from django.shortcuts import render
from . import form
# Create your views here.
def index(request):
return render(request,'basicapp/index.html')
def form_name_view(request):
forms = form.FormName()
if request.method == "POST":
formObject = form.FormName(request.POST)
if formObject.is_valid():
print("Sucess!!!!!")
print(formObject.cleaned_data['name'])
print(formObject.cleaned_data['email'])
print(formObject.cleaned_data['text'])
return render(request,'basicapp/form_page.html',{'form':forms})
form_page.html
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Forms</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
</head>
<body>
<div class = "container">
<h1>Fill out the form</h1>
<form method="POST">
{{form.as_p}}
{% csrf_token %}
<input type="submit" class="btn btn-primary" value = "Submit">
</form>
</div>
</body>
</html>
I am Not sure What I am missing,
I have done everything and had done enough research, But could not find the solution.
Am I missing something because of the versioning of django.
I am following one udemy course and didn't get response, Thats y I am posting here.
Thanks in advance
The issue was in your views, you were not rendering the form object properly.
try this,
def form_name_view(request):
if request.method == "POST":
formObject = form.FormName(request.POST)
if formObject.is_valid():
print("Sucess!!!!!")
# do some redirection
else:
# if a GET (or any other method) we'll create a blank form
formObject = form.FormName()
return render(request, 'basicapp/form_page.html', {'form': formObject})
How is going? I'm learning to programming in django. For the moment I'm building a simple app that utilizing a form update the referenced table.
Now I'm try to add a delete button in each row of my table but, beside I have tried a lot of solutions, I didn't find one that works correctly.
Below my code:
urls
from django.urls import path
from app import views
app_name = 'main'
urlpatterns = [
path('', views.homepage, name='homepage'),
path('delete_item/<int:pk>', views.delete_item, name="delete_item"),
]
forms
from django import forms
from .models import Income
class IncomeModelForm(forms.ModelForm):
class Meta:
model = Income
fields = "__all__"
tables
import django_tables2 as tables
from django_tables2.utils import A
from .models import Income
class PersonTable(tables.Table):
delete = tables.LinkColumn('main:delete_item', args=[A('delete-id')], attrs={'a': {'class': 'btn'}})
class Meta:
model = Income
template_name = "django_tables2/bootstrap.html"
views
from django.shortcuts import render
from django.http import HttpResponse
from django.views.generic import ListView
from .models import Income
from .tables import PersonTable
from .forms import IncomeModelForm
def homepage(request):
table = PersonTable(Income.objects.all())
if request.method == 'POST':
form = IncomeModelForm(request.POST)
if form.is_valid():
print("Il form รจ valido")
new_input = form.save()
else :
form = IncomeModelForm()
context= {"form": form,
"table":table }
return render(request, "app/base.html", context)
def delete_item(request, pk):
Income.objects.filter(id=pk).delete()
items = Income.objects.all()
context = {
'items': items
}
return render(request, 'app/base.html', context)
html
{% load static %}
{% load render_table from django_tables2 %}
<!doctype html>
<html lang="it">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Hello, world!</title>
</head>
<div class="container">
<form class="" action="" method="post">
{% csrf_token %}
{{form|crispy}}
<input type="submit" class="btn btn-danger" value="INVIA">
</form>
</div>
<br>
<br>
<div class="container">
{% render_table table %}
</form>
</div>
</body>
</html>
My table disply the column "Delete" but no buttoms, only a "-". Why? Where is my error?
Please add this
text='static text', argument like delete = tables.LinkColumn('main:delete_item',text='Delete', args=[A('delete-id')], attrs={'a': {'class': 'btn'}})
.
Hope it will work
My login page isn't looking like the way I want it to which is like this bootstrap signin page right here https://getbootstrap.com/docs/4.0/examples/sign-in/. This is what it looks like right now
If you can help me out with this, it would mean the world to me.
Also if you think it's because I didn't link to a CSS page here's what my base template looks like and my structure:
{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Accounts</title>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" type="text/css" href="{% static 'accounts/signin.css' %}" />
</head>
<body>
<div class="jumbotron">
<div class="container">
{% block main_content %}
{% endblock %}
</div>
</div>
</body>
</html>
views.py
from django.contrib.auth import (
authenticate,
get_user_model,
login,
logout,
)
from django.shortcuts import render
from django.http import HttpResponse,HttpResponseRedirect
from .forms import UserLoginForm
# Create your views here.
def login_view(request):
title = "Login"
form = UserLoginForm(request.POST or None)
if form.is_valid():
username = form.cleaned_data.get("username")
password = form.cleaned_data.get('password')
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
# or any other success page
# return HttpResponse("Logged in")
return HttpResponseRedirect('accounts/home')
return render(request, "accounts/form.html", {"form":form, "title": title})
forms.py
from django import forms
from django.contrib.auth import (
authenticate,
get_user_model,
login,
logout,
)
User = get_user_model()
class UserLoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = ('username', 'email', 'password')
def clean(self,*args,**kwargs):
username = self.cleaned_data.get("username")
password = self.cleaned_data.get("password")
user = authenticate(username=username,password=password)
if not user:
raise forms.ValidationError("This user does not exist")
if not user.check_password(password):
raise forms.ValidationError("Incorrect Password")
if not user.is_active:
raise forms.ValidationError("This user is no longer active.")
return super(UserLoginForm, self).clean(*args,**kwargs)
form.html (currently using this for login, open to use the same format for registration)
{% extends 'accounts/base.html' %}
{% block main_content %}
<div class="container">
<div class='col-sm-6 col-sm-offset-3'>
<h1>{{ title }}</h1>
<form method='POST' action='' enctype='multipart/form-data'>{% csrf_token %}
{{ form }}
<input type='submit' class='btn btn-primary btn-block' value='{{ title }}' />
</form>
</div>
</div>
{% endblock %}
What My Framework Looks Like
Thanks a lot
#Lemayzeur this is what my site looks like now
And this is what I want it to look like
-it comes pretty close but unfortunately it's not the same. Nonetheless, I'll keep it and thank you.
Your CSS file works well because the button inherits the bootstrap design,
the problem is all the inputs that you have don't have the class form-control. So to add these classes, you can do it with the widget
class UserLoginForm(forms.Form):
username = forms.CharField(max_length=120,
widget=forms.TextInput(attrs={'class':'form-control',"placeholder":"Username"}))
password = forms.CharField(max_length=100,
widget=forms.PasswordInput(attrs={'class':'form-control',"placeholder":"Password"}))
I can't figure out why it won't update/edit an item and then add it back to list with the edits. If someone can help me out thanks! If I find my answer before I get a response I will post it. I posted my views.py, urls.py and the html for the edit page confirm_edit.html just so you can see all of what I am dealing with. thanks for the help!
from django.shortcuts import render, redirect, HttpResponse
from .models import Course
def index(request):
context = {
'course' : Course.objects.all()
}
return render(request, 'chp1/index.html', context)
def create(request):
if request.method == "POST":
Course.objects.create(SLA_TYPE_CD=request.POST['Name'],
SLA_TS=request.POST['description'], ACTUAL_COMPLETION_TS=request.POST['description'],
TICKET_NUM=request.POST['description'], NOTE_TXT=request.POST['description'])
return redirect('/')
def edit(request, id):
course_to_edit = Course.objects.get(id=id)
if request.method == "GET":
return render(request, 'chp1/confirm_edit.html', {'course' : course_to_edit})
def update(request, id):
if request.method == "POST":
course_to_edit.update(SLA_TYPE_CD=request.POST['Name'],
SLA_TS=request.POST['description'], ACTUAL_COMPLETION_TS=request.POST['description'],
TICKET_NUM=request.POST['description'], NOTE_TXT=request.POST['description'])
return redirect('/')
def destroy(request, id):
course_to_delete = Course.objects.get(id=id)
if request.method == "GET":
return render(request, 'chp1/confirm_delete.html', {'course' : course_to_delete})
course_to_delete.delete()
return redirect('/')
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index),
url(r'^create$', views.create),
url(r'^(?P<id>\d+)/destroy$', views.destroy),
url(r'^(?P<id>\d+)/edit$', views.edit),
]
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Edit SLA_VARIANCE_NOTE</title>
<link rel="stylesheet" href="{% static 'chp1/css/styles.css' %}">
</head>
<body>
<div id="addcourse">
<h2>Are you sure you want to edit the following post?</h2>
<form action="/{{ course.id }}/edit" method='post'>
SLA_TYPE_CD: <input type="text" name="Name" value=""> <br>
SLA_TS: <textarea name="description" rows="1" cols="40"></textarea> <br>
ACTUAL_COMPLETION_TS: <textarea name="description" rows="1" cols="40"></textarea> <br>
TICKET_NUM: <textarea name="description" rows="1" cols="40"></textarea> <br>
NOTE_TXT: <textarea name="description" rows="1" cols="40"></textarea><br>
{% csrf_token %}
<button>Back</button>
<input name="edit" type="submit" value="update">
</form>
</div>
</body>
</html>