how to extend class bassed view - python

I've crated class-based-view which shows content of the post.I also added the ability to make comments there, however the comment form dosn't work.
views.py
class PostDetailView(DetailView):
model=Post
template_name='blogdetail.html'
pk_url_kwarg='id'
def comments(request):
comments=post.comments.all()
new_comment=None
if request.method=="POST":
comment_form=CommentForm(data=request.POST)
if comment_form.is_valid():
new_comment=comment_form.save(committ=False)
new_comment.post=post
new_comment.save()
else:
comment_form=CommentForm()
return render(request, 'allblogs.html', {'comments':comments, 'comment_form':comment_form,
'new_comment':new_comment})
forms.py
class CommentForm(forms.ModelForm):
class Meta:
model=Comment
fields=['post','body']
blogdetail.html
{% extends 'base.html' %}
{% block content %}
<h1>{{post.title}}</h1>
<p>{{post.created_on}}</p>
<p>:{{post.author}}</p>
<p>{{post.text}}</p>
<form>
{{comment_form.as_p}}
<p><input type="submit" value="add"></p>
{% csrf_token %}
</form>
{% endblock content %}

class base views are not working this way.
If you look at your class, you didn't call your comment function.
I suggest you look at this page.
Besides that, for creating a URL for your author, I suggest you use get_absolute_url in your model and use it in your template like this:
{{ author.get_absolute_url }}
Hope that this answer is helped you.

Related

Django rendering Form object rather than form fields

Sure I've missed something obvious, but any help appreciated.
I have a form model:
class UserForm(forms.Form):
name = forms.CharField()
A view:
def userform(req):
context = {}
context['user_form'] = UserForm()
context['message'] = 'test message'
return render(req, 'apps/userform.html', context)
And a template:
{% extends 'base.html' %}
{% block title %} | User Form {% endblock %}
{% block content %}
<h1>Form page</h1>
<form method='POST'>
{% csrf_token %}
{{ user_form }}
<button type='submit'>Send</button>
</form>
{{ message }}
{% endblock %}
I'm pretty sure everything is connected correctly and imported as required - the 'message' property on context renders fine under the form.
However, {{ user_form }} in the template renders the actual Form object instance, rather than the actual form field I'm expecting. I see:
<userform.views.UserForm object at 0x7fcab17e5c10>
Then the form submit button.
What have I missed?
Django 4, if that matters.
So the issue was I had a class based view in the views file with the same name as my Form class - I guess that was getting instantiated, rather than the Form class. Commented out the CBV and everything worked.
If I'd looked harder at the error message, I would have probably seen this sooner as the instantiated object is clearly in the views folder, rather than the forms one...

How to use <int:pk> in class-based general views

bookinstance_form.html
{% extends "catalog/base_generic.html" %}
{% block content %}
<form action="" method="post">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Submit" />
</form>
{% endblock %}
urls.py
path('bookinstance/create/', views.BookInstanceCreate.as_view(), name='bookinstance_create'),
path('bookinstance/<uuid:pk>/update/', views.BookInstanceUpdate.as_view(), name='bookinstance_update'),
path('bookinstance/<uuid:pk>/delete/', views.BookInstanceDelete.as_view(), name='bookinstance_delete'),
views.py
class BookInstanceCreate(CreateView):
model = BookInstance
fields = '__all__'
class BookInstanceUpdate(UpdateView):
model = BookInstance
fields = '__all__'
class BookInstanceDelete(DeleteView):
model = BookInstance
success_url = reverse_lazy('catalog:books')
https://developer.mozilla.org/zh-CN/docs/Learn/Server-side/Django/Forms has all course
How to use int:pk in class-based general views, adding bookinstance needs to be associated with Book, so I need to know book.id, but I don't know how to write it in views.BookInstanceCreate.
If i understand your question. Every time you fill some model Django automaticly create ID for him. You can call this using int:pk tag. Use classic href
{{ url "bookinstance_update" BookInstance.id }} and make query of your books - >
{% for something in BookInstamce%} i Hope thats what you asked for.

Comment isn't getting deleted

I made a comment model for a blog and I wanted to give the user a way to delete the comment so I made a function based view for it but it didn't work so I decided to use a class based view but both of the views give the same error. the only thing that happens is that the url gets a ? after it and the page just refreshes as it is. The function based and class based views are both given below
func based
def comment_delete(request, pk):
comment_to_delete=get_object_or_404(comment,pk=pk)
if request.method=='POST':
post_url=comment_to_delete.content_object.get_absolute_url()
comment_to_delete.delete()
messages.success(request, 'Your comment has been deleted')
return HttpResponseRedirect(post_url)
context={
'comment':comment_to_delete
}
return render(request, 'blog/confirm_delete.html', context)
class based
class DeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
model = comment
success_url = '/'
def test_func(self):
comment= self.get_object()
if self.request.user == comment.user:
return True
return False
html of confirm page
{% extends 'blog/base.html' %}
{% block content %}
<form>
<p>are you sure you want to delete {{ comment }}</p>
<input type="submit" value="confirm" >
</form>
{% endblock %}
models.py
class comment(models.Model):
post=models.ForeignKey(Blog, on_delete=models.CASCADE)
user=models.ForeignKey(User, on_delete=models.CASCADE)
content=models.TextField(max_length=160)
timestamp=models.DateTimeField(auto_now_add=True)
def __str__(self):
return '{}-{}'.format(self.post.title,str(self.user.username))
def get_absolute_url(self):
return reverse('comment', kwargs={"pk": self.pk})
You need to add a post request to your form. Post requests need tokens to protect from Cross Site Request Forgeries. Normally a token is passed with every post request.
<form method="POST">
{% csrf_token %}
<p>are you sure you want to delete {{ comment }}</p>
<input type="submit" value="confirm" >
</form>
The problem is in your template, not your views. You need to add method="post" to the form to do a POST request, and add {% csrf_token %} to prevent a CSRF error.
<form method="post">
{% csrf_token %}
<p>are you sure you want to delete {{ comment }}</p>
<input type="submit" value="confirm" >
</form>

