django security and user control - django

how to prevent people from editing post and publishing and approving and deleting post of other people who are logined in the system in django.i am creating a forum where anyone can post question.i need help to control users who are already registered in the system
this my post_deatil.html
{% extends 'blog/base.html' %}
{% block content %}
<div class="post">
{% if post.published_date %}
<div class="date">
{{ post.published_date }}
</div>
{% else %}
{% if id.is_authenticated %}
<a class="btn btn-primary" href="{% url 'post_publish' pk=post.pk %}">Publish</a>
<a class="btn btn-danger" href="{% url 'post_remove' pk=post.pk %}"><span class="glyphicon glyphicon-remove"></span></a>
<a class="btn btn-success" href="{% url 'post_edit' pk=post.pk %}"><span class="glyphicon glyphicon-pencil"></span></a>
{% endif %}
{% endif %}
<h1>{{ post.title }}</h1>
<p>{{ post.text|linebreaksbr }}</p>
</div>
<hr>
<a class="btn btn-info" href="{% url 'add_comment_to_post' pk=post.pk %}">Add comment</a>
{% for comment in post.comments.all %}
{% if user.is_authenticated or comment.approved_comment %}
<div class="comment">
<div class="date">
{{ comment.created_date }}
{% if not comment.approved_comment %}
<a class="btn btn-danger" href="{% url 'comment_remove' pk=comment.pk %}"><span class="glyphicon glyphicon-remove"></span></a>
<a class="btn btn-success" href="{% url 'comment_approve' pk=comment.pk %}"><span class="glyphicon glyphicon-ok"></span></a>
Cancel
{% endif %}
</div>
<strong>{{ comment.author }}</strong>
<p>{{ comment.text|linebreaks }}</p>
</div>
{% endif %}
{% empty %}
<p>No comments here yet:</p>
{% endfor %}
{% endblock %}
this my view.py
from django.shortcuts import render
from django.utils import timezone
from .models import Post, Comment
from django.shortcuts import render, get_object_or_404
from .forms import PostForm, CommentForm
from django.shortcuts import redirect
from django.contrib.auth.decorators import login_required
def post_list(request):
posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
"""posts = Post.objects.filter(published_date__lte=timezone.now()).get_latest_by('published_date')"""
return render(request, 'blog/post_list.html', {'posts': posts})
def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, 'blog/post_detail.html', {'post': post})
#login_required
def post_new(request):
form = PostForm()
return render(request, 'blog/post_edit.html', {'form': form})
#login_required
def post_new(request):
if request.method == "POST":
form = PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.save()
return redirect('post_detail', pk=post.pk)
else:
form = PostForm()
return render(request, 'blog/post_edit.html', {'form': form})
#login_required
def post_draft_list(request):
posts = Post.objects.filter(published_date__isnull=True).order_by('created_date')
return render(request, 'blog/post_draft_list.html', {'posts': posts})
#login_required
def post_publish(request, pk):
post = get_object_or_404(Post, pk=pk)
post.publish()
return redirect('post_detail', pk=pk)
#login_required
def publish(self):
self.published_date = timezone.now()
self.save()
#login_required
def post_remove(request, pk):
post = get_object_or_404(Post, pk=pk)
post.delete()
return redirect('post_list')
#login_required
def post_edit(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == "POST":
form = PostForm(request.POST, instance=post)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.published_date = timezone.now()
post.save()
return redirect('post_detail', pk=post.pk)
else:
form = PostForm(instance=post)
return render(request, 'blog/post_edit.html', {'form': form})
#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()
return redirect('post_detail', pk=post.pk)
else:
form = CommentForm()
return render(request, 'blog/add_comment_to_post.html', {'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)

You can control it just by checking is authenticated user of session a author of entry.

Related

Unable to login using Django

This is my login view
def login_request(request):
if request.method == 'POST':
username = request.POST.get['username']
password = request.POST.get['password']
user = authenticate(username = username, password = password)
if user is not None:
form = login(request, user)
messages.success(request, f' welcome {username} !!')
return redirect('index')
else:
messages.info(request, f'Unable to Login now')
form = AuthenticationForm()
context = {'form':form}
return render(request, "BizzyCardApp/log-in.html", context)
and this is the log-in.html file
{% extends "BizzyCardApp/base.html" %}
{% block content %}
{% load crispy_forms_tags %}
<br>
<br>
<br>
<br>
<br>
<div class="container center oswald" id="grad" style="border-radius: 10%; width: 300px;">
<br>
<form>
<table class="table table-borderless table-responsive container">
<tbody>
<tr>
<div class="mb-3 mt-3">
<form method="POST">
{% csrf_token %}
{% for field in form %}
<div>
<p>{{ field.label }}: <br> {{ field }}</p>
{% for error in field.errors %}
<small style="color: red">{{ error }}</small>
{% endfor %}
</div>
{% endfor %}
</form>
</div>
</tr>
<tr>
<div class="d-flex justify-content-center">
<button type="submit" class="btn btn-light center text-center">Submit</button>
</div>
</tr>
</tbody>
</table>
</form>
<div class="text-center">
<a href="/sign-up/" class="link-dark">
Don't have an account? Sign Up
</a>
</div>
</div>
{% endblock %}
Once I hit the Submit button, it's supposed to redirect me to the index page but all that happens is that the GET request is done but there is no response from the backend to redirect. It just stays on the same page and the URL changes to
http://127.0.0.1:8000/login/?csrfmiddlewaretoken=0rkrC5wOe8LDQc9x0s0Zdag45PXRZixJAYaQns3dod58QhUL6OdmTEvZMYdRNTfq&username=tushar&password=abcd123*
Try this login view:
def login_request(request):
if request.method == 'GET':
if request.user.is_authenticated:
return redirect('/index/')
if request.method=='GET':
form = loginForm(request.POST)
if form.is_valid():
user=authenticate(username=form.cleaned_data['username'],
password=form.cleaned_data['password'])
if user:
print('user',user)
login(request,user)
return redirect('/index/')
else:
print('Not authenticated')
elif request.method=='GET':
if request.user.is_authenticated:
return redirect('/index/')
form=loginForm()
return render(request,'users/login.html',{'form':form})
In forms.py:
Add this:
class CustomAuthenticationForm(AuthenticationForm):
def confirm_login_allowed(self, user):
if not user.is_active or not user.is_validated:
raise forms.ValidationError('There was a problem with your login.', code='invalid_login')
And in login view, change AuthenticationForm to CustomAuthenticationForm. And import it in login view using below code.
from .form import CustomAuthenticationForm
Finally figured out the answer. The method for the tag wasn't given as POST.
The tag was just and not
The backend kept on getting GET requests instead and that's why the code wasn't working.
This is the Login method code I'm using now
def Login(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username = username, password = password)
if user is not None:
form = auth_login(request, user)
messages.success(request, f' welcome {username} !!')
return redirect('/')
else:
messages.info(request, f'account done not exit plz sign in')
form = AuthenticationForm()
return render(request,'BizzyCardApp/log-in.html',{'form':form})

URL pathfinder in Django - any workaround when it keeps redirecting me to main view?

Sorry for being an embarrassing noob, but I have managed to complete like 99% of the Django Girls tutorial only to realize that there is one essential function in my basic blog site that's not working - the post titles on the main view don't link to their respective post views, even though the code seems alright to me... Guess I am really missing a glaringly obvious mistake! I was considering to switch from pk to slug, could that be an effective workaround?
views.py
from django.shortcuts import render, get_object_or_404
from django.shortcuts import redirect
from django.utils import timezone
from .models import Post
from .forms import PostForm
def post_list(request):
posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
return render(request, 'blog/post_list.html', {'posts': posts})
def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, 'blog/post_detail.html', {'post': post})
def post_new(request):
if request.method == "POST":
form = PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.published_date = timezone.now()
post.save()
return redirect('post_detail', pk=post.pk)
else:
form = PostForm()
return render(request, 'blog/post_edit.html', {'form': form})
def post_edit(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == "POST":
form = PostForm(request.POST, instance=post)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.published_date = timezone.now()
post.save()
return redirect('post_detail', pk=post.pk)
else:
form = PostForm(instance=post)
return render(request, 'blog/post_edit.html', {'form': form})
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.post_list, name='post_list'),
path('post/<int:pk>/', views.post_detail, name='post_detail'),
path('post/new/', views.post_new, name='post_new'),
path('post/<int:pk>/edit/', views.post_edit, name='post_edit'),
]
post_detail.html
{% extends 'blog/base.html' %}
{% block content %}
<article class="post">
<aside class="actions">
{% if user.is_authenticated %}
<a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}">
{% include './icons/pencil-fill.svg' %}
</a>
{% endif %}
</aside>
{% if post.published_date %}
<time class="date">
{{ post.published_date }}
</time>
{% endif %}
<h2>{{ post.title }}</h2>
<p>{{ post.text|linebreaksbr }}</p>
</article>
{% endblock %}
post_list.html
% extends 'blog/base.html' %}
{% block content %}
{% for post in posts %}
<article class="post">
<time class="date">
{{ post.published_date }}
</time>
<h2>{{ post.title }}</h2>
<p>{{ post.text|linebreaksbr }}</p>
</article>
{% endfor %}
{% endblock %}
Thank you for your patience!

