Django does not regulate what the user can choose - python

I am very new to Django so don't judge me :). I am making a blog project and everything works well except one thing. When creating a post, the user can choose any other author that has previously logged in. Is there any way to set the author namespace as the currently logged in user? Here is my code:
Models.py
from django.db import models
from django.utils import timezone
from django.core.urlresolvers import reverse
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.models import User
def validate_even(value):
if value == 'auth.User':
raise ValidationError(
_('%(value)s is not an even number'),
params={'value': value},
)
class Post(models.Model):
author = models.ForeignKey('auth.User')
title = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True,null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def approve_comments(self):
return self.comments.filter(approved_comment=True)
def get_absolute_url(self):
return reverse('post_detail', args=(), kwargs={'pk':self.pk})
def __str__(self):
return self.title
class Comment(models.Model):
post = models.ForeignKey('blog.post',related_name='comments')
author = models.ForeignKey('auth.User')
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 get_absolute_url(self):
return reverse('post_list')
def __str__(self):
return self.text
class UserProfileInfo(models.Model):
user = models.OneToOneField(User)
def __str__(self):
return self.user.username
My forms.py
from django import forms
from blog.models import Comment,Post
from django.contrib.auth.models import User
from blog.models import UserProfileInfo
class PostForm(forms.ModelForm):
class Meta():
model = Post
fields = ['author','title','text']
widgets = {
'title':forms.TextInput(attrs={'class':'textinputclass','autocomplete':'true'}),
'text':forms.Textarea(attrs={'class':'editable medium-editor-textarea postcontent'})
}
class CommentForm(forms.ModelForm):
class Meta():
model = Comment
fields = ['text']
widgets = {
'text':forms.Textarea(attrs={'class':'editable medium-editor-textarea'})
}
def __init__(self, *args, **kwargs):
from django.forms.widgets import HiddenInput
hide_condition = kwargs.pop('hide_condition',None)
super(CommentForm, self).__init__(*args, **kwargs)
if hide_condition:
self.fields['author'].widget = HiddenInput()
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput(attrs={'autocomplete':'false'}))
username = forms.CharField(widget=forms.TextInput(attrs={'autocomplete': 'false'}))
class Meta():
model = User
fields = ('username', 'email', 'password')
widgets = {
'password':forms.TextInput(attrs={'autocomplete':'false'}),
'username':forms.TextInput(attrs={'autocomplete':'false'}),
}
My views.py
from django.shortcuts import render, get_object_or_404,redirect
from django.utils import timezone
from django.views.generic import (TemplateView,ListView,DetailView,CreateView,UpdateView,DeleteView)
from blog.models import Comment,Post
from blog.forms import PostForm,CommentForm
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse_lazy
from django.contrib.auth.decorators import login_required
from django.contrib import auth
from blog.forms import UserForm
from django.contrib.auth import views
from django.contrib.auth.models import User
def register(request):
registered = False
if request.method == 'POST':
user_form = UserForm(data=request.POST)
if user_form.is_valid():
user = user_form.save()
user.set_password(user.password)
user.save()
registered = True
if registered:
views.login(request)
return redirect("/")
else:
print(user_form.errors)
else:
user_form = UserForm()
return render(request, 'registration/registration.html',{'user_form':user_form,registered:'registered'})
class AboutView(TemplateView):
template_name = 'about.html'
class PostListView(ListView):
model = Post
template_name = 'post_list.html'
def get_queryset(self):
return Post.objects.filter(published_date__lte=timezone.now()).order_by('-published_date')
class PostDetailView(DetailView):
model = Post
class CreatePostView(LoginRequiredMixin,CreateView):
login_url = '/login/'
redirect_field_name = 'blog/post_detail.html'
form_class = PostForm
model = Post
def get_queryset(self):
return Post.objects.filter(author=self.request.user)
form_class = PostForm
form_class.author = self.request.user
class PostUpdateView(LoginRequiredMixin,UpdateView):
login_url = '/login/'
redirect_field_name = 'blog/post_detail.html'
model = Post
form_class = PostForm
class PostDeleteView(LoginRequiredMixin,DeleteView):
model = Post
success_url = reverse_lazy('post_list')
class DraftListView(LoginRequiredMixin,ListView):
login_url = '/login/'
redirect_field_name = 'blog/post_list.html'
model = Post
def get_queryset(self):
return Post.objects.filter(published_date__isnull=True).order_by('created_date')
#login_required
def add_comment_to_post(request,pk):
post = get_object_or_404(Post,pk=pk)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
# comment.save()
instance = form.save(commit=False)
instance.author = request.user
instance.save()
return redirect('post_detail',pk=post.pk)
else:
form = CommentForm
return render(request,'blog/comment_form.html',context={'form':form})
#login_required
def comment_approve(request,pk):
comment = get_object_or_404(Comment,pk=pk)
comment.approve()
return redirect('post_detail',pk=comment.post.pk)
#login_required
def comment_remove(request, pk):
comment = get_object_or_404(Comment, pk=pk)
post_pk = comment.post.pk
comment.delete()
return redirect('post_detail', pk=post_pk)
#login_required
def post_publish(request,pk):
post = get_object_or_404(Post,pk=pk)
post.publish()
return redirect('post_detail',pk=pk)
I have tried absolutely everything and nothing worked. Can anyone please help me?

