Reputation: 23
Building a website with referring to a book, I made a blog application.
And I found even nonauthors can edit/delete the post which they didn't write. So I've tried to fix it in many ways but failed so far.
Here are my codes.
models.py
class Post(models.Model):
title = models.CharField('TITLE', max_length=50)
slug = models.SlugField('SLUG', unique=True, allow_unicode=True)
description = models.CharField('DESCRIPTION', max_length=100, blank=True)
content = models.TextField('CONTENT')
create_date = models.DateTimeField('Create Date', auto_now_add=True)
modify_date = models.DateTimeField('Modify Date', auto_now=True)
tag = TagField()
author = models.ForeignKey(User, null=True)
class Meta:
ordering = ('-modify_date',)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('blog:post_detail', args=(self.slug,))
def save(self, *args, **kwargs):
if not self.id:
self.slug = slugify(self.title, allow_unicode=True)
super(Post, self).save(*args, **kwargs)
views.py
class PostUpdateView(LoginRequiredMixin, edit.UpdateView):
model = Post
fields = ['title', 'slug', 'description', 'content', 'tag']
success_url = reverse_lazy('blog:index')
def form_valid(self, form):
form.instance.author = self.request.user
return super(PostUpdateView, self).form_valid(form)
class PostDeleteView(LoginRequiredMixin, edit.DeleteView):
model = Post
success_url = reverse_lazy('blog:index')
def form_valid(self, form):
form.instance.author = self.request.user
return super(PostDeleteView, self).form_valid(form)
Below is the only code which worked and I found it in docs(Using FormMixin with DetailView)
def post(self, request, *args, **kwargs):
if not ((request.user==Post.author) or request.user.is_superuser):
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)
It worked, in some points, cuz it returns HttpResponseForbidden if nonauthor try to click "submit" in update form. However, what I want is that nonauthor cannot even access to update page.
I also found the way to customize dispatch() in stackoverflow but it didn't work.
I'm not sure whether it is proper in Django to use {% if not user == object.author %}{% else %}{% endif %}
on templates like in PHP.
Any advice will be appreciated.
Thanks
Upvotes: 1
Views: 708
Reputation: 959
The dispatch
method is the right place to do this because it will affect all requests. As you've noticed, putting access control code in the post
method doesn't affect GET
requests.
How did you try to override dispatch
? Because something like this should work:
from django.core.exceptions import PermissionDenied
class PostUpdateView(LoginRequiredMixin, edit.UpdateView):
#
# All of your other view code here....
#
def dispatch(self, request, *args, **kwargs):
handler = super().dispatch(request, *args, **kwargs)
user = request.user
post = self.get_object()
if not (post.author == user or user.is_superuser):
raise PermissionDenied
return handler
If you're supporting Python2 you'll have to change the super()
call to super(PostUpdateView, self).dispatch(request, *args, **kwargs)
.
Upvotes: 3