Model form is not able to save in database - python

I am a beginner in Django
I want to save a form data in database but i am not able to save, followed some tutorials also.
form.py:
from django.forms import ModelForm
from .models import *
class listsForm(ModelForm):
class Meta:
model = todo
fields = "__all__"
views.py:
from django.shortcuts import render
from .models import *
from .form import *
def index(request):
lists = todo.objects.all()
form = listsForm()
context = {
'lists':lists,
'form':form,
}
if request.method == 'POST':
form = listsForm(request.POST)
if form.is_valid:
form.save()
return render(request, 'index.html', context)
models.py:
from django.db import models
class todo(models.Model):
title = models.CharField(max_length=200)
description = models.TextField(null=True, blank=True)
created = models.DateField(auto_now_add=True)
def __str__(self):
return self.title

Why are you rendering listsForm?
Your form should be in the template not rendered!
In index.html, your form should looks like the following:
<form action="{% url 'create_todo' %}" method="POST">
{% csrf_token %}
<div class="form-group">
<label for="title">Title</label>
<input type="text" name="title" class="form-control" id="title" required></div>
<div class="form-group">
<label for="Description">Description</label>
<textarea name="description" class="form-control" id="description" ></textarea></div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
In views.py
def index(request):
return render(request, 'index.html')
def create_todo(request):
if request.method == 'POST':
form = listsForm(request.POST)
if form.is_valid():
form.save()
return redirect('index')
In urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('create_todo/', views.create_todo, name='create_todo')
]
You will still need to render existed todos, preferably in another template.
So in views.py
def alltodos(request):
todos = Todo.objects.all()
return render(request, 'index.html', {'todos':todos})
In index.html, above form or after it, it doesn't matter, just for clear visibility
<div class="row justify-content-center mt-5">
<div class="col-md-10">
{% if todos %}
<div class="list-group">
{% for todo in todos %}
<a class="list-group-item list-group-item-action><b>{{ todo.title }}</b>{{ todo.description|truncatechars:30 }}{% endif %}</a>
{% endfor %}
</div>
{% else %}
<div class="text-center">
<h2>Looks like you don't have any todos!</h2>
<br>
</div>
{% endif %}
</div>
</div>
In urls.py add
path('todos', views.alltodos, name='alltodos'),
Advanced project of mine

I have find out why it was not working,
I was using <input type="button"> for submit button
but when I changed it to <button type="submit"> it works.

Related

User Specific Page in TODO List

