Django restricting users from updating/deleting other users posts - python

views.py
#login_required(login_url='/login')
def updatepost(request,pk):
post = Post.objects.get(id=pk)
form = PostForm(instance=post)
if request.method =='POST':
form = PostForm(request.POST, request.FILES, instance=post)
if form.is_valid():
form.save()
return redirect ('mainpage')
context = {'form':form}
return render( request, 'postform.html', context )
postform.html
{% include 'main.html'%}
{% block content %}
{%if user.is_authenticated%}
{% if user.id == post.user.id%}
<div>
<form method="POST" action ="">
{% csrf_token %}
{{form.as_p}}
<input type="Submit" value ="Submit"/>
</form>
</div>
{%endif%}
{%endif%}
{% endblock content %}
I am trying to restrict user who is logged in - from updating , deleting other users posts.
However when I Try to use {% if user.id == post.user.id%} , the page becomes blank even for the user who is editing his own post. The same goes for deleting.
It works on mainpages - where posts are displayed (it hides edit and delete buttons).
What is the reason that the post is not showing inside the template ?
I don't understand that even {{post.user}} in postform.html does not appear , neither on deleteform etc. - why this data of objects of a post is not being sent to postform.html ?

You should change the context to access the post instance from your template.
context = {'form': form, 'post': post}
You can only access the context values from the templates. So pass the ones you want to use while you are returning a response.

Related

Django form requires resubmission

I have a simple form in Django, and in my template I want to display each individual object for the whole queryset which I am saving the form to. The error I am getting is that my form does not seem to submit on the first attempt. Only when I click the submit button, manually refresh the page and then 'confirm form resubmission' do I see my updated queryset objects displayed in the template.
I am saving my form like this in my views:
exercise_name = ExerciseName.objects.all()
if request.method == 'POST':
form = ExerciseNameForm(request.POST)
if form.is_valid():
form.save(commit=True)
else:
form = ExerciseNameForm()
and passing the queryset to the template through the following context:
{ 'exercise_name': exercise_name }
and iterating through it like
{% for exercise_title in exercise_name %}
#content displaying each iteration
{% endfor %}
with my form to update it like:
<div>
<form method = "POST">{% csrf_token %}
{{form.as_p}}
<button type="submit" class="save btn btn-default">Save</button>
</form>
</div>
I am not sure why it is making me refresh the page and resubmit the form again in order to see the updated queryset after submitting the form?
You should be doing something like this:
if request.method == 'POST':
form = ExerciseNameForm(request.POST)
if form.is_valid():
form.save(commit=True)
return HttpResponse("data submitted successfully")
else:
return render(request, "your_template.html", {'form':form})
else:
form = ExerciseNameForm()
return render(request, "your_template.html", {'form':form})

"This field is required" when all fields are filled in Django

When filling out a form I get "This field is required." even though all fields are filled in.
It doesn't have to do with setting required to False or anything like that, because all fields are required.
views.py
def upload(request):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
title = form.cleaned_data['title']
username = request.user.get_username()
category = form.cleaned_data['category']
handle_uploaded_file(request.FILES['file'],title,username,category)
return HttpResponseRedirect('')
else:
form = UploadFileForm()
return render(request, 'main/upload.html', {'form': form})
function
def handle_uploaded_file(f,title,username,category):
with open('/uploads/' + category + '/' + title, 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)
forms.py
class UploadFileForm(forms.Form):
title = forms.CharField(max_length=50)
category = forms.CharField(max_length=50)
file = forms.FileField()
upload.html
{% extends 'base.html' %}
{% block title %}Upload{% endblock %}
{% block content %}
{% if user.is_authenticated %}
Uploading as: {{ user.username }}
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit"/>
</form>
{% else %}
<p>You are not logged in</p>
login
{% endif %}
{% endblock %}
The error I get when filling out a form is: "This field is required"
Screenshot:
When I select a file and it throws the error it unselects whatever file I've selected, similar to how the password field is cleared when hitting sign up without completing every field.
The file isn't being submitted with the request because you didn't sent the correct enctype on the form element. Here are Django's docs concerning that.
<form method="post" enctype="multipart/form-data">
One way to verify this/debug it would be to print the form's data form.data, request.POST and/or request.FILES before the call to is_valid. Or verifying the request in a browser's dev tools.

