AttributeError at /mobile/7/delete/ 'tuple' object has no attribute '_meta' - django

I am trying to delete an item from my project but it gives error. interestingly it is deleting the item but gives error mention above.
views.py:
def delete_mobile(request, mobile_id):
mobile1 = get_object_or_404(Mobile, pk=mobile_id).delete()
form = MobileForm(instance=mobile1)
if form.is_valid():
form.delete()
return redirect('mobile')
return render(request, 'device/delete_mobile.html', {'mobile': mobile1})
delete_mobile.html:
{% extends 'device/base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<div class="container">
<form action="{% url 'delete_mobile' mobile.instance.id %}" method="POST">
{% csrf_token %}
<h3>Delete {{ header }}:</h3>
{{ mobile|crispy }}
<button class="btn btn-success" type="submit">Delete</button>
</form>
{% endblock %}
urls.py:
path('mobile/<str:mobile_id>/delete/', views.delete_mobile, name='delete_mobile'),

actually, the problem was occurring due to repetition of .delete() method in my delete view.
now I have fixed it and working properly.
def delete_mobile(request, mobile_id):
mobile1 = get_object_or_404(Mobile, pk=mobile_id)
form = MobileForm(instance=mobile1)
if form.is_valid():
form.delete()
return redirect('mobile')
return render(request, 'device/delete_mobile.html', {'mobile': mobile1})

Related

How to delete a record through a button in django

I have created a model Announcement in models.py file
class Announcement(models.Model):
title = models.CharField(max_length=30)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
teacher = models.ForeignKey(Teacher, on_delete=models.CASCADE)
def __str__(self):
return self.title
And for deleting a record of Announcement I have created the following view
def AnnouncementDelete(request, pk):
announcement = get_object_or_404(Announcement, pk=pk)
if request.method=='POST':
announcement.delete()
return redirect('/')
return render(request, 'classroom/announcement_confirm_delete.html', {'announcement': announcement})
The delete view of announcement (that is AnnouncementDelete) has the following url
path("delete/<int:pk>/", view=views.AnnouncementDelete, name="AnnouncementDelete"),
If i enter
http://127.0.0.1:8000/classroom/delete/3
on browser it is deleting the Announcement having pk = 3
Now I want a button to directly delete my record without the need of typing http://127.0.0.1:8000/classroom/delete/3 on browser
I have tried the following methods in my allannouncement.html file
{% extends "classroom/base.html" %}
{% block content %}
<h1>Announcements</h1>
{% for announcement in announcements %}
<!-- starting loop (posts is keyword from view) -->
<div style="border-style: solid;">
{% if announcement.teacher.user == request.user %}
<div>
Delete
</div>
{% endif %}
{{ announcement.pk }}
<a class="mr-2">Posted by: {{ announcement.teacher }}</a>
<h2><a class="article-title">{{ announcement.title }}</a></h2>
<p class="article-content">{{ announcement.content}}</p>
</div>
{% endfor %}
{% endblock content %}
but it is giving the following error
NoReverseMatch at /classroom/allannouncement/
Reverse for 'AnnouncementDelete' with no arguments not found. 1 pattern(s) tried: ['classroom/delete/(?P<pk>[0-9]+)/$']
then I also tried passing pk with url like
Delete
But it is giving the following error
TemplateSyntaxError at /classroom/allannouncement/
Could not parse the remainder: ',' from ','
Remove common #refer this
Delete
instead of a link add a form.
Add
{% load crispy_forms_tags %}
in your html file and then add
{% if announcement.teacher.user == request.user %}
<div>
<form action="{% url 'classroom:AnnouncementDelete' announcement.id %}"
method="post">
{% csrf_token %}
<input type="submit" value="Delete">
</form>
</div>
{% endif %}

How to render template after failed form validation?

urls.py:
urlpatterns = [
path('employee/add_employee/', views.add_employee, name='add-employee'),
path('employee/add_employee/add/', views.add_employee_action, name='add-employee-action'),
]
I have add-employee page and some forms to fill there.
views.py:
def add_employee(request):
personal_form = PersonalEmployeeForm()
history_form = EmployeeHistoryForm()
return render(
request,
'sections/add_employee.html',
context={
'personal_form': personal_form,
'history_form': history_form,
}
)
def add_employee_action(request):
if request.method == "POST":
personal_form = PersonalEmployeeForm(request.POST)
history_form = EmployeeHistoryForm(request.POST)
if personal_form.is_valid() and history_form.is_valid():
# here is some logic with models
return redirect('add-employee')
else:
personal_form = PersonalEmployeeForm()
history_form = EmployeeHistoryForm()
return render(
request,
'sections/add_employee.html',
context={
'personal_form': personal_form,
'history_form': history_form,
}
)
template:
<form id="a-submit-form" action="add/" method="POST">
{% csrf_token %}
<div class="column-wrapper">
<div class="column">
<div class="form-wrapper">
{% for field in personal_form.visible_fields %}
{% include "elements/forms/form_line.html" %}
<br>
{% endfor %}
</div>
</div>
<div class="column">
<div class="form-wrapper">
{% for field in history_form.visible_fields %}
{% include "elements/forms/form_line.html" %}
<br>
{% endfor %}
</div>
</div>
</div>
<div class="button-bar-wrapper">
<div class="button_bar">
<a class="a-button positive" id="submit">Добавить</a>
<a class="a-button" href="{% url 'employee' %}">Сотрудники</a>
<a class="a-button" href="{% url 'index' %}">На главуную</a>
</div>
</div>
</form>
Submitting by <a> element is tested and worked well with jQuery script.
The problem is after submitting invalid forms I have a page with blah-blah/employee/add_employee/add/ URL. And if I try to submit forms again I have a page with blah-blah/employee/add_employee/add/add/ URL, which is incorrect. How can I render the page with blah-blah/employee/add_employee/ URL and show all error messages?
This is likely because you have written a relative URL in the <form> tag of the sections/add_employee.html template. The template thus contains something like:
<form method="post" action="add/">
...
</form>
You can use a URL with the {% url … %} template tag [Django-doc]:
<form method="post" action="{% url 'add-employee-action' %}">
...
</form>
Furthermore one usually uses the same path to handle both the GET and the POST request. So in fact you might simply remove the 'add-employee' path.

Django: How to add comments under post

I have trouble adding comments under my posts on the website I'm creating using Django.
This is my story.html file, which is supposed to show the story title, the story itself, all the comments of the story and give users the ability to add a new comment. Although the form is shown, it is not usable. Even though I have added comments to the stories manually through admin, none of them is shown.
{% extends "pinkrubies/base.html" %}
{% block content %}
<div class="post-preview">
<h2 class="post-title"> {{ story.title }}</h2>
<p class="post-subtitle">
{{ story.story }}
</p>
</div>
<div class="post-preview">
{% for com in latest_comments %}
<div class="post-preview">
<p class="post-subtitle"> {{ comment.com }} </p>
</div>
{% endfor %}
</div>
{% if user_id %}
<div class="post-preview">
<form action="{% url 'pinkrubies:story' user.id story.id %}" method="post">
{% csrf_token %}
<div class="form-group">
<p class="post-title">
Comments
</p>
<textarea id="text" name="text"class="form-control" placeholder="Comment" rows="4">{{ comment.com }}
</textarea>
</div>
<button type="submit" class="btn btn-primary"> Submit </button>
</form>
</div>
{% else %}
<p class="post-meta">You must have an account to comment. Log in or Register</p>
{% endif %}
{% endblock %}
views.py
def story_view(request, user_id, story_id):
latest_comments = Comment.objects.order_by('-date')
if story_id is not None:
story = get_object_or_404(Story, pk=story_id)
else:
story = Story()
story.user_id = user_id
if request.method == 'POST':
story.title = request.post.get('title')
story.story = request.post.get('story')
story.date = timezone.now()
story.save()
return HttpResponseRedirect(reverse('pinkrubies:story', args=(user_id,)))
else:
context = {
'user_id': user_id,
'story_id': story_id,
'title': story.title,
'story': story,
'comments': story.comments,
'latest_comments': latest_comments
}
return render(request, 'pinkrubies/story.html', context)
def comment_view(request, comment, user_id):
latest_comments = Comment.objects.order_by('-date')
if request.method == 'POST':
comment.com = request.POST['com']
comment.date = timezone.now()
comment.save()
return HttpResponseRedirect(reverse('pinkrubies:story', args=(user_id,)))
else:
context = {'latest_comments': latest_comments}
return render(request, 'pinkrubies/story.html', context)
I am aware I have added the "latest_comments" in both views, I did that to see if any of it works and it doesn't. I'm not even sure that the comment_view is needed.
Also, when I try to submit a comment, this error is thrown:
AttributeError: 'WSGIRequest' object has no attribute 'post'
in story_view story.title = request.post.get('title')
Any help is welcome!
Thank you !!!
First of all, if you want to get something from POST, you should use request.POST.get('title'); although I would rather use a Form and let it handle the request.
At a first glance, this:
{% for com in latest_comments %}
<div class="post-preview">
<p class="post-subtitle"> {{ comment.com }} </p>
</div>
{% endfor %}
Sould be
{% for comment in latest_comments %}
<div class="post-preview">
<p class="post-subtitle"> {{ comment.com }} </p>
</div>
{% endfor %}
In your code, you're using com to iterate through latest_comments, yet you try to use comment to access com attribute (not sure how your Comment model looks like though)
It's accessed via request.POST. WSGIRequest object does not have a post field it has POST field.
Also, you are not sending the fields you are attempting to read from request.
...
story.title = request.POST.get('title')
story.story = request.POST.get('story')
...
only field you are sending is called text and it should be accessed like this
text = request.POST.get('text')
also template has more errors please check your code once again.

Django 2.1 NoReverseMatch error Using post method in Class Based Views

Url :
re_path(r'^detail/(?P<slug>\w+)/$', ProblemDetail.as_view(), name='problem_detail'),
View :
class ProblemDetail(View):
template_name='problem/problem_detail.html'
form_class=AnswerForm
def get(self,request,slug):
context={'problem':Problem.objects.get(slug=slug),'form':self.form_class()}
return render(request,self.template_name,context)
def post(self,request,slug):
bound_form=self.form_class(request.POST)
obj=Problem.objects.get(slug=slug)
real_answer=obj.answer
if bound_form.is_valid():
if bound_form.cleaned_data['answer'] == real_answer:
return render(request,
'problem/Answerstatus.html',
{'message':'Good Job !'})
else:
return render(request,
'problem/Answerstatus.html',
{'message':'Wrong ! Try Again !'})
Template :
{% extends "problem/base_problem.html" %}
{% block content%}
<h2>{{problem.p_name}}</h2>
<h3>{{problem.difficulty}}</h3>
<p>{{problem.p_description}}</p>
<form action= "{% url 'problem_detail' %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" > Check </button>
</form>
{% endblock %}
The above template is a rough idea for testing (Its not Final template,needs tons of changes, we know that.)
I get the following error :
Reverse for 'problem_detail' with no arguments not found. 1 pattern(s) tried: ['detail/(?P<slug>\\w+)/$']
You should add slug argument when you are returning in post method. Try returning HttpResponseRedirect and reverse to your url together with slug in args list.
return HttpResponseRedirect(reverse('problem_detail', args=[slug]))
It looks as if the problem is occuring in a {% url %} tag in your problem/Answerstatus.html, but we can't be sure because you haven't included that template in your question.
It looks as if you need to include the problem in your template whenever you render the template, for example,
return render(request, 'problem/Answerstatus.html', {'problem': obj, 'message':'Good Job !'})
and then in the template, include the slug in the {% url %} tag:
{% url 'problem_detail' problem.slug %}
Add get_absolute_url method to your model like this :
def get_absolute_url(self):
return reverse('problem_detail',kwargs={'slug':self.slug})
Also in your templates :
{% block body-block %}
<h2>{{problem.p_name}}</h2>
<h5>{{problem.difficulty}}</h5>
<p>{{problem.p_description}}</p>
<form action= "{{ problem.get_absolute_url }}" method="post"> # Pay Attention here
{% csrf_token %}
{{ form.as_p }}
<button type="submit" > Check </button>
</form>
{% endblock %}
This will fetch the url and the regex will match .

How to change the value of ENDLESS_PAGINATION_PER_PAGE from template side?

I use Django Endless Paginator plugin.
I try to change the value of ENDLESS_PAGINATION_PER_PAGE from template side.
As default is 10.
I want to realize some dropbox where the user can change between (Example: 10,20,50,100 Objects).
Thanks for answer, but something not work property.
1. I have view.py
def adv_search(request):
objects = None
if request.GET.get('key'):
form = AdvancedSearchForm(request.GET)
if form.is_valid():
repo = Repository()
objects = list(repo.find_objects('*'+form.cleaned_data['key'] +'*', type=FileObject, chunksize=20))
return render(request, 'templates/adv_search.html', {'form': form, 'objects': objects })
return render(request, 'templates/adv_search.html', {'form': AdvancedSearchForm(), 'objects': objects})
2. Then forms.py
class AdvancedSearchForm(forms.Form):
key = forms.CharField(max_length=500, label="", widget= forms.TextInput(attrs={'class': 'label'}))
show_props = forms.MultipleChoiceField(choices = (("pid", "pid"),("title", "title"),("type","type"),("source","source"),("date","date"),("publisher","publisher"),("subject","subject"),("label","label"),("cDate","cDate"),("mDate","mDate")),required=False, widget=forms.CheckboxSelectMultiple(attrs={'class': 'my-class'}))
paginator = forms.ChoiceField(choices =(('10', '10'),('20','20'), ('50','50'), ('100','100')) ,required=False, )
3. adv_search.html
{% paginate paginator objects %}
{% for obj in objects %}
...
<div class="paginator">
{% get_pages %}
{{ pages.first_as_arrow }}
{% show_pages %}
{{ pages.last_as_arrow }}
<form method="get">
{{ form.paginator }}
<input type="submit" Value="Go">
</form>
{{ pages.total_count }} total objects
</div>
Everything works except select
Thanks Andrey
You can have a form which will set pagination per page and then use that submitted value in template. Here is an example:
View
from django.shortcuts import render
from .models import Entry
def endless_view(request):
pagination_per_page = request.GET.get('per_page', 10)
entries = Entry.objects.all()
return render(request, 'some_template.html', {'pagination_per_page':
pagination_per_page, 'entries': entries})
Template
{% extends 'base.html' %}
{% load endless %}
{% block content %}
{# #}
<form action="" method="get">
<select name="per_page">
<option value="10">10 per page</option>
<option value="20">20 per page</option>
<option value="50">50 per page</option>
<option value="100">100 per page</option>
</select>
<input type="submit" Value="Go">
</form>
{% paginate pagination_per_page entries %}
{% for entry in entries %}
{# your code to show the entry #}
{% endfor %}
{% show_pages %}
{% endblock content %}
Reference
http://django-endless-pagination.readthedocs.org/en/latest/templatetags_reference.html