In your PostForm, remove author from the fields, so it cannot be edited by the user:
fields = ['title', 'text']
Then in your CreatePostView, remove the def get_queryset() method as it doesn't do anything here. You should instead override the form_valid method, that's where you get a chance to update the model that was created by the form.
def form_valid(self, form):
self.object = form.save(commit=False) # the form's save method returns the instance
self.object.author = self.request.user # here you assign the author
self.object.save()
return HttpResponseRedirect(self.get_success_url())
Alternatively, to keep as close as possible to the CreateView parent class:
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form) # this will call `CreateView`'s `form_valid()` method, which saves the form.

Related

Trying to restric a queryset in Django base on foreign key relationship

I am trying to make a form in Django that gives the user a limited selection based on a foreign key. To be more exact, the form has 2 fields, a ModelChoiceField and a simple text field. This form's purpose is to allow a user to add a Riddle to a previously created Room. So the goal is to limit the ModelChoiceField to only allow the currently logged-in user to add riddles to just their own rooms.
forms.py:
from django import forms
from .models import Project, Riddle
class ProjectForm(forms.ModelForm):
class Meta:
model = Project
fields = ['title', 'max_players', 'has_actor', 'scenario']
class RiddleForm(forms.ModelForm):
project = forms.ModelChoiceField(queryset=Project.objects.all(),
empty_label=None,
widget=forms.Select(attrs={'class': 'form-control'}),
label='Project')
class Meta:
model = Riddle
fields = ['project','description']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['project'].queryset = Project.objects.all()
self.fields['project'].label_from_instance = lambda obj: obj.title
models.py:
from django.db import models
from django.contrib.auth import get_user_model
from django.urls import reverse
User = get_user_model()
class Project(models.Model):
title = models.CharField(max_length=255, unique=True)
max_players = models.PositiveIntegerField(default=0)
has_actor = models.BooleanField(default=False)
scenario = models.TextField(blank=True, null=True)
#number_of_riddles = models.PositiveIntegerField(default=0)
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='rooms')
def get_absolute_url(self):
return reverse(
"rooms:project_list",
kwargs={
"username": self.user.username,
#"pk": self.pk
}
)
class Riddle(models.Model):
project = models.ForeignKey(Project, on_delete=models.CASCADE)
description = models.TextField()
urls.py:
from django.urls import path
from .views import ProjectListView, ProjectDetailView, ProjectCreateView, ProjectUpdateView, ProjectDeleteView, RiddleAddView
app_name = 'rooms'
urlpatterns = [
path('projects/madeby/<slug:username>', ProjectListView.as_view(), name='project_list'),
path('projects/<slug:username>/<int:pk>/', ProjectDetailView.as_view(), name='project_detail'),
path('projects/create/', ProjectCreateView.as_view(), name='project_create'),
path('projects/update/<int:pk>', ProjectUpdateView.as_view(), name='project_update'),
path('projects/delete/<int:pk>/', ProjectDeleteView.as_view(), name='project_delete'),
path('projects/addriddle/', RiddleAddView.as_view(), name='riddle_add'),
]
views.py:
from django.urls import reverse_lazy, reverse
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views import View, generic
from django.views.generic import CreateView, DetailView, UpdateView
from .models import Project, Riddle
from .forms import ProjectForm, RiddleForm
from django.contrib.auth import get_user_model
from django.http import Http404
from braces.views import SelectRelatedMixin
from django.contrib import messages
User = get_user_model()
class ProjectCreateView(CreateView):
model = Project
form_class = ProjectForm
template_name = 'rooms/project_form.html'
#success_url = reverse_lazy('rooms:project_list username=')
def get_success_url(self):
return reverse('rooms:project_list', kwargs= {'username': self.request.user})
def form_valid(self, form):
form.instance.user = self.request.user
return super().form_valid(form)
#def get_context_data(self, **kwargs):
# context = super().get_context_data(**kwargs)
# context['riddle_form'] = RiddleForm()
# return context
#def form_valid(self, form):
#project = form.save()
# project_id = self.kwargs.get('pk')
# project = Project.objects.get(id=project_id)
# riddle_form = RiddleForm(self.request.POST)
#if riddle_form.is_valid():
# riddle = riddle_form.save(commit=False)
# riddle.project = project
# riddle.save()
#return super().form_valid(form)
class ProjectDetailView(DetailView):
model = Project
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
project_id = self.kwargs.get('pk')
project = Project.objects.get(id=project_id)
context['project'] = project
return context
class ProjectUpdateView(UpdateView):
model = Project
form_class = ProjectForm
template_name = 'rooms/project_form.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['riddle_form'] = RiddleForm()
return context
#def form_valid(self, form):
#project = form.save()
# project_id = self.kwargs.get('pk')
# project = Project.objects.get(id=project_id)
# riddle_form = RiddleForm(self.request.POST)
#if riddle_form.is_valid():
# riddle = riddle_form.save(commit=False)
# riddle.project = project
# riddle.save()
#return super().form_valid(form)
#def form_valid(self, form):
# form.save()
# return redirect('rooms:project_list')
class ProjectListView(generic.ListView):
model = Project
template_name = "rooms/room_list.html"
def get_queryset(self):
try:
self.room_user = User.objects.prefetch_related('rooms').get(
username__iexact=self.kwargs.get('username')
)
except User.DoesNotExist:
raise Http404
else:
return self.room_user.rooms.all()
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["room_user"] = self.room_user
return context
class ProjectDeleteView(LoginRequiredMixin, SelectRelatedMixin, generic.DeleteView):
model = Project
select_related = ('user',)
#success_url = reverse_lazy('home')
def get_success_url(self):
return reverse('rooms:project_list', kwargs= {'username': self.request.user})
def get_queryset(self):
queryset = super().get_queryset()
return queryset.filter(user_id=self.request.user.id)
def delete(self, *args, **kwargs):
messages.success(self.request, "Post Deleted")
return super().delete(*args, **kwargs)
class RiddleAddView(CreateView):
model = Riddle
form_class = RiddleForm
template_name = 'rooms/riddle_form.html'
def form_valid(self, form):
project = form.cleaned_data.get('project')
project_title = project.title
try:
project = Project.objects.get(title=project_title)
except Project.DoesNotExist:
messages.error(self.request, "No project with the title '{}' was found.".format(project_title))
return super().form_invalid(form)
form.instance.project = project
return super().form_valid(form)
def get_success_url(self):
return reverse_lazy('rooms:project_detail', kwargs={'username': self.object.project.user.username, 'pk': self.object.project.id})
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['riddle_form'] = RiddleForm()
#context['project_id'] = self.kwargs['project_id']
return context
For now, I just have the Project.objects.all() but that does not achieve the functionality I want.
I have tried using the select_related(), filter() methods and the attribute__foreignattribute syntax to no success. Any ideas of how I should go about this are welcome! Taking into account how common this operation is, the solution is probably something pretty obvious, but I haven't been able to come up with something to fit my case.
Thanks in advance!
I think you can pass the user as an argument for the RiddleForm:
In RiddleAddView you can define user as a parameter for the RiddleForm:
class RiddleAddView(CreateView):
...
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs
...
Then you can use it to restrict the queryset in the RiddleForm:
class RiddleForm(forms.ModelForm):
...
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super().__init__(*args, **kwargs)
self.fields['project'].queryset = Project.objects.filter(user=user)
...
Also, you can use the reverse relationship:
class RiddleForm(forms.ModelForm):
...
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super().__init__(*args, **kwargs)
self.fields['project'].queryset = user.rooms.all()
...