Display User Profile getting ERROR: 'AnonymousUser' object has no attribute '_meta'

I have a simple view that is suppose to check if there is post data,
if so update the user data using UserChangeForm. Else get the form
data of user and display.
Issue: AttributeError at /profile/edit 'AnonymousUser' object has no
attribute '_meta'
I think it might be this line in the edit_profile view
# Handles the get request - if no post info is submitted then get the form and display it on the edit profile page.
else:
form = UserChangeForm(instance=request.user)
args = {'form': form}
return render(request, 'accounts/profile_edit.html', args)
Not sure what. Here is the view.py edit_profile
def edit_profile(request):
# Handle post request - if the user submits a form change form details and pass the intance user
if request.method == 'POST':
form = UserChangeForm(request.POST, intance=request.user)
if form.is_valid():
form.save()
return redirect('accounts/profile')
# Handles the get request - if no post info is submitted then get the form and display it on the edit profile page.
else:
form = UserChangeForm(instance=request.user)
args = {'form': form}
return render(request, 'accounts/profile_edit.html', args)
profile_edit.html
{% extends 'base.html' %}
{% block head %}
<title>Profile</title>
{% endblock %}
{% block body %}
<div class="container">
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Save Changes</button>
</form>
</div>
{% endblock %}
You can't update an AnnonymousUser (that is special user class set for not logged in users). One solution of your problem is to disallow viewing this page by not authenticated user by decorating your view using login_required decorator.
You got error because there is not user logged in.
You can instead use try method.
In your code use if user.is_authenticated
if user.is_authenticated():
if request.method == 'POST':
form = UserChangeForm(request.POST, intance=request.user)
if form.is_valid():
form.save()
return redirect('accounts/profile')
# Handles the get request - if no post info is submitted then get the form and display it on the edit profile page.
else:
form = UserChangeForm(instance=request.user)
args = {'form': form}
return render(request, 'accounts/profile_edit.html', args)
else:
raise PermissionDenied

Unable to update CharField - Django

First of all I'm glad to be here, I read you lately and i found useful answers here.
This is my first post so please be kind with me, I'm a newbie in programming.
So, I'm writing my 1st web application in Django - a todo app and I don't know how to write the function that does this this. I found something in Django docs and in other related discussions but it doesn't work.
Here's my code:
#models.py
class Task(models.Model):
user = models.ForeignKey(User)
task = models.CharField(max_length=200)
initialized_at = models.DateTimeField(auto_now_add=True)
due_date = models.DateField(default=datetime.now)
done = models.BooleanField(default=False)
def __unicode__(self):
return self.task
#views.py
def edit_task(request, id):
if request.method == 'POST':
task_to_edit = Task.objects.get(pk=task_id)
form = TaskForm(request.POST, instance=task_to_edit)
form.save()
if form.is_valid():
task_to_edit = form.save()
return HttpResponseRedirect('/')
else:
form = TaskForm()
return render(request, 'todo/edit_task.html', {'form': form})
#urls.py
url(r'^edit_task/(?P<task_id>\w+)/$', 'todo.views.edit_task')
#edit_task.html
{% block content %}
<form action="/edit_task/" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
{% endblock content %}
When I submit the updated form I get this error:
Page not found (404)
Request Method: POST
Request URL: hxxp://127.0.0.1:8000/edit_task/
Using the URLconf defined in jbz.urls, Django tried these URL patterns, in this order:
^admin/
^$ [name='index']
^(?P<task_id>\d+)/$
^(?P<task_id>\d+)/$
^add-task/$
^delete-task/(?P<task_id>\w+)/$
^edit_task/(?P<id>\w+)/$
^done/(?P<task_id>\d*)/$
The current URL, edit_task/, didn't match any of these.
and the root urls.py looks like:
url(r'', include('todo.urls'))
#edit_task.html
{% block content %}
<form action="/edit_task/{{task.id}}" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
{% endblock content %}
Notice how I added {{task.id}} expression in <form action="/edit_task/{{task.id}}" method="post">
IMPORTANT NOTE: Substitute {{task.id}} to whatever variable accomplishes this in your template.
The reason why you get the error is because edit_task/ is not getting the other part, task_id to match the regular expression:
url(r'^edit_task/(?P<task_id>\w+)/$', 'todo.views.edit_task')
UPDATE: Also your edit_task view has potential errors as well>
def edit_task(request, id):
task_to_edit = Task.objects.get(pk=id)
if request.method == 'POST':
form = TaskForm(request.POST, instance=task_to_edit)
form.save()
if form.is_valid():
task_to_edit = form.save()
return HttpResponseRedirect('/')
else:
form = TaskForm(instance=task_to_edit)
# you don't pass any task variable to the view so the form view
# won't know which task to edit, you'll have to handle that
return render(request, 'todo/edit_task.html', {'form': form, 'task':task_to_edit})
Note: I corrected the code in the view a little. Now the task_to_edit is passed also to the Form to fill the fields when the view is requested via GET. Notice that in order to access to this view, the url in the browser should look like this http://www.example.com/edit_task/2
If other wise you try to access http://www.example.com/edit_task without passing the id you'll get Error 404.
Hope this helps!
I think your pattern for edit task expects an id - task name. Try changing your URL pattern:
'^edit_task/(?P<task_id>\w+)/$'
to
'^edit_task/$'
or providing the task id that you want to edit.
Just add name space to your url and according update your template.
#urls.py
url(r'^edit_task/(?P<task_id>\w+)/$', 'todo.views.edit_task', name= "edit_task")
#edit_task.html
{% block content %}
<form action="{% url 'edit_task' task_id %}" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
{% endblock content %}

