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.
Related
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!
The post requests from the frontend do not get saved in the database, without any error shown. However, when I manually add entries from the admin panel, it shows on the frontend.
My index.html(form part):
<form class="main__input--form" method="POST">
{% csrf_token %}
<p class="main__input--text">
<textarea name="content" id="content" class="main__input--content" cols="35" rows="8" aria-label="Entry content" placeholder="Enter text here..."></textarea>
</p>
<button class="main__input--submit" type="submit">Vent</button>
</form>
My extension of index which loops through the database entries:
{% for obj in all_vents %}
<div>
<h1>{{obj.vent}}</h1>
</div>
<br />
{% endfor %}
My models.py:
class Vents(models.Model):
vent = models.CharField(max_length=10000)
def __str__(self):
return self.vent
My forms.py:
from django import forms
from .models import Vents
class VentForm(forms.ModelForm):
class Meta:
model = Vents
fields = ['vent']
My views.py:
from django.shortcuts import render, redirect
from .forms import VentForm
from .models import Vents
def ventout(request):
if request.method == "POST":
form = VentForm(request.POST or None)
if form.is_valid():
form.save()
return redirect("ventout")
else:
all_vents = Vents.objects.all()
return render(request, "ventout.html", {"all_vents": all_vents})
Views:
def ventout(request):
all_vents = Vents.objects.all()
if request.method == "POST":
form = VentForm(request.POST or None)
if form.is_valid():
form.save()
return redirect("ventout")
else:
form = VentForm()
context = {"all_vents": all_vents, "form":form}
return render(request, "ventout.html", context)
Template:
<form class="main__input--form" method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="main__input--submit">Vent</button>
</form>
you could install/use "crispy_forms_tags" to make the form look better,
https://django-crispy-forms.readthedocs.io/en/latest/index.html
if you want to go further you could install/use "widget_tweaks"
https://pypi.org/project/django-widget-tweaks/
Your index.html from part should have {{ form }} form tag, as I guess.
Try Using following code
<form class="main__input--form" method="POST">
{% csrf_token %}
{{ form }}
<p class="main__input--text">
<textarea name="content" id="content" class="main__input--content"
cols="35" rows="8" aria-label="Entry content" placeholder="Enter text here...">
</textarea>
</p>
<button class="main__input--submit" type="submit" value="Submit">Vent</button>
</form>
I can't post in Django, because when I import an image it doesn't work for me. it tells me that there's no file selected but I selected one.
This is the post model that I created, models.py file:
class Post(models.Model):
publisher = models.ForeignKey(User,on_delete=models.CASCADE)
caption = models.CharField(max_length=100)
date_created = models.DateTimeField(default=timezone.now())
image = models.ImageField(upload_to="post_images")
def __str__(self):
return self.caption
here's the forms.py file for the Post model:
from django import forms
from .models import Post
class CreatePostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['caption','image']
here's the Publish function in views.py file which implements the logic for my publish feature:
#login_required
def Publish(request):
if request.method == "POST":
form = CreatePostForm(request.POST,request.FILES)
if form.is_valid():
form.publisher = request.user
form.save()
return redirect("home")
else:
form = CreatePostForm()
return render(request,"posts/publish.html",{
"form":form,
})
int the urls.py file:
from django.urls import path
from . import views
urlpatterns = [
path('publish/',views.Publish,name="publish"),
path('',views.home,name="home"),
]
and here's in html template:
{% extends "users/base.html" %}
{% load crispy_forms_tags %}
{% block title %}create{% endblock title%}
{% block content %}
<div class="container-fluid">
<div class="row">
<div class="col-sm-6 col-md-5 authentification">
<div class="form-header">
<h1>
publish
</h1>
</div>
<div class="form-body">
<form method="POST">
<fieldset class="form-group" enctype="multipart/form-data">
{% csrf_token %}
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button type="submit" class="btn btn-primary form-control">publish</button>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock content %}
the Django version used is 2.2 and the Python 3.8. and Windows 10 Pro
You should alter the .publisher attribute of the .instance wrapped in the form, not the form itself, so:
#login_required
def Publish(request):
if request.method == 'POST':
form = CreatePostForm(request.POST,request.FILES)
if form.is_valid():
form.instance.publisher = request.user
form.save()
return redirect('home')
else:
form = CreatePostForm()
return render(request,'posts/publish.html',{
'form': form,
})
Since you are submitting both files and data, you should specify the enctype=… attribute [mdn] in the <form>:
<form enctype="multipart/form-data" method="POST">
…
</form>
Note: Django's DateTimeField [Django-doc]
has a auto_now_add=… parameter [Django-doc]
to work with timestamps. This will automatically assign the current datetime
when creating the object, and mark it as non-editable (editable=False), such
that it does not appear in ModelForms by default.
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
I'm new to django and I'm trying to create forms, but whenever I run this I end up with a submit button with no input fields. If you see any other mistakes, don't hesitate to tell me.
views.py
from django.shortcuts import render
from django.http import HttpResponse
from .forms import *
def form(request):
if request.method == 'POST':
form = forma(request.POST)
if form.is_valid():
return HttpResponseRedirect('index.html')
else:
form = forma()
return render(request, 'action.html', {"form":form})
def action(request):
return render(request, 'action.html')
**forms.py **
from django import forms
class forma(forms.Form):
your_name = forms.CharField(label='Your name', max_length=100)
index.html
<body>
<section id = "sec">
<h1>... </h1>
<h3> ... </h3>
<h4> ... <h4>
<button> ... </button>
<p>{{hola}} alo {{darwich}}</p>
<form action= "action.html" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
</section>
<body>