I cannot render the contact.html. Why? I am facing to the following error and description:
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/contact/
admin/
[name='index']
contact [name='contact']
The current path, contact/, didn't match any of these.
Here is my code:
views.py
def contact(request):
if request.method == 'POST' :
form = ContactForm(request.POST)
if form.is_valid():
form.save()
return render ('thanks.html', {'form':form})
else:
form = ContactForm()
return render(request, 'contact.html', {'form':form})
models.py
from django.db import models
class Contact (models.Model):
name = models.CharField (max_length=100)
email = models.EmailField (max_length=100)
subject = models.CharField (max_length=100)
message = models.TextField (max_length=1000)
forms.py
from django.forms import ModelForm
from .models import ContactModel
class ContactForm (ModelForm):
class Meta:
model = ContactModel
fields = ['name', 'email', 'subject', 'message']
urls.py
urlpatterns = [
path('', views.index, name='index'),
path('contact', views.contact, name='contact'),
]
contact.html
<body>
<div class="container">
<br />
<form action="{% url 'contact' %}" method="post">
{% csrf_token %}
...
<div id="success">
<button type="submit" class="btn btn-outline-dark"
id="sendMessageButton">
Send Message
</button>
</form>
</div>
Are you sure that the form is valid? Repeating the Contact-page indicates that you end up within the else:. That would explain why nothing is saved, as the if: is skipped, and it would explain why the incorrect render() without a request passed is not giving you any issues.
Try printing out the POST-data with print(request.POST) at the top of the view to see if all variables you expect to see are there and that everything is spelled correctly (easy mistake). Compare what is POST:ed with what your form is looking for.
When you get that working, I would consider changing the render to a redirect.
It is also a good idea to add a second else: if the form is not valid. This would look like:
if form.is_valid():
name = form.cleaned_data['name']
email = form.cleaned_data['email']
subject = form.cleaned_data['subject']
message = form.cleaned_data['message']
form.save()
return redirect('your-thankyou-url')
else: #if form is not valid
render(request, 'contact.html', {'form': form})
That would render any errors and make it clear for whomever is entering information that something submitted is faulty.
Best of luck!
Related
Right now, users can view all forms that are completed by any user, even when they are logged in and all forms get posted onto the same html page. I want users to only be able to view their own forms they completed when logged into their account. Any directions would be helpful. I understand functions more than classes in views, an ideal solution would use functions. Thank you so much for any advice as this is my first Django I am trying on my own without strictly following a video or class.
models.py
from django.db import models
from django.contrib.auth.models import User
from django.forms import ModelForm
from django import forms
class Step1_Model(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
title = "STEP 1: Safety during a violent incident"
box1 = models.CharField(max_length=100, null=True)
box2 = models.CharField(max_length=100, null=True)
box3 = models.CharField(max_length=100, null=True)
box4 = models.CharField(max_length=100, null=True)
box5 = models.CharField(max_length=100, null=True)
box6 = models.CharField(max_length=100, null=True)
def __str__(self):
return self.title
forms.py
from django import forms
from .models import Step1_Model
class Step1_Form(forms.ModelForm):
box1 = forms.CharField()
class Meta:
model = Step1_Model #which model we want to use as a model for our model form
fields= ("box1","box2","box3", "box4", "box5", "box6")
views.py
from django.shortcuts import render, redirect
from django.contrib import messages
from .forms import Step1_Form
from .models import Step1_Model
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
def loginPage(request):
if request.method == "POST": #The user entered the info and logged in.
username = request.POST.get('username') #this is sent from the front end through the login.html.
password = request.POST.get('password')
try:
user= User.objects.get(username=username)
except:
messages.error(request, "User does not exist.")
user = authenticate(request, username=username, password=password) #if get was successful authenticate user.
if user is not None: #if we got a user
login(request, user) #will add the session in the database and browser.
return redirect('home')
else:
messages.error(request, "Username or password does not exist.")
context = {}
return render(request, 'registration/login_registration.html', context)
def logoutUser(request):
logout(request) # deletes the token/user session
return redirect('home')
#login_required(login_url='login_user')
def Step1_Form_Completion(request):
"""Generates link for user to fill out form"""
form = Step1_Form #Assign the form to the variable in the function.
if request.method == 'POST': # if method or form is requested then POST or send data to this function. If someone is loggded in . .
form = Step1_Form(request.POST) #the method is form and it is to be posted.
if form.is_valid(): #if the form is django's definiton for 'valid' then save it and redirect the user home.
form.save()
return redirect('/')
return render(request, 'form.html', {'form':form} ) # return this function to the form.html page and let it use form as s variable and call it's attributes (form.box1)
#login_required(login_url='login_user') #sends user back to login page if they try to go to a view form.
def Step1_Form_View(request):
"""View for user to see completed form"""
step1 = Step1_Model.objects.all()
return render(request,'form_view.html',{'step1': step1})
def index(request):
return render(request, 'index.html')
def register_user(request):
form = UserCreationForm()
if request.method == 'POST': #if someone has filled out a form do something.
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data['username']
password = form.cleaned_data['password1']
user = authenticate(username=username, password=password) #authenticate user
login(request, user) #log user in
messages.success(request, 'Registration Successful')
return redirect('home')
else:
form = UserCreationForm()
return render(request, 'registration/register_user.html', {'form': form} )
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('login', views.loginPage, name='login_user'),
path('logout', views.logoutUser, name='logout'),
path('register_user', views.register_user, name='register_user'),
path('', views.index, name='home'),
path('step1', views.Step1_Form_Completion, name='step1'),
path('form_view', views.Step1_Form_View, name='form_view'),
]
form.html
{% block content %}
</head>
<body>
<form method='post'>
{% csrf_token %}
STEP 1: Safety during a violent incident. I will not always be able to avoid violent incidents. In order to increase safety I may use a variety of strategies.
I can use some of the following strategies:
<p>
A. When I need to leave the house because of an emergency I will keep my keys in: {{ form.box1 }}.
<p>
B. When I need to put out a fire I will:{{ form.box2 }}.
</p>
</p>
<button type="submit">Submit</button>
</form>
</body>
</html>
{% endblock content %}
form_view.html
<body>
<!-- user_input shows up here but way too much. not only the logged in users form.-->
{% if step1 %}
<h1>Your Step 1 Plan</h1>
<tr>
{% for st in step1 %}
<p>
A. I will <b>{{ st.box1 }}</b>.
<p>
B. I will put the fire out by <b>{{ st.box2 }}</b> in order to leave quickly.
</p>
index.html
<!-- my homepage and how users get to view wand submit forms-->
{% extends 'base.html' %}
{% block content %}
<!--Row 1-->
<div class="row">
<div class="col-md-1">
<p>{{request.user}}</p>
</div>
<!--Row 2-->
<div class="row">
<div class="col-md-auto">
Step 1: A Violent Incident
</div>
<div class="col-md-auto">
Form
</div>
<div class="col-sm-auto">
View
</div>
</div>
{% endblock %}
Instead of passing all Step1_Model in view just pass that one asign to request.user
#login_required(login_url='login_user') #sends user back to login page if they try to go to a view form.
def Step1_Form_View(request):
"""View for user to see completed form"""
step1 = request.user.step1_model
return render(request,'form_view.html',{'step1': step1})
now you don't need {% for st in step1 %} in form_view.html template.
And for future readability use PascalCase in class names(models, forms, etc), you don't need to add 'model' to class name, and snake_case for function names.
Found the answer for this if anyone wants to know, I haven't seen this answer online anywhere. I had to watch more videos about how accessing the database works. I needed to add two lines of code:
In views.py
form.instance.user= request.user in to my form_completion function.
step1 = StepOne.objects.filter(user=request.user) into my form_view function.
See below for an example:
#login_required(login_url='login_user')
def Step1_Form_Completion(request):
"""Generates link for user to fill out form"""
form = StepOneForm #Assign the form to the variable in the function.
if request.method == 'POST': # if method or form is requested then POST or send data to this function. If someone is loggded in . .
form = StepOneForm(request.POST) #the method is form and it is to be posted.
if form.is_valid(): #if the form is django's definiton for 'valid' then save it and redirect the user home.
form.instance.user= request.user
form.save()
return redirect('/')
return render(request, 'form.html', {'form':form} ) # return this function to the form.html page and let it use form as s variable and call it's attributes (form.box1)
#login_required(login_url='login_user') #sends user back to login page if they try to go to a view form.
def Step1_Form_View(request):
"""View for user to see completed form"""
step1 = StepOne.objects.filter(user=request.user)
return render(request,'form_view.html',{'step1': step1})
guys, I am beginner at Django. I watch lessons on youtube and get different results. I use Django==2.0.7 and Python==3.6.5.
I try to get error on my page, if I write not correct name of title, but I don't get it. Look at func - **def clean_title(self, *args, kwargs), I hope, you understand, what I mean. There I have "raise forms.ValidationError("Error")", but it doesn't work anymore.
forms.py
from django import forms
from .models import Product
class ProductForm(forms.ModelForm):
title = forms.CharField(label='',
widget=forms.TextInput(attrs={"placeholder": "title"}))
Description = forms.CharField(
required=False,
widget=forms.Textarea(
attrs={
"placeholder": "Your description",
"class": "new-class-name two",
"id": "new-class-name two",
"rows": 20,
'cols':120
}
)
)
Price = forms.DecimalField(initial=199.99)
class Meta:
model = Product
fields = [
'title',
'Description',
'Price'
]
def clean_title(self, *args, **kwargs):
title = self.cleaned_data.get('title')
if "Ruslan" in title:
return title
else:
raise forms.ValidationError("Error")
In forms.py I created class ProductForm and declared the fields. In my page I see it.
Also I defined clean_title. I wanted to get error if I filled in wrong name of title.
views.py
from django.shortcuts import render
from .models import Product
from .forms import ProductForm as CreateForm, PureDjangoForm
def create_form(request):
form = CreateForm(request.POST or None)
if form.is_valid():
form.save()
form = CreateForm()
context = {
'form': form
}
return render(request, "create_product_form.html", context)
create_product_form.html
{% extends 'base.html' %}
{% block content %}
<form action='.' method="POST"> {% csrf_token %}
{{ form.as_p }}
<input type='submit' value='Save' />
</form>
{% endblock %}
This is my file.html, it inherits any not important details from base.html.
Guys, what's wrong, help me, please, I can't understand how I can get error if name of title is not correct? I see all fields on my page and I can fill in it, but it doesn't show me errors.
You should not create a new form if you made one that is invalid, the view thus should look like:
def create_form(request):
if request.method == 'POST':
form = CreateForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('name-of-some-view')
else:
form = CreateForm()
context = {
'form': form
}
return render(request, 'create_product_form.html', context)
Note: In case of a successful POST request, you should make a redirect
[Django-doc]
to implement the Post/Redirect/Get pattern [wiki].
This avoids that you make the same POST request when the user refreshes the
browser.
I am a learner in django. i have created my first form, but when i input data i dont see it in my database but see in in my shell. I have rechecked my code but it seem fine, yet still it wont save in my code in the database.
Please help me out here.Thanks.
Model:
from django.db import models
class Login(models.Model):
first_name = models.CharField(max_length=200)
second_name = models.CharField(max_length=200)
email = models.EmailField()
password = models.CharField(max_length=200)
View:
from django.http import HttpResponse
from django.shortcuts import render
from .models import Login
from .forms import login_form
def homeview(request):
return HttpResponse("<h1>Hello There</h1>")
def login_view(request):
form = login_form(request.POST or None)
if form.is_valid:
form.save
context = {
"form":form
}
return render(request, "login.html", context)
Template:
{% block content %}
<form action="" method="GET">{% csrf_token %}
{{form.as_p}}
<input type="submit" value="Login"/>
</form>
{% endblock %}
Form:
from django import forms
from .models import Login
class login_form(forms.ModelForm):
class Meta:
model = Login
fields = [
"first_name",
"second_name",
"email",
"password"
]
Following lines are incorrect:
if form.is_valid:
form.save
Currently the if will always return True because .is_valid returns the bound method.
You need to call is_valid -> form.is_valid()
Same for form.save. You would only return the bound method save, but you don't call it.
These lines would look like this:
if form.is_valid():
form.save()
Furthermore: In your template the used method for your form is GET but you are accessing request.POST. You need to change either one of them to the other method, e.g. method="POST".
I'm familiar with creating forms based on Model forms, in that case I can use form.save() to save the data in database. The question is, how do I save/retrieve the data of this form that I didn't create through a model form?
I've tried the following code but I'm not sure how to retrieve and save the data from NameForm.
#forms.py file:
from django import forms
class NameForm(forms.Form):
your_name = forms.CharField(label = 'your name', max_length = 100)
# views.py file
from django.shortcuts import render, redirect
from .forms import NameForm
def home(request):
return render(request, 'meal_plans/home.html')
def name(request):
if request.method != 'POST':
form = NameForm()
else:
form = NameForm(data=request.POST)
if form.is_valid():
your_name = form.cleaned_data['your_name']
return redirect('meal_plans:home')
return render(request, 'meal_plans/name.html', {'form': form})
# name.html template
<form action="{% url 'meal_plans:home' %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form
One option is to save the data in the users session. The docs explain quite nicely how to implement this. In your case, it would be something like this:
if form.is_valid():
request.session['your_name'] = form.cleaned_data['your_name']
...
To access that session variable in another view, you would use:
your_name = request.session.get('your_name')
I am trying to have a user input a task from the frontend and have that data instantiate a new model and add this new field in the database associated with their account. I have tried the following;
Profile HTML
<form id="taskitem_form" method="post" action="/">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.help_text }}
{{ field }}
{% endfor %}
<input type="submit" name="submit" value="Add Task" class ="btn btn-primary" />
</form>
Model
class TaskItem(models.Model):
taskn = models.CharField(max_length = 400)
usern = models.ForeignKey(User)
def __str__(self):
return self.taskn
Views
def add_task(request):
# Get the context from the request.
#context = RequestContext(request)
# A HTTP POST?
if request.method == 'POST':
form = TaskItemForm(request.POST)
# Have we been provided with a valid form?
if form.is_valid():
task = form.save(commit=False)
task.usern = request.user
task.save()
# we should redirect after data modifying
return redirect('/user/%s' %(request.user))
else:
# If the request was not a POST, display the form to enter details.
return render(request, 'profile.html', {'form': form})
# Bad form (or form details), no form supplied...
# Render the form with error messages (if any).
return render(request, 'profile.html', {'form': form})
Forms
from django import forms
from bkmks.models import TaskItem
class TaskItemForm(forms.ModelForm):
taskn = forms.CharField(max_length = 300, help_text = "Please enter your task")
# An inline class to provide additional information on the form.
class Meta:
fields = ('taskn', 'usern' )
#This is the association between the model and the model form
model = TaskItem
Lot's of Changes needed to your code.
I'm posting a working version so that you can try.
Put profile.html file as bkmks/templates/bkmks/profile.html
Get it working. Customize later.
profile.html
<form id="taskitem_form" method="post" action="">
{% csrf_token %}
{{form}}
<input type="submit" name="submit" value="Add Task" class ="btn btn-primary" />
</form>
model as it is.
views.py
from django.contrib.auth.decorators import login_required
from django.shortcuts import render_to_response, RequestContext, redirect
from .forms import TaskItemForm
#login_required
def add_task(request):
# Get the context from the request.
context = RequestContext(request)
# A HTTP POST?
if request.method == 'POST':
form = TaskItemForm(request.POST)
# Have we been provided with a valid form?
if form.is_valid():
# Save the new category to the database.
task = form.save(commit=False)
task.usern = request.user
task.save()
# Redirect to home (/)
return redirect('/')
else:
# The supplied form contained errors - just print them to the terminal.
print form.errors
else:
# If the request was not a POST, display the form to enter details.
form = TaskItemForm()
# Bad form (or form details), no form supplied...
# Render the form with error messages (if any).
return render_to_response('bkmks/profile.html', {'form': form}, context)
forms.py
class TaskItemForm(forms.ModelForm):
# task is changed to taskn
taskn = forms.CharField(max_length = 300, help_text = "Please enter your task")
# An inline class to provide additional information on the form.
class Meta:
fields = ('taskn',)
#This is the association between the model and the model form
model = TaskItem
If you get any error or data is not getting saved post here.
Going through Django tutorial will be an wise decision.
The below should do what you need. You really want to inherit 100% of everything from your model when you can. This insures all model validation trickles down to the form. I utilized verbose_name and help_text on the model to achieve this.
Models
from django.conf import settings
class TaskItem(models.Model):
taskn = models.CharField(
max_length=400,
verbose_name="task",
help_text="Please enter your task.",
)
usern = models.ForeignKey(
to=settings.AUTH_USER_MODEL,
related_name="tasks",
)
def __str__(self):
return self.taskn
For the forms, I have added a forms.HiddenInput widget to the user, assuming you want the user submitting the task to become the user.
Forms
from django import forms
from bkmks.models import TaskItem
class TaskItemForm(forms.ModelForm):
widgets = {
'user': forms.HiddenInput,
}
class Meta:
model = TaskItem
fields = ('taskn', 'usern')
I have used a CreateView to reduce code complexity, and overrode the form_valid to add the user instance to the form.
Views
from django.views.generic import CreateView
from bkmks.models import TaskItem
from bkmks.forms import TaskItemForm
class TaskCreateView(CreateView):
model = TaskItem
form_class = TaskItemForm
template_name = "path/to/template.html"
def form_valid(self, form):
form.instance.user = self.request.user
return super(TaskCreateView, self).form_valid(form)
Finally, in the template, we simply want to use {{ form }}. I see you are looking into bootstrap. I'll suggest django-crispy-forms for this, but that is beyond the scope of your question.
Template
<form id="taskitem_form" method="post" action="/">
{% csrf_token %}
{{ form }}
<input type="submit" name="submit" value="Add Task" class ="btn btn-primary" />
</form>
https://docs.djangoproject.com/en/1.8/topics/http/shortcuts/#render-to-response
render_to_response expects a template as the first argument, not a url.
I think in your second call to render_to_response should include the template name / path , while the first one should use a return HttpResponseRedirect("/") instead, though its not clear exactly what your problem is.
Add this line to imports in views.py
from django.contrib.auth.decorators import login_required
Decorate add_task view
#login_required
def add_task(request):
Then, edit part of your code
if form.is_valid():
task = form.save(commit=False)
task.usern = request.user
task.save()
# we should redirect after data modifying
return redirect('/')
else:
# etc.
Some notes. You may replace render_to_response to render.
Remove this line
context = RequestContext(request)
Replace
# Wrong usage, actually.
# Should be something like
# render_to_response(template_name, context, context_instance)
render_to_respone('/', {'form': form}, context)
with
# if template_name is "profile.html"
render(request, 'profile.html', {'form': form})
Why define a field called task in the form if you've already got a field in the model called taskn, wouldn't it be better to just use that? And like the guys have said, you need to specify a template to render (that's why you're not seeing anything).
It'd also be a good idea to pass the current user to the form's user field.
#login_required
def add_task(request):
# Get the context from the request.
context = {}
# A HTTP POST?
if request.method == 'POST':
form = TaskItemForm(request.POST)
# Have we been provided with a valid form?
if form.is_valid():
# Save the new category to the database.
form.save()
# Now call the index() view.
# The user will be shown the homepage.
return render_to_response(
'profile.html',
{'form': form},
RequestContext(request, context)
)
else:
# The supplied form contained errors - just print them to the terminal.
print form.errors
else:
# If the request was not a POST, display the form to enter details.
form = TaskItemForm(initial={'usern': request.user})
# Bad form (or form details), no form supplied...
# Render the form with error messages (if any).
return render_to_response(
'profile.html',
{'form': form},
RequestContext(
request, context
)
)
Form;
from django import forms
from bkmks.models import TaskItem
class TaskItemForm(forms.ModelForm):
taskn = forms.CharField(max_length = 300, help_text = "Please enter your task")
# An inline class to provide additional information on the form.
class Meta:
fields = ('taskn', 'usern' )
#This is the association between the model and the model form
model = TaskItem