I am making a simple todolist application but while I am trying to create user specific pages, I am unable to add a new task probably beacause database is not getting all required datas(i.e. owner of the task).
models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class value(models.Model):
task=models.CharField(max_length=200)
complete=models.BooleanField(default=False)
created=models.DateTimeField(auto_now_add=True)
owner=models.ForeignKey(User,on_delete=models.PROTECT)
def __str__(self):
return self.task
views.py
from http.client import HTTPResponse
from urllib import response
from django.shortcuts import render,redirect
from todo.models import value
from django.http import HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
# Create your views here.
from .forms import TitleForm
from django.urls import reverse
from django.contrib.auth.models import User
def home(request):
values=value.objects.all()
form=TitleForm()
if request.method=='POST':
form=TitleForm(request.POST)
if form.is_valid():
new_data=form.save(commit=False)
new_data.owner=request.user()
new_data.save()
return HttpResponseRedirect('/')
context={'form':form,'values':values}
return render(request,'home.html',context)
#update
def update(request,id):
ggwp=value.objects.get(id=id)
form=TitleForm(instance=ggwp)
if request.method == 'POST':
form=TitleForm(request.POST,instance=ggwp)
if form.is_valid:
form.save()
return redirect('home')
context={'form':form,}
return render(request,'update.html',context)
#delete
def delete_data(request, id ):
if request.method=="POST":
ggwp=value.objects.get(id=id)
ggwp.delete()
return HttpResponseRedirect(reverse('deldata', kwargs={'id':id}))
return redirect("/")
forms.py
from django import forms
from django.forms import ModelForm
from .models import value
from django import forms
class TitleForm(forms.ModelForm):
class Meta:
model= value
fields='__all__'
urls.py(app)
from django.conf.urls import url
from django.urls import path
from . import views
urlpatterns=[
path('',views.home,name='home'),
path('delete/<str:id>', views.delete_data,name='deldata'),
path('update/<str:id>',views.update,name='update')
]
home.html(main page)
<form method="POST">
{% if user.is_authenticated %}
Hello,{{user.username}}<br>
Logout
{% else%}
Register
login
{% endif %}
</form>
<div class="p-3 mb-2 bg-warning text-dark" style="text-align: center;">
<form action="/" method="post" >
{% csrf_token %}
{{form.task}}
<input class='btn btm-sm btn-info' type='submit' name='add' value="add" >
</form>
{% for val in values %}
{% if val.complete == True %}
<s>{{val}}</s>
{% else %}
<span>{{val}}</span>
{% endif %}
<form action="{% url 'deldata' val.id %}" method="POST" class="in-line">
{% csrf_token %}
<input class='btn btm-sm btn-danger' type="submit" name="delete" value="delete">
<a class='btn btm-sm btn-info' href="{% url 'update' val.id %}" >Update</a>
</form>
{% endfor %}
</div>
Home.html looks like this:
todo
When i want to add a task and click on add, nothing really happens. It only redirects back to same page but not data is inserted in database.
If there are problems in questions, I am really sorry!
Home.html :
<div class = "divname">
{% if user.is_authenticated %}
Hello,{{user.username}}<br>
Logout
{% else%}
Register
login
{% endif %}
</div>
<div class="p-3 mb-2 bg-warning text-dark" style="text-align: center;">
<form method="POST" >
{% csrf_token %}
{{form}}
<input class='btn btm-sm btn-info' type='submit' name='add' value="add" >
</form>
{% for val in values %}
{% if val.complete == True %}
<s>{{val}}</s>
{% else %}
<span>{{val}}</span>
{% endif %}
<form action="{% url 'deldata' val.id %}" method="POST" class="in-line">
{% csrf_token %}
<input class='btn btm-sm btn-danger' type="submit" name="delete" value="delete">
<a class='btn btm-sm btn-info' href="{% url 'update' val.id %}" >Update</a>
</form>
{% endfor %}
</div>
UPDATE1 : EXCLUDING USER IN FORM AND ADDING THE CURRENT USER IN VIEWS
#Do not add Owner into the model form fields
forms.py:
from django import forms
from django.forms import ModelForm
from .models import value
from django import forms
class TitleForm(forms.ModelForm):
class Meta:
model= value
fields=['task', 'complete', 'created']
Views.py:
def home(request):
values=value.objects.all()
form=TitleForm()
if request.method=='POST':
form=TitleForm(request.POST)
if form.is_valid():
new_data=form.save(commit=False)
new_data.owner=request.user
new_data.save()
return HttpResponseRedirect('/')
context={'form':form,'values':values}
return render(request,'home.html',context)

Django form in an extended template

