I have been struggling for the past couple of days trying to get my forms to save into my database. As of right now it is creating the object in the database but all of the fields inside the object are empty. I'm trying to save data from a ModelForm into the model.
Models.py
class ContactForm(models.Model):
Name = models.CharField(max_length= 50)
Email = models.EmailField()
Phone = models.CharField(max_length= 50)
Message = models.CharField(max_length= 200)
def __str__(self):
return self.Name
forms.py
class ContactForm(ModelForm):
name = forms.CharField(max_length=50)
email = forms.EmailField(required=True)
phone = forms.CharField(max_length=15)
message = forms.CharField(max_length=50)
class Meta:
model = ContactForm
fields = ['name','email','phone','message']
views.py
def contact(request):
if request.method=='POST':
form = ContactForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
else:
form = ContactForm()
args = {'form': form}
return render(request, 'home/contact.html', args)
urls.py
urlpatterns = [
url(r'^$', views.home, name='home'),
url(r'^about/$', views.about, name='about'),
url(r'^buy-now/$', views.buyNow, name='buy-now'),
url(r'^buy-form/$', views.buyForm, name='buy-form'),
url(r'^contact/$', views.contact, name='contact'),
url(r'^login/$', login, {'template_name': 'home/login.html'}, name='login'),
url(r'^logout/$', logout, {'template_name': 'home/logout.html'}, name='logout'),
url(r'^account/$', views.account, name='account'),
url(r'^register/$', views.register, name='register'),
]
template contact.html
{% extends 'base.html' %}
{% block head %}
<title>Aeviternus | Contact </title>
{% endblock %}
</head>
<body>
{% block body %}
<!-- Section: Contact -->
<section>
<div class="container">
<div class="row">
<div class="col s12 m6">
<div class="card-panel teal white-text center">
<i class="material-icons">email</i>
<h5>Contact Us</h5>
<p>If you have any comments or suggestions for any upcoming content or features you would like to see added, We want to hear about it.</p>
</div>
<ul class="collection with-header">
<li class="collection-header">
<h4>Location</h4>
</li>
<li class="collection-item">CSCI 152 Development Lab</li>
<li class="collection-item">5241 N Maple Ave</li>
<li class="collection-item">Fresno, CA 93740</li>
</ul>
</div>
<div class="col s12 m6">
<div class="card-panel grey lighten-3">
<h5>Please fill out this form</h5>
<form method ="post">
{% csrf_token %}
{{ form }}
<button type="submit" class="waves-effect waves-light btn-large">Submit</button>
</form>
</div>
</div>
</div>
</div>
</section>
{% endblock %}
<!--JavaScript at end of body for optimized loading-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/js/materialize.min.js"></script>
<script>
// Sidenav
const sideNav = document.querySelector('.sidenav');
M.Sidenav.init(sideNav, {});
</script>
</body>
</html>
Any help would be greatly appreciated.
Both your model name and form name are same. So, probably it's causing the problem.
change your form class name to ContactModelForm. Then your form class becomes
class ContactModelForm(forms.ModelForm):
name = forms.CharField(max_length=50)
email = forms.EmailField(required=True)
phone = forms.CharField(max_length=15)
message = forms.CharField(max_length=50)
class Meta:
model = ContactForm
fields = ['name','email','phone','message']
or
class ContactModelForm(forms.ModelForm):
class Meta:
model = ContactForm
fields = ['Name','Email','Phone','Message']
and replace ContactForm with ContactModelForm in your views.
Related
I'm currently using UpdateView to add edit functionality to my Django project. It's working correctly insofar as I can edit my data, however when I submit the new data, it returns a NoReverseMatch error:
NoReverseMatch at /MyHealth/edit/8
Reverse for 'health_hub_history' not found. 'health_hub_history' is not a valid view function or pattern name.
I've researched it and added a get_absolute_url to my model, but it isn't working. Any help would be appreciated!
models.py:
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
class HealthStats(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
date = models.DateField(auto_now=True)
weight = models.DecimalField(max_digits=5, decimal_places=2)
run_distance = models.IntegerField(default=5)
run_time = models.TimeField()
class Meta:
db_table = 'health_stats'
ordering = ['-date']
def get_absolute_url(self):
return reverse('health_hub_history')
def __str__(self):
return f"{self.user} | {self.date}"
urls.py:
from django.urls import path
from django.contrib.staticfiles.storage import staticfiles_storage
from django.views.generic.base import RedirectView
from . import views
app_name = 'HealthHub'
urlpatterns = [
path('', views.home, name='home'),
path('MyHealth/', views.health_hub, name='health_hub'),
path('MyHealth/update', views.UpdateHealth.as_view(), name='health_hub_update'),
path('MyHealth/history', views.health_history, name='health_hub_history'),
path('favicon.ico', RedirectView.as_view(url=staticfiles_storage.url("favicon.ico"))),
path('MyHealth/delete/<item_id>', views.delete_entry, name='health_hub_delete'),
path('MyHealth/edit/<int:pk>', views.EditHealth.as_view(), name='health_hub_edit'),
]
Views.py:
class EditHealth(UpdateView):
model = HealthStats
template_name = 'health_hub_edit.html'
fields = ['weight', 'run_distance', 'run_time']
health_hub_edit.html:
{% extends 'base.html' %}
{% load static %}
{%load crispy_forms_tags %}
{% block content %}
<div class="container-fluid">
<div class="row">
<div class="col-sm-12 text-center">
<h1>Edit my Data</h1>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-auto text-center p-3">
<form method="post" style="margin-top: 1.3em;">
{{ form | crispy }}
{% csrf_token %}
<button type="submit" class="btn btn-signup btn-lg">Submit</button>
</form>
</div>
</div>
<div class="row justify-content-center">
</div>
</div>
{% endblock content %}
This error occurs because the django couldn't resolve the url
you didn't specify a primary key to base the query on.
you should modify this function
def get_absolute_url(self):
return reverse('health_hub_history', kwargs={'user': self.user})
also that health_history url is it a class based view you should add .as_view() to the end and observe camel casing
Lastly your url should observe the primary key specified
You can do this:
class EditHealth(UpdateView):
model = HealthStats
template_name = 'health_hub_edit.html'
fields = ['weight', 'run_distance', 'run_time']
def get(self, request):
return HttpResponse("health_hub")
def post(self, request):
# do something
return redirect("health_hub")
urlpatterns = patterns('',
url('', views.home, name='home'),
url('MyHealth/', views.health_hub, name='health_hub'),
url('^MyHealth/update', views.UpdateHealth.as_view(), name='health_hub_update'),
url('MyHealth/history', views.health_history, name='health_hub_history'),
url('favicon.ico', RedirectView.as_view(url=staticfiles_storage.url("favicon.ico"))),
url('MyHealth/delete/<item_id>', views.delete_entry, name='health_hub_delete'),
url('MyHealth/edit/<int:pk>', views.EditHealth.as_view(), name='health_hub_edit'),
)
This will solve your problem
I found the answer to this issue here:
https://stackoverflow.com/a/48068932/19053957
Looks like all I need to do was refer to the app name prior to the name of the URL in get_absolute_url()!
I'm trying to make a user active when I tap a button, and I'm using a DetailView.
views.py
from .models import Model
from django.contrib.auth.models import User
from django.shortcuts import redirect
class UserInspectView(DetailView):
model = Model
template_name = 'user-inspect.html'
# Make the user is_active = True
def accept (request, pk):
user = User.objects.get(id=pk)
user.is_active
return redirect('home')
...
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('inspect/<slug:slug>/', views.UserInspectView.as_view(), name='user-inspect'),
path('inspect/<int:pk>/accept/', views.accept, name="user-accept"),
...
]
user-inspect.html
{% extends 'base.html' %}
{% block title %} <title>User Inspection</title> {% endblock %}
{% block content %}
<div class="d-flex justify-content-center">
<div class="container d-flex flex-column">
<div class="ms-5 ps-5" >
<h3><strong>User:</strong> {{model.user}}</h3>
<br>
<h3><strong>Name:</strong> {{model.name}}</h3>
</div>
</div>
</div>
<br><br><br>
<div class="d-flex justify-content-center">
<div class="btn-toolbar" role="toolbar" aria-label="Toolbar with button groups">
<div class="btn-group me-2 me-5 pe-5" role="group" aria-label="First group">
<form method="post" action="{% url 'user-accept' model.user.pk %}">
{% csrf_token %}
<button type="submit" class="btn btn-primary">Accept</button>
</form>
</div>
<div class="btn-group me-2 me-5 ps-5" role="group" aria-label="First group">
Back
</div>
</div>
</div>
{% endblock %}
models.py
from django.db import models
from django.contrib.auth.models import User
class Model(models.Model):
name = models.CharField(max_length=100)
user = models.ForeignKey(User, on_delete=models.CASCADE)
slug = models.SlugField(unique=True, blank=False, null=False)
Before my accept view looked like this
def accept (request, pk):
user = User.objects.get(id=pk)
user.is_active()
user.save()
return redirect('home')
but I changed it, because I got this error
TypeError at inspect/30/accept/
'bool' object is not callable
When I tap the Accept button, it takes me to the redirect that I have in the accept view, but the user is still inactive.
user.is_active is a boolean not a function.
def accept (request, pk):
user = User.objects.get(id=pk)
user.is_active = True
user.save()
return redirect('home')
I have a template called courses for the url http://127.0.0.1:8000/gradebook/courses/. This template lists existing Course objects loads the CourseForm form. The form successfully creates new objects.
If I go to the addassessment template with url http://127.0.0.1:8000/gradebook/addassessment/7/, it correctly loads the AssessmentForm. I want to submit this form and then return to the previous courses template. The AssessmentForm submits and the object is saved, but when it redirects back to the courses template, the CourseForm does not load. The courses template loads, the expect html loads correctly other than the form fields. I notice that the url for this page is still http://127.0.0.1:8000/gradebook/addassessment/7/ and not ../gradebook/courses/.
app_name = 'gradebook'
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('signup/', SignUpView.as_view(), name='signup'),
path('courses/', views.courses, name='courses'),
path('classroom/', views.classroom, name='classroom'),
path('objective/<int:course_id>/', views.addobjective, name='addobjective'),
path('addassessment/<int:course_id>/', views.addassessment, name='addassessment'),
]
#urls.py project
urlpatterns = [
path('', TemplateView.as_view(template_name='home.html'), name='home'),
path('admin/', admin.site.urls),
path('gradebook/', include('gradebook.urls')),
path('gradebook/', include('django.contrib.auth.urls')),
]
#models.py
class Course(models.Model):
course_name = models.CharField(max_length=10)
class Classroom(models.Model):
classroom_name = models.CharField(max_length=10)
course = models.ForeignKey(Course, on_delete=models.CASCADE)
class Assessment(models.Model):
course = models.ForeignKey(Course, on_delete=models.CASCADE)
assessment_name = models.CharField(max_length=10)
objectives = models.ManyToManyField('Objective')
class Objective(models.Model):
course = models.ForeignKey(Course, on_delete=models.CASCADE)
objective_name = models.CharField(max_length=10)
objective_description = models.CharField(max_length=30)
#views.py
def courses(request):
course_list = Course.objects.order_by('course_name')
context = {'course_list': course_list}
if request.method == 'POST':
details = CourseForm(request.POST)
if details.is_valid():
course = details.save(commit=False)
course.save()
form = CourseForm(None)
context['form'] = form
return render(request, "gradebook/courses.html", context)
else:
context['form'] = details
return render(request, "gradebook/courses.html", context)
else:
form = CourseForm(None)
context['form'] = form
return render(request, "gradebook/courses.html", context)
def addassessment(request, course_id):
course_list = Course.objects.order_by('course_name')
this_course = Course.objects.get(id=course_id)
objectives = Objective.objects.filter(course=this_course).order_by('objective_name')
context = {'this_course': this_course}
context['objectives'] = objectives
context['course_list'] = course_list
if request.method == 'POST':
form = AssessmentForm(request.POST)
if form.is_valid():
assess = form.save(commit=False)
# save the course that the objective belongs to
assess.course = this_course
assess.save()
form.save_m2m()
return render(request, "gradebook/courses.html", context)
else:
context['form'] = form
return render(request, "gradebook/addassessment.html", context)
else:
form = AssessmentForm(None)
form.fields["objectives"].queryset = Objective.objects.filter(course=this_course)
context['form'] = form
return render(request, "gradebook/addassessment.html", context)
#forms.py
class AssessmentForm(ModelForm):
class Meta:
model = Assessment
fields = ('assessment_name', 'objectives',)
class CourseForm(ModelForm):
class Meta:
model = Course
fields = ["course_name"]
def clean(self):
super(CourseForm, self).clean()
course_name = self.cleaned_data.get('course_name')
if course_name and Course.objects.filter(course_name__iexact=course_name).exists():
self.add_error(
'course_name', 'A course with that course name already exists.')
if len(course_name) > 10:
self.add_error(
'Your course name cannot be longer than 10 characters')
return self.cleaned_data
#courses template: course.html
<div class="container">
<div class="row">
<div class="twelve columns">
<h1>Courses</h1>
</div>
</div>
<div class="row">
<div class="col-md-12">
{% if course_list %}
<ul>
{% for course in course_list %}
<li><div class = "row">
<div class = "col-md-3">
{{ course.course_name }}
</div>
</div></li>
{% endfor %}
</ul>
{% else %}
<p>No Courses are available.</p>
{% endif %}
</div>
</div>
<div class="row">
<div class="col-md-3">
<p>Create a new course</p>
</div>
<div class="col-md-3">
<form action="{% url 'gradebook:courses' %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<div class="form-group">
<button type="submit" class="btn btn-primary">
Submit
</button>
</div>
</form>
</div>
</div>
</div>
#addassessment template: addassessment.html
<div class="container">
<div class="row">
<div class="twelve columns">
<h1>{{ this_course }}</h1>
</div>
</div>
<div class="row">
<div class="col-md-3">
<p>Add an assessment to your class</p>
</div>
<div class="col-md-3">
<div class="form-group">
<form action="" method="post">
{% csrf_token %} {{ form|crispy }}
<div class="form-group">
<button type="submit" class="btn btn-secondary">Submit</button>
</div>
</form>
</div>
</div>
</div>
</div>
There are no error messages.
When you submit your assessment form at http://127.0.0.1:8000/gradebook/addassessment/7/ your sending a post request back to your addassessment view function to process your form which you know. The url will still be the same as a result, which is what you are seeing.
I would suggest against returning the courses template if your assessment form is valid in the way you have written
#inside addassessment view function
return render(request, "gradebook/courses.html", context)
If you are just wanting to redirect to the courses view upon successfully saving the assessment form I suggest using the redirect shortcut.
# add to your import
from django.shortcuts import render, redirect
#inside addassessment view function - replacing "return render(request, "gradebook/courses.html", context)"
return redirect(courses)
This will send your request object to the courses view function. The redirect will use a GET action instead of a post so you'll just see what you would normally at http://127.0.0.1:8000/gradebook/courses/. This will also be the url!
So I'm trying to make a form to appear after the user is authenticated. When the user authenticated then the form appears on the home page but it never appears. I'm pretty sure I'm doing something wrong either in paths or view but can't figure this out. When I do the same code to external new template it works fine but I want the form to appear on the same page. Here is the code:
views.py
def vpn(request):
form = vpn_form(request.POST or None)
if form.is_valid():
form.save()
context ={
'form': form
}
return render(request, 'loginas/home.html', context)
urls.py
urlpatterns = [
# /
path('', views.home, name='home'),
# TEMPORARY
path('signin', views.sign_in, name='signin'),
path('signout', views.sign_out, name='signout'),
path('callback', views.callback, name='callback'),
path('', views.vpn, name='vpn'),
models.py
class VPN(models.Model):
name = models.CharField(max_length=125)
surname = models.CharField(max_length=125)
description = models.TextField()
date_to = models.DateField()
date_from = models.DateField()
forms.py
from .models import VPN
class vpn_form(forms.ModelForm):
class Meta:
model = VPN
fields = ('name', 'surname', 'description', 'date_to', 'date_from')
home template
{% extends "loginas/layout.html" %}
{% load static %}
{% block content %}
<div class="container">
<h1 class="d-flex justify-content-center"> </h1>
<p class="d-flex justify-content-center"></p>
{% if user.is_authenticated %}
<form>
{{form.as_p}}
</form>
{% else %}
<div class="d-flex justify-content-center">
Login
</div>
{% endif %}
{% endblock %}
And the page just loads empty no form present no errors in the console. Any help how to do this would be great
i want to create a todolist app with django.
i created a form for list model but when the user click on submit to submit a list, the form is'nt saved, why?
this is views.py
i have created an instance of the form and set the user field to it and then save the instance but fact it does'nt
def index(request):
if request.user.is_authenticated:
user_ = User.objects.get(username=request.user.username)
lists = user_.user.all()
form = listForm()
if request.method == "POST":
form = listForm(request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.user = request.user
instance.save()
return HttpResponseRedirect(reverse("index"))
context = {'lists':lists, 'form':form}
return render(request, 'todolists/index.html', context)
else:
return render(request, 'todolists/login.html')
this is index template
{% extends "todolists/layout.html" %}
{% block body %}
{% if user.is_authenticated %}
<div class="center-column">
<form method="POST" action="{% url 'index' %}">
{% csrf_token %}
{{form.title}}
<input type="submit" class="btn btn-info">
</form>
<div class="todo-list">
{% for list in lists %}
<div class="item-row">
<a class="btn btn-sm btn-info" href="{% url 'update' list.id %}">update</a>
<a class="btn btn-sm btn-danger" href="{% url 'update' list.id %}">delete</a>
<span>{{list}}</span>
</div>
{% endfor %}
</div>
</div>
{% endif %}
{% endblock %}
this is urls.py
from django.urls import path
from .import views
urlpatterns = [
path('', views.index, name='index'),
path('update/<str:id>/', views.update, name='update'),
path("login", views.login_view, name="login"),
path("logout", views.logout_view, name="logout"),
path("register", views.register, name="register"),
]
this is models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class User(AbstractUser):
pass
class list(models.Model):
title = models.CharField(max_length=200)
finished = models.BooleanField(default=False)
timestamps = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="user")
def __str__(self):
return self.title
here is the form code
class listForm(forms.ModelForm):
title= forms.CharField(label=mark_safe("<span style='color:white;'>Title:</span>"),
widget= forms.TextInput(attrs={'placeholder':'Add new task...', 'class':'form-control'}))
finished= forms.BooleanField(label=mark_safe("<span style='color:white;'>Finished:</span>"),
widget= forms.CheckboxInput(attrs={'style':'width:25px;'}))
class Meta:
model = list
fields = '__all__'
Try updating your template file {{ form.title }} to {{ form }} as mentioned in django docs here is the link
Update your forms.py file if want only title field in the HTML
class listForm(forms.ModelForm):
title= forms.CharField(label=mark_safe("<span style='color:white;'>Title:</span>"),
widget= forms.TextInput(attrs={'placeholder':'Add new task...', 'class':'form-control'}))
class Meta:
model = list
fields = ('title', )