RelatedManager object is not iterable

Whenever I run my code, I get a "RelatedManager" object is not iterable error. Here is my models.py:
from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
from django.urls import reverse
class Post(models.Model):
contents = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
replies = list()
def __str__(self):
return f'{self.author} - {self.pk} - {self.date_posted}'
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
class Reply(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='replies')
contents = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return f'{self.author} - {self.date_posted}'
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
class Meta:
ordering = ['-date_posted']
Here is my views.py:
from django.shortcuts import render, get_object_or_404
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from .models import Post
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.auth.models import User
from .forms import ReplyForm
class PostListView(ListView):
model = Post
template_name = 'app/home.html'
context_object_name = 'posts'
ordering = ['-date_posted']
paginate_by = 15
def PostDetailView(request, **kwargs):
template_name = 'app/post_detail.html'
post = get_object_or_404(Post, pk=kwargs['pk'])
replies = post.replies
new_reply = None
# Reply added
if request.method == 'POST':
reply_form = ReplyForm(data=request.POST)
if reply_form.is_valid():
# Create reply object but don't save to db yet
new_reply = reply_form.save(commit=False)
# Assign the current post the the reply
new_reply.post = post
# Save reply to db
new_reply.save()
replies.append(new_reply)
else:
reply_form = ReplyForm()
return render(request, template_name, {'post':post, 'replies':replies, 'form':reply_form})
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = ['contents']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Post
fields = ['contents']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
else:
return False
class PostDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
model = Post
success_url = '/'
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
else:
return False
def about(request):
return render(request, 'app/about.html', {'title':'About App'})
def n_help(request):
return render(request, 'app/help.html', {'title':'App Help Page'})
The problem is when I try to iterate through the Post.replies list, it gives me a Related Manager instead of the list I intended it to be. Here is the variables in the Django debug page:
kwargs: {'pk':8}
new_reply: None
post: <Post: TestUser - 8 - 2022-02-06 00:12:33.255956+00:00>
replies: <django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager.<locals>.RelatedManager object at 0x00000262D26052E0>
reply_form: <ReplyForm bound=False, valid=False, fields=(contents)>
request: <WSGIRequest: GET '/post/8/'>
template_name: app/post_detail.html
As you can see the "replies" variable is a related manager, not a list. I tried making replies global and using a function to return it as a list, which worked but it still gave me the RelatedManager error. The only difference was the Django Debug variables looked like this:
kwargs: {'pk':8}
new_reply: None
post: <Post: TestUser - 8 - 2022-02-06 00:12:33.255956+00:00>
replies: []
reply_form: <ReplyForm bound=False, valid=False, fields=(contents)>
request: <WSGIRequest: GET '/post/8/'>
template_name: app/post_detail.html
Even though replies is now a list and that is the only thing I am iterating through, it still gives me the exact same error. I would appreciate any help given.