I am very new to Django, I have a home template (home.html) which is extending a base template (base.html) with {% extends "base.html" %}.
base.html containts a contact form.
<form id="email-form" name="email-form" data-name="Email Form" method="post">
{% csrf_token %}
<div>
<label for="Name-2" class="field-label">Full name</label>
{% render_field form.name class+="text-field w-input" %}
</div>
<div>
<label for="Email-2" class="field-label">Email address</label>
{% render_field form.from_email class+="text-field _2 w-input" %}
</div>
<div>
<label for="Phone-2" class="field-label">Phone number</label>
{% render_field form.phone class+="text-field _2 w-input" %}
</div>
<div>
<label for="Timeline" class="field-label">More information</label>
<div>
{% render_field form.message class+="text-field area w-input" %}
</div>
</div>
<div class="algin-center form-actions">
<input type="submit" value="Send Message" data-wait="Please wait..." class="button full w-button">
</div>
</form>
views.py
from django.core.mail import send_mail, BadHeaderError
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, redirect
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(required=True)
from_email = forms.EmailField(required=True)
phone = forms.CharField(required=True)
message = forms.CharField(widget=forms.Textarea, required=True)
def homeView(request):
if request.method == 'GET':
form = ContactForm()
else:
form = ContactForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
phone = form.cleaned_data['phone']
from_email = form.cleaned_data['from_email']
message = form.cleaned_data['message']
try:
send_mail(name, message, from_email, ['email#email.com'])
except BadHeaderError:
return HttpResponse('Invalid header found.')
return redirect('success')
return render(request, "home.html", {'form': form})
The form is rendering fine, however, when I click the submit button nothing happens. I'm guessing this is because the form is not in the homeView directly but through extension, but I have no idea how to fix it, is it possible to have the form in an extended view?

How to you put a checkbox in a django.contrib.auth.forms UserCreationForm

I have multiple fields in my Django UserCreationForm including the already included username, password 1, and password 2. I have also added and email field. I am unable to add a checkbox.
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(required=True)
is_teacher = forms.BooleanField(required=True)
class Meta:
model = User
fields = ['is_teacher', 'username', 'email', 'password1', 'password2']
I want there to be a checkbox to declare if the user wants to register as a teacher or as a student.
{% extends 'base.html' %}
{% block content %}
<div class="container row">
<form method="POST" class='input-field col s6 offset-s3' >
{% csrf_token %}
<fieldset>
<legend>
Sign Up:
</legend>
{{form.as_p}}
</fieldset>
<br>
<button class="btn waves-effect waves-light green accent-2" type="submit" name="action">Submit
<i class="material-icons right">send</i>
</button>
<br><br>
<div>
<small>
Already have an account? <a href='{% url "login"%}'>Sign In</a>
</small>
</div>
</form>
</div>
{% endblock %}
from django.shortcuts import render, redirect
from .forms import UserRegisterForm
from django.contrib import messages
from django.contrib.auth.decorators import login_required
# Create your views here.
def register(request):
if request.method == "POST":
form = UserRegisterForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Account created for {username}!')
return redirect('/')
else:
form = UserRegisterForm()
return render(request, 'users/register.html', {'form': form})
#login_required
def profile(request):
return render(request, 'users/profile.html')
You already added the BooleanField in django form here:
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(required=True)
is_teacher = forms.BooleanField(required=True)
class Meta:
model = User
fields = ['is_teacher', 'username', 'email', 'password1', 'password2']
looks good you only need to add the it to your html
{% extends 'base.html' %}
{% block content %} <div class="container row">
<form method="POST" class='input-field col s6 offset-s3' >
{% csrf_token %}
<fieldset>
<legend>
Sign Up:
</legend>
{{form.as_p}}
</fieldset>
<br>
<button class="btn waves-effect waves-light green accent-2" type="submit" name="action">Submit
<i class="material-icons right">send</i>
</button>
<br><br>
<div>
<small>
Already have an account? <a href='{% url "login"%}'>Sign In</a>
</small>
</div>
<div name="new is teacher checkbox">
{{form.is_teacher}}
</div>
</form>
</div> {% endblock %}
You can access the value of is_teacher in views too by forms.cleaned_data.get('is_teacher')

Update a Profile picture