How to convert string to CharField

In my project there is an opportunity even for unauthorized users to leave a comment to a post. So, I have commentForm:
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('author', 'text',)
and model:
class Comment(models.Model):
post = models.ForeignKey('blog.Post', on_delete=models.CASCADE, related_name='comments')
author = models.CharField(max_length=200)
text = models.TextField()
If user is authorized, I want to substitute to author fileld username and don't show the input on page, otherwise site visitor should fill this input himself. I've tried to write this in appropriate view:
if request.user.is_authenticated:
form = CommentForm(request.POST, initial={'author': request.user.username})
But form.is_valid is false.
Then I've tried:
if request.user.is_authenticated:
form.fields['author'] = request.user.username
During form validating appeared 'string' object has no attribute 'disabled'.
The question is how to deal with it the right way? Thanks.
post_detail.html
{% extends 'blog/base.html' %}
{% block content %}
<div class="post">
{% if post.published_date %}
<div class="date">
{{ post.published_date }}
</div>
{% else %}
<a class="btn btn-default" href="{% url 'post_publish' post_id=post.pk blog_id=blog.pk %}">Publish</a>
{% endif %}
{% if user.is_authenticated and user == post.blog.author%}
<a class="btn btn-default" href="{% url 'post_remove' post_id=post.pk blog_id=blog.pk %}">удалить</a>
<a class="btn btn-default" href="{% url 'post_edit' post_id=post.pk blog_id=blog.pk %}">редактировать</a>
{% endif %}
<h1>{{ post.title }}</h1>
<p>{{ post.text|safe|linebreaks }}</p>
</div>
<hr>
<p>New comment</p>
<form method="POST" class="post-form">{% csrf_token %}
<!-- HERE I HIDE AUTHOR FIELD FROM LOGGED IN USERS -->
{% if user.is_authenticated %}
{{ form.text }}
{{ form.text.errors }}
{% else %}
{{ form.as_p }}
{% endif %}
<button type="submit" class="save btn btn-default">Send</button>
</form>
{% for comment in post.comments.all %}
<div class="comment">
<div class="date">
{{ comment.created_date }}
<!-- {% if not comment.approved_comment %} -->
<a class="btn btn-default" href="{% url 'comment_remove' post_id=post.pk blog_id=blog.pk com_id=comment.pk %}">удалить</a>
<!-- {% endif %}-->
</div>
<strong>{{ comment.author }}</strong>
<p>{{ comment.text|linebreaks }}</p>
</div>
{% empty %}
<p>No comments here yet :(</p>
{% endfor %}
{% endblock %}
views.py
from .models import Post, Comment, Blog
from django.shortcuts import render
from django.utils import timezone
from django.shortcuts import render, get_object_or_404
from .forms import PostForm, CommentForm, BlogForm
from django.shortcuts import redirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth import logout, login
from django.contrib.auth.models import User
def post_detail(request, blog_id, post_id):
blog = get_object_or_404(Blog, pk=blog_id)
post = get_object_or_404(Post, pk=post_id)
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
if request.user.is_authenticated:
comment.author = request.user.username
comment.post = post
comment.save()
return redirect('post_detail', blog_id=blog_id, post_id=post.pk)
else:
form = CommentForm()
return render(request, 'blog/post_detail.html', {'post': post, 'blog': blog, 'form': form})
#login_required
def post_publish(request, blog_id, post_id):
post = get_object_or_404(Post, pk=post_id)
post.publish()
return redirect('post_detail', blog_id=blog_id, post_id=post.pk)
#login_required
def post_remove(request, blog_id, post_id):
post = get_object_or_404(Post, pk=post_id)
post.delete()
return redirect('post_list', blog_id=blog_id)
#login_required
def comment_remove(request, blog_id, post_id, com_id):
comment = get_object_or_404(Comment, pk=com_id)
comment.delete()
return redirect('post_detail', blog_id=blog_id, post_id=post_id)
#login_required
def post_edit(request, blog_id, post_id):
post = get_object_or_404(Post, pk=post_id)
if request.method == "POST":
form = PostForm(request.POST, instance=post)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.save()
return redirect('post_detail', blog_id = blog_id, post_id=post.pk)
else:
form = PostForm(instance=post)
return render(request, 'blog/post_edit.html', {'form': form})
def post_list(request, blog_id):
blog = get_object_or_404(Blog, pk=blog_id)
posts = blog.posts.all().filter(published_date__isnull=False).order_by('published_date')
return render(request, 'blog/post_list.html', {'posts': posts, 'blog': blog})
I don't know if this is the best way to solve my problem, but it helped:
change a form value before validation in Django form

Why does a Contact Form fail to work with jinja tags?

I can successfully create a contact form with Django (2.1).
When I put the form tags inside with {% csrf_token %} inside a {% block content %}{% endblock %} in a HTML template, I cannot get the "success" page to "fire".
Why would this happen when I use the jinja tags?
Middleware:
'django.middleware.csrf.CsrfViewMiddleware',
urls.py
from django.conf.urls import url, include
from django.urls import path
from . import views
# from django.contrib.auth.views import login
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^$', views.about, name='about'),
url(r'^$', views.howitworks, name='services'),
url(r'^$', views.showroom, name='showroom'),
url(r'^privacy/', views.privacy, name='privacy'),
url(r'^terms-of-service/', views.tos, name='terms-of-service'),
url(r'^contact/', views.emailView, name='contact'),
# path('email/', views.emailView, name='email'),
path('success/', views.successView, name='success'),
]
views.py
from django.shortcuts import render, redirect
from django.http import HttpResponse, HttpResponseRedirect
from django.core.mail import send_mail, BadHeaderError
from .forms import ContactForm
def index(request):
return render(request, 'home/landing.html')
def about(request):
return render(request, 'home/landing#about.html')
def howitworks(request):
return render(request, 'home/landing#services.html')
def showroom(request):
return render(request, 'home/landing#portfolio.html')
def privacy(request):
return render(request, 'home/privacy.html')
def tos(request):
return render(request, 'home/terms-of-service.html')
# def contact(request):
# return render(request, 'home/contact.html')
# def login(request):
# return render(request, 'auth/account/login.html')
# def signup(request):
# return render(request, 'auth/account/signup.html')4
def emailView(request):
if request.method == 'GET':
form = ContactForm()
else:
form = ContactForm(request.POST)
if form.is_valid():
first_name = form.cleaned_data['first_name']
last_name = form.cleaned_data['last_name']
subject = form.cleaned_data['subject']
from_email = form.cleaned_data['from_email']
message = form.cleaned_data['message']
try:
send_mail(subject, message, from_email, ['peterdoh#gmail.com'])
except BadHeaderError:
return HttpResponse('Invalid header found.')
return redirect('success')
return render(request, "home/contact.html", {'form': form})
def successView(request):
# return HttpResponse('Success! Thank you for your message to Revs Direct.')
return render(request, "home/success.html", {})
contact.html
{% extends "home/base.html" %}
{% load staticfiles %}
{% block header %}
{% include 'home/header1.html' %}
{% endblock %}
{% block content %}
<h3 class="section-title">Contact Us</h3>
<p class="section-description">We d love to hear from you. Please fill in the form below with any queries or questions that
you may have.</p>
<div class="container wow fadeInUp">
<div class="row justify-content-center">
<div class="col-lg-3 col-md-4">
<div class="info">
<!-- <div>
<i class="fa fa-map-marker"></i>
<p>A108 Adam Street<br>New York, NY 535022</p>
</div> -->
<!-- <div>
<i class="fa fa-envelope"></i>
<p>info#revsdirect.com</p>
</div> -->
<!-- <div>
<i class="fa fa-phone"></i>
<p>HOLD</p>
</div> -->
</div>
<div class="social-links">
<h3>Social Media</h3>
<a href="#" class="facebook">
<i class="fab fa-facebook-f"></i>
</a>
<a href="#" class="instagram">
<i class="fab fa-instagram"></i>
</a>
<a href="#" class="twitter">
<i class="fab fa-twitter"></i>
</a>
<!-- <i class="fa fa-google-plus"></i>
<i class="fa fa-linkedin"></i> -->
</div>
</div>
<div class="col-lg-5 col-md-8">
<div class="form">
<!-- <div id="sendmessage">Your message has been sent. Thank you!</div>
<div id="errormessage"></div> -->
<form role="form" action="" method="post" class="contactForm">{% csrf_token %}
{{ form.as_p }}
<div class="form-actions">
<button type="submit">Send</button>
</div>
</form>
</div>
</div>
</div>
{% endblock %}
Have you saved your form?
if form.is_avlid():
myform = form.save(commit=False)
# add as per your requirement
myform.save()
return statement
I found a working solution using guidance from https://hellowebbooks.com/news/tutorial-setting-up-a-contact-form-with-django/.
In contact.html, I used:
<div class="container">
<br>
<br>
<h2>Contact</h2>
<p>Send me a message</p>
{% if messages %}
<div class="row">
<div class="col-xs-12">
{% for message in messages %}
<p {% if message.tags %} class="{{ message.tags }}" {% endif %}>{{ message }}</p>
{% endfor %}
</div>
</div>
{% endif %}
<form role="form" action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<button class="button primary type=" submit">Send Message</button>
</form>
</div>
Then in my forms.py:
from django import forms
class ContactForm(forms.Form):
contact_name = forms.CharField(required=True)
contact_email = forms.EmailField(required=True)
content = forms.CharField(
required=True,
widget=forms.Textarea(attrs={'rows': 4, 'cols': 40})
)
def __init__(self, *args, **kwargs):
super(ContactForm, self).__init__(*args, **kwargs)
self.fields['contact_name'].label = "Your name:"
self.fields['contact_email'].label = "Your email:"
self.fields['content'].label = "Your message:"
and finally, my views.py:
from django.shortcuts import render, redirect
from django.http import HttpResponse, HttpResponseRedirect
from .forms import ContactForm
from django.contrib import messages
from django.core.mail import EmailMessage
from django.template.loader import get_template
# Create your views here.
def index(request):
form_class = ContactForm
# new logic!
if request.method == 'POST':
form = form_class(data=request.POST)
if form.is_valid():
contact_name = request.POST.get('contact_name', '')
contact_email = request.POST.get('contact_email', '')
form_content = request.POST.get('content', '')
# Email the profile with the
# contact information
template = get_template('landing/contact_template.txt')
context = {
'contact_name': contact_name,
'contact_email': contact_email,
'form_content': form_content,
}
content = template.render(context)
email = EmailMessage(
"[Peter Doherty] New contact form submission",
content,
"Peter Doherty" +'',
['peterdoh#gmail.com'],
headers = {'Reply-To': contact_email }
)
email.send()
messages.success(request, 'Thank you. Message sent.')
# return redirect('^$')
return render(request, 'landing/index.html', {'form': form_class,})
It was unclear why the first approach was throwing up an error. This approach works and have tested in. Also, ensure that your email configuration is correct in the settings.py file.

