I’m learning Django, but it’s hanging on such a seemingly simple moment. I need to check and allow the user to edit only his posts, and if he clicks the link for editing someone else’s - render a specific page.
I can not form a condition for user verification, please help:
views.py
#login_required
def blogs_edit_text_post(request, post_id):
post_form = PostForm(instance=TextPost.objects.get(id=post_id))
owner = TextPost.objects.get(pk=1)
if request.user == owner:
if request.method == "POST":
post_form = PostForm(request.POST, instance=TextPost.objects.get(id=post_id))
if post_form.is_valid():
post = post_form.save()
return redirect(blogs_blog)
return render(request, 'blogs/edit_text_post.html', {
'post_form': post_form
})
else:
return render(request, 'blogs/error_page.html', {})
models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile_user_id')
blog_title = models.CharField(max_length=300, verbose_name='Название блога')
blog_description = models.TextField(max_length=500, verbose_name='Пара слов о себе', blank=True)
profile_pic = models.ImageField(default='nophoto.jpg', upload_to='user_pics/', blank=True, verbose_name='Аватар')
class TextPost(models.Model):
author = models.ForeignKey(Profile, on_delete=models.CASCADE)
title = models.CharField(max_length=300, verbose_name='Заголовок')
post = models.TextField(max_length=500, verbose_name='Текст поста', blank=False)
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
urls.py
path('blogs/blog/', views.blogs_blog, name='blogs-blog')
Please note these points:
Don't relate TextPost to Profile model, relate it directly to the User model. It will be more easy for your project.
Always use "related_name" in OneToOneField or ForeignKeyField.
Always use context (or another named variable) to pass variable in template. in big projects, you will have to pass many variables.
models.py
class TextPost(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user_name') # User, not Profiel, related_name added
title = models.CharField(max_length=300, verbose_name='Заголовок')
post = models.TextField(max_length=500, verbose_name='Текст поста', blank=False)
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
views.py
#login_required
def blogs_edit_text_post(request, post_id):
post = TextPost.objects.get(id=post_id)
if post.author == request.user: # post.author.user == request.user if it's related to Profile
if request.method == "POST":
post_form = PostForm(request.POST, instance=TextPost.objects.get(id=post_id))
if post_form.is_valid():
post = post_form.save()
return redirect(blogs_blog)
else:
post_form = PostForm(instance=TextPost.objects.get(id=post_id))
context = {
'post_form': post_form
}
return render(request, 'blogs/edit_text_post.html', context)
else:
return render(request, 'blogs/error_page.html', {})
Related
I get an Error:
cannot unpack non-iterable bool object
profile = Profile.objects.get(Profile.user == request.user)
This is my models.py in account app and blog app:
class Profile(models.Model):
STATUS_CHOICES = (
('manager', 'مدیر'),
('developer', 'توسعهدهنده'),
('designer', 'طراح پروژه'),
)
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
bio = models.CharField(max_length=50, blank=True)
task = models.CharField(choices=STATUS_CHOICES, max_length=20, blank=True, null=True, default=None)
date_of_birth = models.DateField(blank=True, null=True)
photo = models.ImageField(upload_to='users/photos/%Y/%m/%d/', blank=True)
def __str__(self):
return f'{self.user.get_full_name()}'
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
profile = models.ForeignKey(Profile, on_delete=models.CASCADE, related_name='user_comments')
body = models.TextField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=False)
and this is my views.py for comments:
def post_detail(request, year, month, day, slug):
post = get_object_or_404(Post, slug=slug, status='published', publish__year=year, publish__month=month, publish__day=day)
tags = Tag.objects.all()
tagsList = []
for tag in post.tags.get_queryset():
tagsList.append(tag.name)
profile = Profile.objects.get(Profile.user == request.user)
comments = post.comments.filter(active=True)
new_comment = None
if request.method == 'POST':
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
new_comment = comment_form.save(commit=False)
new_comment.profile = profile
new_comment.post = post
new_comment.save()
return redirect('post_detail', slug=post.slug)
else:
comment_form = CommentForm()
post_tags_ids = post.tags.values_list('id', flat=True)
similar_posts = Post.published.filter(tags__in=post_tags_ids).exclude(id=post.id)
similar_posts = similar_posts.annotate(same_tags=Count('tags')).order_by('-same_tags', '-publish')[:3]
return render(request, 'blog/post/detail.html', {'post': post, 'comments': comments, 'new_comment': new_comment, 'comment_form': comment_form, 'similar_posts': similar_posts, 'tagsList': tagsList, 'tags': tags})
Is there any solution for this problem?
Assuming you need to get only single profile instance i.e. current logged in user's profile so you can either use:
profile = Profile.objects.get(user=request.user)
or:
get_object_or_404(Profile, user=request.user)
To limit the view to be accessed by only logged in users, use #login_required decorator so:
#login_required(login_url='/accounts/login/') # you can give any login_url you want.
def post_detail(request, year, month, day, slug):
#...
hi am working on a project where user-added the post onto the site and driver check his post and give him offer ( price) to ship their load .when the driver submits the post(price) ....at the admin level the selected post and which driver adds the price is working properly, however when the same user logged in (which added the post earlier)and want to see the price of his post-offer by a particular driver. so how can I show to the front end with filtration of the particular user?
this is my user post model
class Loader_post(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE ,related_name="Loader")
pick_up_station = models.CharField(max_length=150)
destination_station = models.CharField(max_length=150)
sender_name = models.CharField(max_length=150)
phone_number = PhoneNumberField(null=False, blank=False, unique=True)
receiver_name = models.CharField(max_length=150)
def __str__(self):
return self.user.username
def get_absolute_url(self):
return reverse("Loader:my_job", kwargs={"pk": self.pk})
here is the price added to the post
class price(models.Model):
my_post = models.ForeignKey(Loader_post, related_name='prices',on_delete=models.CASCADE,
null=True, default='')
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, null=True, default='')
driver_price = models.CharField(max_length=150, null=True)
driver_name = models.CharField(max_length=150, null=True)
approved_price = models.BooleanField(default=False)
status = models.BooleanField(default=False)
def get_absolute_url(self):
return reverse("Driver:Driverview")
def __str__(self):
return self.driver_price
this is the view of the user post(views.py)
class Loader_post_view(CreateView, LoginRequiredMixin):
form_class = forms.Loader_post_form
model = Loader_post
template_name = "post_detail.html"
success_url = reverse_lazy("Loader:my_job")
def form_valid(self, form):
print(form.cleaned_data)
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.save()
return super().form_valid(form)
and this is the view of added price o particular post
#login_required
def add_price_to_post(request, pk):
post = get_object_or_404(Loader_post, pk=pk)
user = request.user
if request.method == "POST":
form = price_form(request.POST)
if form.is_valid():
ps = form.save(commit=False)
ps.user = request.user
ps.status = True
ps.save()
ps.my_post.add(post)
return redirect('Driver:Driverview')
else:
form = price_form()
return render(request, 'price_form.html', {'form': form})
now how can I show at the front-end of particular logged in user-added price to the post
hi am working on a project where am using multiple user data
a user did a post onto the site and when driver see that post he adds their offer to that post but when driver submit the post ...at the admin level the particular is selected automatically but the post is not selected on which he adds price
this is my post model.py
class Loader_post(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE ,related_name="Loader")
pick_up_station = models.CharField(max_length=150)
destination_station = models.CharField(max_length=150)
sender_name = models.CharField(max_length=150)
phone_number = PhoneNumberField(null=False, blank=False, unique=True)
receiver_name = models.CharField(max_length=150)
this is my second model of adding price to a particular post
class price(models.Model):
my_post = models.ManyToManyField(Loader_post, related_name='prices')
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, default='')
driver_price = models.CharField(max_length=150, null=True)
driver_name = models.CharField(max_length=150, null=True)
approved_price = models.BooleanField(default=False)
status = models.BooleanField(default=False)
this is my adding price to the post views.py
#login_required
def add_price_to_post(request, pk):
post = get_object_or_404(Loader_post, pk=pk)
user = request.user
if request.method == "POST":
form = price_form(request.POST)
if form.is_valid():
ps = form.save(commit=False)
ps.user = request.user
ps.status = True
ps.post = post
ps.save()
return redirect('Driver:Driverview')
else:
form = price_form()
return render(request, 'price_form.html', {'form': form})
this is my html add post button
{% for loader in Loader %}
this is loop
and this is button
add price
It is a ManyToMany relation between price and Loader_post model, hence ps.post = post won't work. You need to use add() method to add new post. Like this:
ps.save()
ps.my_post.add(post)
models.py
class Post(models.Model):
message = models.CharField(max_length=2000)
topic = models.ForeignKey(Topic, related_name="posts", null=True,
blank=True, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(User, null=True, blank=True,
on_delete=models.CASCADE)
like = models.IntegerField(default=0)
views = models.IntegerField(default=0)
class ReplyPost(models.Model):
reply = models.CharField(max_length=2000)
post = models.ForeignKey(Post, related_name="reply", null=True,
blank=True, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(User, null=True, blank=True,
on_delete=models.CASCADE)
views.py
def reply_post(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == "POST":
form = ReplyPostForm(request.POST)
if form.is_valid():
replypost = form.save(commit = False)
replypost.reply = form.cleaned_data.get("reply")
replypost.post = post
replypost.created_by = request.user
replypost.save()
return redirect("post", post.id)
else:
form = ReplyPostForm()
args = {
'form': form,
'post':post
}
return render(request, 'home/replypost.html', args)
urls.py
urlpatterns = [
#.....
url(r'^home/questions/(?P<pk>\d+)/reply/$', views.reply_post,
name="replypost"),
url(r'^home/questions/(?P<pk>\d+)/$', views.post, name="post"),
]
forms.py
class ReplyPostForm(ModelForm):
reply = forms.CharField(widget = forms.Textarea)
class Meta:
model = ReplyPost
fields = ('reply',)
The error:
ValueError. The view 'WebBoard.views.reply_post' didn't return an
'HttpResponse' object. It returned 'None' instead.
I can't not understand what is wrong with the code..Please update me if the code above is not sufficient to understand.
Your code needs to return an HttpResponse instance for the case when a request is POST but the form is not valid.
Looking at your code, try to move the last lines back one indentation level; that way everything that isn't a POST with a valid form will fall into that last return statement.
def reply_post(request, pk):
post = ...
if request.method == "POST":
form = ReplyPostForm(request.POST)
if form.is_valid():
...
return redirect("post", post.id)
else:
form = ReplyPostForm()
args = {
'form': form,
'post': post,
}
return render(request, 'home/replypost.html', args)
I want to ask for guidance on how to do this Django email notification
https://docs.djangoproject.com/en/1.8/topics/email/#send-mail
I have a basic task form and option to assign it to someone, when the form is saved I want to send an email notification to the assigned user.
Job/task models.py
class Job(models.Model):
completed = models.BooleanField(default=False)
task_name = models.CharField(max_length=80, blank=False)
description = models.CharField(max_length=80, blank=False)
is_important = models.BooleanField(default=False)
completion_date = models.DateField(blank=True, null=True)
assign_to = models.ForeignKey(User, blank=True, null=True)
comments = models.TextField(blank=True)
def __unicode__(self):
return self.task_name
Job/task view.py
#login_required
def job(request):
if request.method == 'POST':
form = JobForm(request.POST)
if form.is_valid():
job_record = form.save(commit=False)
job_record = form.save(commit=False)
job_record.user = request.user
job_record.save()
return redirect('jobs:list')
else:
form = JobForm()
return render(request, 'jobs/form.html', {'form': form})
You are nearly there:
#login_required
def job(request):
form = JobForm(request.POST or None)
if form.is_valid():
job_record = form.save(commit=False)
job_record.assign_to = request.user
job_record.save()
send_mail(
subject="subject",
message="message",
from_email="from#myserver.com",
recipient_list=[job_record.assign_to.email]
)
return redirect('jobs:list')
return render(request, 'jobs/form.html', {'form': form})