How to import current login user in to form by form.py Django

I want to automatically add the name of a logged in user to the form but i don't know how to import this varaible to the form
FILES >>>>
forms.py
class CommentForm(forms.ModelForm):
class Meta:
model = ArticleComment
fields = ('user_name', 'body')
widgets = {
'user_name': forms.HiddenInput(attrs={'value': username }),
'body': forms.Textarea(attrs={'class': 'form-control'})
}
models.py
class ArticleComment(models.Model):
post = models.ForeignKey(Article, related_name='comments', on_delete=models.CASCADE)
user_name = models.CharField(max_length=255)
body = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '%s - %s' % (self.post.title, self.user_name)
def get_absolute_url(self):
return reverse('article', args=(str(self.id)))
views.py
class AddCommentView(CreateView):
model = ArticleComment
form_class = CommentForm
template_name = 'add_comment.html'
# fields = '__all__'
def form_valid(self, form):
form.instance.post_id = self.kwargs['category_id']
return super().form_valid(form)
success_url = reverse_lazy('index')
Your ArticleComment model has the username set as a CharField, which means it is going to be expecting a string. I believe what you want to do is to set the user_name field of the CommentForm to the username of the currently logged-in user.
forms.py
from django import forms
from .models import ArticleComment
class CommentForm(forms.ModelForm):
class Meta:
model = ArticleComment
fields = ('body', )
widgets = {
'user_name': forms.HiddenInput(), # remove attrs of the HiddenInput
'body': forms.Textarea(attrs={'class': 'form-control'})
}
views.py
from django.shortcuts import render
from .models import ArticleComment, Article
from .forms import CommentForm
from django.urls import reverse_lazy
from django.views.generic import CreateView
from django.contrib.auth.mixins import LoginRequiredMixin
class AddCommentView(LoginRequiredMixin, CreateView):
model = ArticleComment
form_class = CommentForm
template_name = 'add_comment.html'
def form_valid(self, form):
form.instance.post_id = self.kwargs['category_id']
form.instance.user_name = self.request.user.username # this sets the username field to the username of the currently logged in user
return super().form_valid(form)
success_url = reverse_lazy('index')

