My success_url for my class based delete view does not work for some reason.
in views.py
# allows a user to delete a project
class DeletePost(DeleteView):
template_name = 'user_posts/post_delete.html'
model = Post
# return to the all posts list
success_url = reverse_lazy('posts_list')
# make sure the user is looking at its own post
def dispatch(self, request, *args, **kwargs):
obj = self.get_object()
if not obj.user == self.request.user:
raise Http404("You are not allowed to Delete this Post")
return super(DeletePost, self).dispatch(request, *args, **kwargs)
in urls.py:
path('list/', PostsListView.as_view(), name="posts_list"),
path('create-post/', CreatePostView.as_view(), name="post_create"),
path('update-post/<int:pk>', UpdatePost.as_view(), name="post_update" ),
path('delete-post/<int:pk>', DeletePost.as_view(), name="post_delete")
in the HTML file:
{% extends 'base.html' %}
{% block content %}
<form action="." method="POST" style="width:80%;">
{% csrf_token %}
<h3>Do You want to delete this post: "{{ object.title }}"</h3>
<input class="btn btn-primary" type="submit" value="Confirm"/>
Cancel
</form>
{% endblock content %}
whenever I click ok to delete a specific project, it doesn't return to the list of posts for:
image of the error on the webpage
you have not this URL indeed:
forum-posts/delete-post/
actually, you forgot to specify an integer indicating the post_id that must be deleted. for example:
forum-posts/delete-post/1/
Related
I need to iterate through a list of checkboxes and add a link to each of them. However I am not able to do so.
The template shows the complete form as a link istead of an individual checkbox being a list.
Below given is my code:
Here is my forms.py:
class GetTaskDescription(forms.Form):
get_tasks = forms.ModelMultipleChoiceField(
queryset=Task.objects.none(),
widget=forms.CheckboxSelectMultiple,
required=True
)
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super(GetTaskDescription, self).__init__(*args, **kwargs)
self.fields['get_tasks'].queryset = self.user.task_set.all()
def get_task_description(self):
tasks = self.cleaned_data['get_tasks']
return tasks
Here is my html:
{% extends 'todoapp/base.html' %}
{% block title %}Select a Task{% endblock %}
{% block content %}
<h2>Select tasks to view description</h2>
<form method="get" action="{% url 'view_task_description' %}" name="view_task_description">
{% for tasks in view_tasks %}
{{ tasks }}
{% endfor %}
<br/>
<input type="submit" value="View Description">
<button onclick="location.href='{%url 'dashboard' %}?name=Go back'" type="button">Go back</button>
</form>
{% endblock %}
Here is my views.py:
#login_required(login_url='/login/')
def view_task_description(request):
task_description = GetTaskDescription(data=request.GET, user=request.user)
if task_description.is_valid():
obj = GetTaskDescription.get_task_description(task_description)
print obj
return render(request, 'todoapp/task_desc.html', context={'description': obj})
return render(request, 'todoapp/select_task_description.html', context={'view_tasks': GetTaskDescription(user=request.user)})
You're trying to iterate over a form instance:
'view_tasks': GetTaskDescription(user=request.user)
{% for tasks in view_tasks %}
To access field choices you should use view_tasks.fields.get_tasks.choices in template.
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 have 4 models: Post, Comment, Blogger and User.
I have an post_description template, in below of that, I have placed a comment form.
But how to define it in views? My problem is - to get its username, like the user who is logged in will be stored as "posted_by" and in which blog post he post will be stored as "topic" of the blog.
How to store these information, so they get automatically added?
Form that i has described in post_desc.html
{% if user.is_authenticated %}
<form method="post">
{% csrf_token %}
<input type="text" name="comment" style="width: 800px; height: 145px;">
<button type="submit">Submit Comment</button>
</form>
{% else %}
<p>Login to comment</p>
{% endif %}
Current view of that post_desc:
def post_desc(request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, 'post_desc.html', {'post': post})
Now the user can be accessed as follows in the views:
user = request.user
And about the Topic, maybe you could add a hidden input in your form to get blog id , as you are already passing the post in the form template. :
<form method="post">
{% csrf_token %}
<input type="text" name="comment" style="width: 800px; height: 145px;">
<input type="hidden" name="topic" value="{{ post.id }}">
<button type="submit">Submit Comment</button>
And when posted in the view you can get blog by:
post_id = request.POST.get('topic')
post = get_object_or_404(Post, pk=post_id)
And then finally proceeding with your actual flow.
I think what you need here is basic model form setup.
I am hoping there is a blog entry and comments associated with it and you want a commenting functionality on each post.
This is rough quick answer.
Your models.py looks like this:
from django.db import models
from django.conf import settings
class Comments(models.Model):
posted_by = models.ForeignKey(settings.AUTH_USER_MODEL)
topic = models.ForeignKey(Blog)
comment = models.TextField()
last_modified = models.DateTimeField(auto_now=True)
created_on = models.DateTimeField(auto_now_add=True)
You setup a model form in your forms.py
from django.forms import ModelForm
from .models import Comments
class CommentForm(ModelForm):
class Meta:
model = Comments
fields = ['comment']
You setup a model form post view.
#login_required
#require_http_methods(["POST"])
def post_comments_controller(request, identifier):
from .forms import CommentForm
comment_form = CommentForm(request.POST or None)
if comment_form.is_valid():
comment_obj = comment_form.save(commit=False)
topic = Blog.objects.get(id=identifier)
comment_obj.posted_by = request.user
comment_obj.item = topic
comment_obj.save()
return HttpResponse("Done")
else:
return HttpResponseBadRequest()
You setup a entry point in your urls.py
from django.conf.urls import patterns, url
from django.conf import settings
urlpatterns = patterns('',
url(r'^/blog/(?P<identifier>[d]+)/comment$',
'views.post_comments_controller', name='post_comment')
)
And your finally the html form
{% if user.is_authenticated %}
<form method="POST" action="{% url 'post_comment' blog.id %}">
{% csrf_token %}
<input type="text" name="comment" style="width: 800px; height: 145px;">
<button type="submit">Submit Comment</button>
</form>
{% else %}
<p>Login to comment</p>
{% endif %}
This is not tested overall. Let me know.
From Django docs you can use FormMixin with DetailView like this:
class AuthorInterestForm(forms.Form):
message = forms.CharField()
class AuthorDetail(FormMixin, DetailView):
model = Author
form_class = AuthorInterestForm
def get_success_url(self):
return reverse('author-detail', kwargs={'pk': self.object.pk})
def post(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return HttpResponseForbidden()
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
# Here, we would record the user's interest using the message
# passed in form.cleaned_data['message']
return super().form_valid(form)
Hi Guys
I started coding in Django and i just wanted to make an 9gag-Clone.
I followed some Tutorials and acctualy made a Blog. But when i "upload" Images it allways take the default value.
So here is my Html:
{% extends "posts/post_base.html" %}
{% load bootstrap3 %}
{% block post_content %}
<h3 class="title">Poste Some Memes here</h3>
<form action="{% url 'posts:create' %}" method="POST">
{% csrf_token %}
{% bootstrap_form form %}
<input type="submit" value="posten" class="btn btn-primary btn-large">
</form>
{% endblock %}
Here is my Views.py:
class CreatePost(LoginRequiredMixin, SelectRelatedMixin, generic.CreateView):
fields = ('title','picture','group')
model = models.Post
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.save()
return super().form_valid(form)
and at least my models.py:
class Post(models.Model):
user = models.ForeignKey(User,related_name='posts')
created_at = models.DateTimeField(auto_now=True)
title = models.CharField(max_length=30,default='Titel')
picture= models.ImageField(upload_to=settings.MEDIA_ROOT, default='/static/img/default.png')
title_html = models.CharField(max_length=30,default='Titel', editable = False)
group = models.ForeignKey(Group,related_name='posts',null=True,blank=True)
def __str__(self):
return self.title
def save(self,*args,**kwargs):
self.title_html =misaka.html(self.title)
super().save(*args,**kwargs)
def get_absolute_url(self):
return reverse('posts:single',kwargs={'username':self.user.username,'pk':self.pk})
class Meta:
ordering = ['-created_at']
#unique_together = ['user','title','bild']
urls.py and other htmlfiles work correctly.
everything was makemigrated and migrated
I just need to know why it dont save the Images, or dont upload it.
Just replace
<form action="{% url 'posts:create' %}" method="POST">
with
<form action="{% url 'posts:create' %}" method="POST" enctype="multipart/form-data>
Uploaded image are at self.request.FILES
self.object.picture = self.request.FILES or self.request.FILES.get('key')
self.object.save()
You can POST data in self.request.POST and file in self.request.FILES
Both answers where right so couldn't pick them bouth.
So here is the solution:
Added
enctype="multipart/form-data"
to my HTML-Form
AND
added
self.bild = self.request.FILES['bild']
to my CreatePost
So i'm developing an app using Django framework, and i need HTML forms to insert/delete and update data from the database. I was able to make the form to Update the data, but i can't seem to find any info on how to make a Create form and a delete button.
I tried this, with no success:
HTML
<form action="{% url 'conta_details_html' conta.id %}" data-method="delete">
<input type="submit" value="delete">
</form>
Views:
class ContaDetailsHTML(APIView):
renderer_classes = [TemplateHTMLRenderer]
template_name = 'conta_details.html'
def get(self, request, pk):
user = request.user
conta = get_object_or_404(Conta, pk=pk,user=user)
serializer = ContaDetailsSerializerHTML(conta)
return Response({'serializer': serializer, 'conta': conta})
def delete(self,request,pk):
"""Deletes a transaccao"""
user = request.user
if not user.is_authenticated:
return Response(status=status.HTTP_403_FORBIDDEN)
conta = get_object_or_404(Conta, pk=pk, user=user)
serializer = ContaDetailsSerializerHTML(conta,many=False)
if conta:
conta.delete()
return Response(status=status.HTTP_200_OK)
return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST)
Maybe im not getting the syntax correct on the html, but the update form was pretty easy, like this:
<form action="{% url 'conta_details_html' conta.id %}" method="POST">
{% csrf_token %}
{% render_form serializer %}
<input type="submit" value="Save">
</form>
any idea ?
Edit:
URL:
url(r'^api/html/contas/(?P<pk>[0-9]+)/$', views.ContaDetailsHTML.as_view(), name='conta_details_html'),
Oh even for delete is it's easy. You missed out on a few things here.
1. DELETE is a HTTP Verb, Your method field in the form can take one of this.
<form action="{% url 'conta_details_html' conta.id %}" data-method="delete" method="DELETE">
<input type="submit" value="delete">
</form>
In your delete view, you are trying to serialiaze but you don't need to.
def delete(self, request, pk):
"""Deletes a transaccao"""
user = request.user
if not user.is_authenticated:
return Response(status=status.HTTP_403_FORBIDDEN)
conta = get_object_or_404(Conta, pk=pk, user=user)
conta.delete()
return Response(status=status.HTTP_200_OK)