nothing happens when submitting django form

I have a problem with django forms, when submitting a form nothing seems to happen, even the server didn't get any response except GET request to view the form template.
here is my code for the forms.py :
from django.forms import ModelForm
from .models import Post
class PostForm(ModelForm):
class Meta:
model = Post
fields = [
"title",
"content",
"category"
]
and here is my post_form.html :
{% extends 'base.html' %}
{% block content %}
<h1>form</h1>
<form method="POST" action=".">
{% csrf_token %}
{{ form.as_p }}
</form>
<button type="submit">Create Post</button>
{% endblock content %}
and here is my handling for the form in views.py :
def post_create(request):
if request.method == "POST":
form = PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.save()
return redirect("posts:detail", pk=post.pk)
else :
form = PostForm()
context = {
"form":form,
}
return render(request,"post_form.html", context)
forms.py
from django.forms import ModelForm
from .models import Post
class PostForm(ModelForm):
class Meta:
model = Post
fields = ["title", "content", "category"]
views.py
def post_create(request):
form = PostForm()
if request.method == "POST":
form = PostForm(request.POST)
if form.is_valid():
post = form.save()
return redirect("posts:detail", pk=post.pk)
return render(request,"post-form.html", {"form": form})
post-form.html
{% extends 'base.html' %}
{% block content %}
<h1>form</h1>
{% for error in form.non_field_errors %}
<article class="message is-danger alert-message">
<div class="message-body">
<p>{{ error|escape }}</p>
</div>
</article>
{% endfor %}
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Create Post">
</form>
{% endblock content %}
in your views:
if form.is_valid():
form.commit = False
form.save()
or
if form.is_valid():
form.save(commit=false)
I suggest the latter
Don't Forget Place Your Submit Button In Form Tag !