How to automatically update a field depending on the user who changed it in Django?

Context:
In the Blog part of page any registered User can post, but all posts that are from non superuser accounts have to be approved by an admin on the Admin page where I registered the model as well.
This functions as intended.
My question:
How can I make it so that if a Blog Post gets updated by a superuser(doesn't matter what kind of a change for example: when admin opens one single post and adds in a further text in the body of the post, or deletes some part of a text because it seems malicious or fake), that it is automatically approved(The field approved gets then set to TRUE)?
I already thought of adding a further field in the model called changed_by and have it initially null.
Code:
blog/models.py
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
class BlogPost(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
approved = models.BooleanField(default=False)
changed_by = models.ForeignKey(User, default=None) # I am planning to use this but how?
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('blogPost-detail', kwargs={'pk': self.pk})
blog/admin.py
from django.contrib import admin
from .models import BlogPost
def approve_multiple_posts(modeladmin, request, queryset):
for blogPost in queryset:
if blogPost.approved:
blogPost.approved = False
else:
blogPost.approved = True
blogPost.save()
approve_multiple_posts.short_description = 'Change approval status'
class PostAdmin(admin.ModelAdmin):
list_display = ['title', 'author', 'date_posted', 'approved']
actions = [approve_multiple_posts, ]
admin.site.register(BlogPost, PostAdmin)
blog/views.py
from django.shortcuts import render, get_object_or_404
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.auth.models import User
from .models import BlogPost
from django.views.generic import (
ListView,
DetailView,
CreateView,
UpdateView,
DeleteView
)
def blog(request):
context = {
'blogPosts': BlogPost.objects.all()
}
return render(request, 'blog/blog.html', context)
class PostListView(ListView):
model = BlogPost
template_name = 'blog/blog.html'
context_object_name = 'blogPosts'
ordering = ['-date_posted']
paginate_by = 5
def get_queryset(self):
return BlogPost.objects.filter(approved=True).order_by('-date_posted')
class UserPostListView(ListView):
model = BlogPost
template_name = 'blog/user_blogPosts.html'
context_object_name = 'blogPosts'
paginate_by = 5
def get_queryset(self):
user = get_object_or_404(User, username=self.kwargs.get('username'))
return BlogPost.objects.filter(author=user, approved=True).order_by('-date_posted')
class PostDetailView(DetailView):
model = BlogPost
class PostCreateView(LoginRequiredMixin, CreateView):
model = BlogPost
fields = ['title', 'content']
def form_valid(self, form):
form.instance.author = self.request.user
if self.request.user.is_superuser:
form.instance.approved = True
return super().form_valid(form)
class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = BlogPost
fields = ['title', 'content']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def test_func(self):
blog_post = self.get_object()
if self.request.user == blog_post.author:
return True
return False
class PostDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
model = BlogPost
success_url = '/blog'
def test_func(self):
blog_post = self.get_object()
if self.request.user == blog_post.author:
return True
return False
I would appreciate any help/suggestions you have! Thanks
In your PostAdmin class, you can override a method called save_model (Django docs). Try something like this:
class PostAdmin(admin.ModelAdmin):
list_display = ['title', 'author', 'date_posted', 'approved']
actions = [approve_multiple_posts, ]
def save_model(self, request, obj, form, change):
important_fields = ['title', 'content'] # modify save if these fields changed
if any(x in important_fields for x in form.changed_data):
obj.approved = request.user.is_superuser
super().save_model(request, obj, form, change)
This will make approved True only if the user is a superuser, otherwise it will be set to False.

Django - How to allow only the owner of a new post to edit or delete the post?

I will be really grateful if anyone can help to resolve the issue below.
I have the following Django project coding. The problem is: when the browser was given "/posts/remove/<post_id>/" or "/posts/edit/(<post_id>/" as the url, it will allow the second user (not owner) to perform the remove and edit jobs, respectively.
How can I allow only the owner of a new post to edit or delete the post?
account.models.py:
from django.db import models
from django.conf import settings
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
def __str__(self):
return 'Profile for user {}'.format(self.user.username)
posts.models.py:
from django.db import models
from django.conf import settings
from django.utils import timezone
from django.utils.text import slugify
from django.core.urlresolvers import reverse
from taggit.managers import TaggableManager
class PublishedManager(models.Manager):
def get_queryset(self):
return super(PublishedManager, self).get_queryset().filter(status='published')
class Post(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
related_name='posts_created')
title = models.CharField(max_length=200)
slug = models.SlugField(max_length=200, unique_for_date='created')
image = models.ImageField(upload_to='images/%Y/%m/%d', null=True, blank=True)
description = models.TextField(blank=True)
created = models.DateTimeField(default=timezone.now,
db_index=True)
updated = models.DateTimeField(auto_now=True)
users_like = models.ManyToManyField(settings.AUTH_USER_MODEL,
related_name='posts_voted',
blank=True)
status = models.CharField(max_length=10, default='published')
objects = models.Manager() # The default manager.
published = PublishedManager() # The Dahl-specific manager.
tags = TaggableManager()
class Meta:
ordering = ('-created',)
def __str__(self):
return self.title
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse('posts:detail', args=[self.id, self.slug])
posts.view.py:
from django.views.decorators.http import require_POST
from django.shortcuts import render, redirect, get_object_or_404, render_to_response
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.conf import settings
from django.core.context_processors import csrf
from .forms import PostCreateForm, EmailPostForm, CommentForm, SearchForm
from .models import Post
from actions.utils import create_action
#login_required
def post_create(request):
"""
View for creating a new post.
"""
if request.method == 'POST':
# form is sent
form = PostCreateForm(data=request.POST, files=request.FILES)
if form.is_valid():
cd = form.cleaned_data
new_item = form.save(commit=False)
# assign current user to the item
new_item.user = request.user
tags = form.cleaned_data['tags']
new_item.save()
for tag in tags:
new_item.tags.add(tag)
new_item.save()
create_action(request.user, 'created a post:', new_item)
messages.success(request, 'Post added successfully')
form = PostCreateForm()
else:
messages.error(request, 'Error adding new post')
else:
# build form
form = PostCreateForm(data=request.GET)
return render(request, 'posts/post/create.html', {'section': 'posts',
'form': form})
#login_required
def post_remove(request, post_id):
Post.objects.filter(id=post_id).delete()
return redirect('posts:mypost')
#login_required
def post_edit(request, post_id):
item = Post.objects.get(pk=post_id)
if request.method == 'POST':
form = PostCreateForm(request.POST, instance=item)
if form.is_valid():
form.save()
return redirect('posts:mypost')
else:
form = PostCreateForm(instance=item)
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('posts/post/post_edit.html', args)
posts.urls.py
from django.conf.urls import url
from . import views
from .feeds import LatestPostsFeed
urlpatterns = [
url(r'^create/$', views.post_create, name='create'),
url(r'^remove/(?P<post_id>\d+)/$', views.post_remove, name='post_remove'),
url(r'^edit/(?P<post_id>\d+)/$', views.post_edit, name='post_edit'),
]
Add request.user == item.user check inside your method.
#login_required
def post_remove(request, post_id):
item = Post.objects.get(pk=post_id)
if request.user == item.user:
Post.objects.filter(id=post_id).delete()
return redirect('posts:mypost')
#login_required
def post_edit(request, post_id):
item = Post.objects.get(pk=post_id)
if request.user == item.user:
...
//write your code here

Categories

Resources