so i'm working on little django application where users can view and modify there profile ,but i didn't know how to provide a button under the profile picture that allows the user to choose a new one and when he chooses it redirect him to the same page with the new profile picture ,any help or ideas will be usefull , tnks !!
here's what i tried :
forms.py
class picture_form(forms.ModelForm):
class Meta:
model=Profile
fields=('image',)
views.py
def profile(request):
if request.method == 'POST':
form = picture_form(request.POST, request.FILES)
if form.is_valid():
profile = Profile.objects.get(user=request.user)
profile.image = form.cleaned_data['image']
profile.save()
return redirect(reverse('profile'))
else:
for usr in User.objects.all():
if request.user.get_full_name() == usr.get_full_name():
prf = Profile.objects.filter(user=usr)
form = picture_form()
return render(request, 'store/profile.html', {'profile': prf, 'form': form})
template
{% if prf.image %}
<div class="profile-img">
<img src="{{ prf.image.url }}" id="prf_img" alt=""/>
</div>
{% else %}
<div class="profile-img">
<img src="{% static 'img/empty-profile-picture.png' %}" id="prf_img" alt=""/>
</div>
{% endif %}
<!--<a href="{% url 'upload_picture' %}"> <div class="file btn btn-lg " >
Change Photo
<input type="file" name="file"/>
</div></a> -->
<form method="post" action="{% url 'profile' %}" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" class="btn btn-outline-success" value="upload">
</form>
</div>
Django has an awesome generic editing view called UpdateView. You can do something like this:
models.py
class Profile(models.Model):
image = models.ImageField()
views.py
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic.edit import UpdateView
#method_decorator(login_required, name='dispatch')
class UpdateProfileView(UpdateView):
model = Profile
fields = ['image']
template_name_suffix = '_update_form'
success_url = ''
def form_valid(self, form):
form.instance.user = self.request.user
return super().form_valid(form)
profile_update_form.html
<form method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Update">
</form>
urls.py
from . import views
path('<int:pk>/update/', views.UpdateProfileView.as_view(), name='profile-update')

Cannot see the form input field at all

I would like to collect the content that user input, then change the database using POST method. But i just blank when i clicked post button on the website.
Here's the views.py
class PostTweet(View):
def post(self, request, username):
form = TweetForm(request.POST)
print form.is_valid()
print request.POST
print form.errors
if form.is_valid():
user = User.objects.get(username=username)
tweet = Tweet(text=form.cleaned_data['text'],
user=user,
country=form.cleaned_data['country'])
tweet.save()
return HttpResponseRedirect('/user/'+username)
else:
form = TweetForm()
return render(request, 'profile.html', {'form':form})
class Profile(View):
"""
User Profile page reachable from /user/<username> URL
"""
def get(self, request, username):
params = {}
user = User.objects.get(username = username)
tweets = Tweet.objects.filter(user=user)
params["tweets"] = tweets
params["user"] = user
return render(request, 'profile.html', params)
forms.py
from django import forms
class TweetForm(forms.Form):
text = forms.CharField(widget=forms.Textarea, max_length=160)
country = forms.CharField(widget=forms.HiddenInput(),required=False)
profile.html
{% extends "base.html" %}
{% block content %}
<div class="row clearfix">
<div class="col-md-6 col-md-offset-3 column">
<form id="form" method="POST" action="post/">{% csrf_token %}
<div class="col-md-8 fieldWrapper">
{{ form }}
<span class="input-group-btn">
<button class="btn btn-default" type="submit">Post</button>
</span>
</div>
</form>
</div>
<h3> </h3>
<div class="col-md-12 column">
{% for tweet in tweets %}
<div class="well">
<span>{{ tweet.text}}</span>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
Here's the urls.py
from django.conf.urls import include, url, patterns
from django.contrib import admin
from tweets.views import Index, Profile, PostTweet, HashTagCloud
admin.autodiscover()
urlpatterns = patterns('',
url(r'^$', Index.as_view()),
url(r'^user/(\w+)/$', Profile.as_view()),
url(r'^admin/', include(admin.site.urls)),
url(r'^user/(\w+)/post/$', PostTweet.as_view()),
url(r'^hashTag/(\w+)/$', HashTagCloud.as_view()),
)
Anyone just give me a hint would be appreciated :-)
Adding {{form}} only should not render the field. form is an object with fields as properties. In your html try substituting {{form}} with {{form.text}}
Also you can try passing the object "form" as follows:
return render(request, 'profile.html', form = form)

Categories