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', )
Related
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 have been trying to add a view that uploades videos and displays them in the main template, well while adding code, I realized that the view that uploades the file isn't being rendered while the view that shows the uploded file in the template gets rendered but it doesnt show anything because nothing is being uploded. I dont know where the error might be but I think it is on the views.py, maybe the urls.py.
views.py
def upload(request):
if request.method == 'POST':
form = PostForm(request.POST, request.FILES)
if form.is_valid():
instance = form.save(commit=False)
instance.user = request.user
instance.save()
return redirect('home')
print('succesfully uploded')
else:
form = PostForm()
print('didnt upload')
return render(request, 'home.html', {'form': form})
def home(request):
contents = Post.objects.all()
context = {
"contents": contents,
}
print("nice")
return render(request, 'home.html', context)
urls.py
urlpatterns = [
path('', views.home, name='home'),
path('upload', views.upload, name='upload'),
]
models.py
class Post(models.Model):
text = models.CharField(max_length=200)
video = models.FileField(upload_to='clips', null=True, blank="True")
user = models.ForeignKey(User, related_name='imageuser', on_delete=models.CASCADE, default='username')
def __str__(self):
return str(self.text)
forms.py
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('text', 'video')
exclude = ['user']
home.html (uplodes the content and displays it)
<div class="user-content">
{% for content in contents %}
<li class="">{{ content.text }}
{% if content.video %}
<video class="video" width='400'>
<source src='{{ content.video.url }}' type='video/mp4'>
</video>
{% endif %}
</li>
{% endfor %}
</div>
<div class="uplodes">
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="text" name="text" placeholder="Add a comment..." required="" id="id_text">
<input type="file" name="video" id="id_video">
<button class="submit-button" type="submit">Save</button>
</form>
</div>
I am trying to create a student register page that allows the student to upload a profile photo. I am using Django User model and a StudentProfile model that has a OneToOne relation with User. Here are my codes:
student\models.py:
from django.db import models
from django.contrib.auth.models import User
class StudentProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,)
avatar = models.ImageField(upload_to='student_profile/', null=True, blank=True)
def __str__(self):
return self.user.username
students/form.py:
from django import forms
class ImageUploadForm(forms.Form):
profile_photo = forms.ImageField()
eLearning/views.py:
from django.contrib.auth import authenticate, login, get_user_model
from django.http import HttpResponse
from django.shortcuts import render, redirect
from .forms import LoginForm, RegisterForm
from students.forms import ImageUploadForm
from students.models import StudentProfile
User = get_user_model()
def register_page(request):
register_form = RegisterForm(request.POST or None)
photo_upload_form = ImageUploadForm(request.POST, request.FILES)
context = {
"register_form": register_form,
"photo_upload form": photo_upload_form
}
if register_form.is_valid():
# print(register_form.cleaned_data)
username = register_form.cleaned_data.get("username")
first_name = register_form.cleaned_data.get("first_name")
last_name = register_form.cleaned_data.get("last_name")
email = register_form.cleaned_data.get("email")
password = register_form.cleaned_data.get("password")
new_user = User.objects.create_user(
username, email, password,
first_name=first_name,
last_name=last_name,
)
if photo_upload_form.is_valid():
user = username
avatar = photo_upload_form.cleaned_data.get("profile_photo")
new_user_profile = StudentProfile.objects.create(user, avatar)
print(new_user)
return render(request, "auth/register.html", context)
auth/register.html:
{% extends "base.html" %}
{% load static %}
{% block content %}
{% load crispy_forms_tags %}
<div class="container">
<div class="row my-4">
<div class="col-5">
<form action="" method="post" class="form-control">
{% csrf_token %}
{{ register_form|crispy }}
<input type="submit" class="btn btn-default" value="Submit">
</form>
</div>
<div class="col-5">
<form method="post" enctype="multipart/form-data" class="form-control">
{% csrf_token %}
<input id="id_image" type="file" class="my-2" name="image">
{{ photo_upload_form|crispy }}
</form>
</div>
</div>
</div>
{% endblock %}
I am facing 2 problems:
1) The ImageUploadForm is not rendering on to register.html
2) A StudentProfile is not being created. User is being created fine.
I also tried replacing form with ModelForm for ImageUploadForm but I get a NULL constraint for student_user since Django doesn't what user for StudentProfile is.
I have been looking through Stack Overflow. All solutions are about how to upload a user image to Django admin but I haven't found anything that shows how to associate the uploaded image to User model during registration. Forgive me if this is a repeated question. Thanks.
In your eLearning/views.py:
the context you are passing to the html page the _ is missing
context = {
"register_form": register_form,
"photo_upload form": photo_upload_form
}
This will be the reason for the ImageUploadForm is not rendering on to register.html
It's should be like
context = {
"register_form": register_form,
"photo_upload_form": photo_upload_form
}
So I figured it out. The real issue was with the register.html code. The submit button only worked for the register_form so the photo upload form was not validating, hence student profile entry was not being created. Here's the updated code:
eLearning/views.py:
from students.forms import ImageUploadForm
from students.views import upload_pic
def register_page(request):
register_form = RegisterForm(request.POST or None)
photo_upload_form = ImageUploadForm(request.POST, request.FILES)
context = {
"register_form": register_form,
"photo_upload_form": photo_upload_form
}
if register_form.is_valid():
username = register_form.cleaned_data.get("username")
first_name = register_form.cleaned_data.get("first_name")
last_name = register_form.cleaned_data.get("last_name")
email = register_form.cleaned_data.get("email")
password = register_form.cleaned_data.get("password")
new_user = User.objects.create_user(
username, email, password,
first_name=first_name,
last_name=last_name,
)
upload_pic(request, photo_upload_form, username=username)
return render(request, "auth/register.html", context)
students/views.py:
from django.contrib.auth import get_user_model
from django.http import HttpResponseRedirect
from django.shortcuts import render, redirect, HttpResponse
from .models import StudentProfile
from .forms import ImageUploadForm
def upload_pic(request, form, username):
if request.method == 'POST':
if form.is_valid():
User = get_user_model()
user = User.objects.get(username=username)
avatar = form.cleaned_data.get('profile_photo')
new_user_profile = StudentProfile.objects.create(user=user, avatar=avatar)
new_user_profile.save()
register.html:
{% extends "base.html" %}
{% load static %}
{% block content %}
{% load crispy_forms_tags %}
<div class="container">
<div class="row my-4">
<div class="col-5">
<form action="" method="post" enctype="multipart/form-data" class="form-control">
{% csrf_token %}
{{ register_form|crispy }}
{{ photo_upload_form|crispy }}
<input type="submit" class="btn btn-default" value="Submit">
</form>
</div>
</div>
</div>
{% endblock %}
You have to make sure enctype="multipart/form-data" is inside your tags or the image upload form will not get validated. I would also recommend adding an image validation method to your form.py. Something Sachin pointed out earlier: image form and validation. Hope this helps.
recently I decide to add a comment block to my template in my django app but when I add it to my app , I faced to this error :
add_comment_to_post() got an unexpected keyword argument 'item_id'
my template.html:
{% block content %}
<form action="#" method="post" novalidate="novalidate">
{% csrf_token %}
{{ form.as_p }}
<div class="row">
<div class="col-md-4">
<p><label>Name*</label><input type="text" name="your-name" value=""
size="60" class=""
aria-required="true"
aria-invalid="false"></p>
</div>
<div class="col-md-4">
<p><label>Email*</label><input type="text" name="your-email"
value=""
size="60" class=""
aria-required="true"
aria-invalid="false"></p>
</div>
<div class="col-md-4">
<p><label>Website</label><input type="text" name="your-website"
value=""
size="60" class=""
aria-required="true"
aria-invalid="false"></p>
</div>
<div class="col-md-12">
<p><label>Message</label><textarea name="your-message" cols="60"
rows="3" class=""
aria-invalid="false"></textarea>
</p>
</div>
</div>
<div class="dividewhite2"></div>
<p>
<button type="button" href="{% url 'add_comment_to_post' pk=item.pk %}"
class="btn btn-lg btn-darker">Post Comment
</button>
</p>
</form>
{% endblock %}
my models.py :
from django.db import models
from datetime import date
from django.utils import timezone
# Create your models here.
class Blogs(models.Model):
main_image = models.ImageField(upload_to='Blogs/', help_text='This Image Is Gonna To Be Show At Blogs Page.',
blank=False, default='')
class Comment(models.Model):
post = models.ForeignKey('Blog.Blogs', on_delete=models.CASCADE, related_name='comments')
author = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
approved_comment = models.BooleanField(default=False)
def approve(self):
self.approved_comment = True
self.save()
def __str__(self):
return self.text
my form.py:
from django.forms import ModelForm
from .models import Blogs, Comment
class CommentForm(ModelForm):
class Meta:
model = Comment
fields = ('author', 'text',)
my views.py :
from django.shortcuts import render, get_object_or_404, redirect
from Blog.forms import CommentForm
from .models import Blogs, Comment
def item(request, items_id):
items = get_object_or_404(Blogs, pk=items_id)
return render(request, 'Blog/Items.html', {'item': items, 'comments': Comment})
def add_comment_to_post(request, pk):
post = get_object_or_404(Blogs, pk=pk)
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.save()
return redirect('post_detail', pk=post.pk)
else:
form = CommentForm()
return render(request, 'blog/Items.html', {'form': form})
and my urls.py:
from django.urls import path
from Blog import views
from Blog import models
urlpatterns = [
path('<int:item_id>/', views.add_comment_to_post, name='add_comment_to_post'),
path('<int:items_id>/', views.item, name='Itemz'),
]
I checked my code many times but I can't understand what is my problem.
is any body know to how can I add comment to my app or what is my problem?
In addition, I'm sorry for writing mistakes in my question.
change this
def add_comment_to_post(request, pk):
To:
def add_comment_to_post(request, item_id):
Then change everywhere inside the function you wrote pk to item_id
views.py
def add_comment_to_post(request, item_id):
post = get_object_or_404(Blogs, pk=item_id)
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.save()
return redirect('post_detail', pk=post.pk)
else:
form = CommentForm()
return render(request, 'blog/Items.html', {'form': form, 'item': post})
and in your template:
<button type="button" href="{% url 'add_comment_to_post' item.pk %}"
class="btn btn-lg btn-darker">Post Comment
</button>
Double check your url patterns maybe? Try:
urlpatterns = [
path('<int:pk>/', views.add_comment_to_post, name='add_comment_to_post'),
The variable name in your view method needs to match the variable name in the url. Therefore you need both to be pk or both to be item_id
The Problem happen because in urls.py there were two subject that was pass to one views.
change views to this :
urlpatterns = [
path('<int:pk>/', views.item, name='Itemz'),
]
then change html part to this :
{% if not user.is_authenticated %}
<p><a href="{% url 'login' %}" class="btn btn-gr btn-xs">Login To Send
A Command.</a></p>
{% endif %}
<div class="dividewhite2"></div>
{% if user.is_authenticated %}
<form method="post" novalidate="novalidate">
{% csrf_token %}
{{ form.as_p }}
<div class="dividewhite2"></div>
<p>
<button href="{% url 'Itemz' item.id %}" type="submit"
class="btn btn-lg btn-darker">Post Comment
</button>
</p>
</form>
{% endif %}
now the Django project will run properly.
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.