I am not able to save the form data to databse in django

I want to add data through form and see it queried in my template
blog url:
urlpatterns = [
url(r'^admin/',admin.site.urls),
url(r'^blog/',include('content.urls',)),
]
content url:
urlpatterns = [
url(r'^add/$', views.add_content, name='content'),
]
models.py
from django.db import models
class AddContent(models.Model):
content_name = models.CharField(max_length=100, default='', blank=False, unique=True)
def __str__(self):
return self.content_name
forms.py
from django import forms
from .models import AddContent
class AddContentForm(forms.ModelForm):
class Meta:
model = AddContentModel
fields = [
"content_name",
]
views.py
def add_content(request):
form = AddContentForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
return redirect("/blog/content/")
content_data = AddContent.objects.all()
context = {
"form":form,
"content":content_data,
}
return render(request, "add_content.html", context)
def view_content(request):
view_data = AddContent.objects.all()
context = {
"show_content":view_data,
}
return render(request, 'show_content.html', context)
templates:
add_content.html
{% extends 'base.html' %}
{% block content %}
<form method='POST' action="/blog/content/">
{% csrf_token %}
{{ form.as_p }}
<input type='submit' value='Add Content'/>
<h3>Recent content</h3>
{% for show in show_content %}
<p>{{ show.content_name }}</p>
{% endfor %}
{% endblock %}
The form data is not being saved, when I add it through admin interface it gives the result but form fails.
(this is just some useless content that I am writing in the bracket, stackoverflow didn't allow me posting as it looks like my post is mostly code; please add more details it said but i think the code has lot of details and i cant write anything just for the sake of length)
Your model form should look like this
from django import forms
from .models import AddContent
class AddContentForm(forms.ModelForm):
class Meta:
model = AddContent
fields = [
"content_name",
]
You've defined the wrong model name in the Meta class of model form. It should be AddContent not AddContentModel
I'm new to django too, but don't you need to specify the request inside the functions in views.py like :
def add_content(request):
if(request.method == 'POST'):
# rest of code here
Your form does not post to the view that saves the data; it posts directly to the view_content view, which ignores the data completely.
You can set the form action to "." to get it to post back to the same view that rendered it.
(As an additional point, you should avoid hard-coding URLs. Use the {% url %} tag in templates, and the reverse() function in views, to output URLs based on view names.)
First :
Correct the redirect() in your form.
return redirect("add_content", request.POST= None)
Second : you need to specify a URL for the content view : view_content
url(r'^content/$', views.view_content, name='content'),
And You need a template to render content (show_content.html :
{% extends 'base.html' %}
{% block content %}
<h3>Recent content</h3>
{% for show in show_content %}
<p>{{ show.content_name }}</p>
{% endfor %}
{% endblock %}
Edit :
Your form is not well defined. I edit my answer to make it complete :
You have to correct the model in your form (AddContent not AddContentModel) :
class Meta:
model = **AddContent**
fields = [
"content_name",
]

Django - saving form to the built in database SQLite

This is my first time using Django and I am very simply trying to save text to the database. I have created the table inputs in the database.
I am getting the following error;
Error - Page not found (404)
My code is as follows;
Models.py
from django.db import models
class Input(models.Model):
waist = models.IntegerField(default=0)
height = models.IntegerField(default=0)
def __unicode__(self):
return "{0} {1} {2}".format(
self, self.waist, self.height)
forms.py
class InputForm(forms.ModelForm):
class Meta:
model = Input
fields ={
'waist',
'height'
}
views.py
def InputView(request):
if request.POST:
form = InputForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('account/input')
else:
form = InputForm()
args = {'form' : form}
return render(request,'accounts/input.html', args)
urls.py
url(r'^input/$',views.InputView, name='view_input')
input.html
{% extends 'base.html' %}
{% block head %}
<title> Edit Profile </title>
{% endblock %}
{% block body %}
<div class="container">
<h1> Enter Body Details </h1>
<br>
<br>
<form action="account/input" method="post">
{% csrf_token %}
<ul>
{{form.as_ul}}
</ul>
<input type="Submit" name="submit" value="submit"/>
</form>
</div>
{% endblock %}
If any one can help it would be greatly appreciated.
HttpResponseRedirect('account/input')
you need to add one more '/' to the beginning like
HttpResponseRedirect('/account/input')
Another way to do it is to use reverse() so if you change the URL you don't have to change your code and you avoid mistakes entering the URL.
Instead of
HttpResponseRedirect('/account/input')
use
HttpResponseRedirect(reverse('view_input'))
remember to add the import
from django.urls import reverse

Categories

Resources