Require help in Django 'local variable 'form' referenced before assignment'

I am having problem in django. I have created a form in my app where I can take details of a client. Now I want to create a form which can allow me to edit a form. However I am having some problems when I go to /index/edit_client/1, I get this error.
local variable 'form' referenced before assignment
I do not know what the reason why I have got this error, but from what I have looked at, it does not help matters unless of course there is another way how to create an edit form to edit the clients form. Here are some output that can be helpful too.
# urls.py
urlpatterns = patterns('',
(r'^index/$', login_required(direct_to_template), { 'template': 'index.html' }),
(r'^index/clients/$', client_info),
(r'^index/clients_details/(?P<id>\d+)/$', clients_details),
(r'^index/edit_client/(?P<id>\d+)/$', edit_client),
)
# views.py
#login_required
def edit_client(request, id=1):
clients_list = Client.objects.filter(pk=id)
if request.method == 'POST':
form = ClientForm(request.POST or None)
if form.is_valid():
form.save()
return HttpResponseRedirect('/index/clients/')
else: form = ClientForm()
return render_to_response('edit_client.html', {'form': form}, context_instance=RequestContext(request))
#edit_client.html
{% extends "base.html" %}
{% block content %}
<font face="verdana,news gothic,arial,heltevica,serif">
<h3>Edit Client</h3>
</font>
<form method= "POST" action="">
<font face="verdana,news gothic,arial,heltevica,serif">
<div id="form">
<table>
{{form.as_table}}
</table>
<div align="center" STYLE=" margin-right:190px">
<input type="submit" value="Submit" STYLE="background-color:#E8E8E8; color:#181818 "/>
</div>
</div>
</form>
{% endblock %}
This will always run:
return render_to_response('edit_client.html', {'form': form}
But if request.method is not POST, nothing is assigned to form.
Fixed code:
#login_required
def edit_client(request, id=1):
clients_list = Client.objects.filter(pk=id)
form = ClientForm()
if request.method == 'POST':
form = ClientForm(request.POST or None)
if form.is_valid():
form.save()
return HttpResponseRedirect('/index/clients/')
return render_to_response('edit_client.html', {'form': form}, context_instance=RequestContext(request))
In your edit_client method, you pass form in the response, however, if the method wasn't a POST, you won't have initialized a form.

Categories

Resources