I want to learn python and web-dev and I am trying to make a functional web application. Right now I have problem with django-autocomplete-light.
I am trying to use autocomplete for my django application. I followed the tutorial, but when I try to search It says that The results could not be loaded.
But results are shown in dropdown list.
I have a form where user can add new invoce, I am trying to use django-autocomplete-light for autocompleting all suppliers so user, doesn't need to search for it.
My models:
class Supplier(models.Model):
supp_name = models.CharField(max_length=255)
mat_number = models.CharField(max_length=255)
organ = models.CharField(max_length=255, null=True, blank=True)
street = models.CharField(max_length=255, null=True, blank=True)
email = models.CharField(max_length=255, null=True, blank=True)
def __str__(self):
return self.supp_name.encode("utf-8")
def get_absolute_url(self):
return reverse('supplier-detail', args=[str(self.id)])
def __unicode__(self):
return '%s' % (self.supp_name,)
class Invoice(models.Model):
organization = models.ForeignKey(Group, help_text="organization")
input_peo = models.CharField(max_length=150)
date = models.DateTimeField(auto_now_add=True)
supplier = models.ForeignKey(Supplier, on_delete=models.SET_NULL, null=True, related_name='name')
invoice_number = models.CharField(max_length=100, null=True, blank=True, help_text='Številka preračuna')
price = models.FloatField(null=True, blank=True, help_text='Cena brez DDV')
sum_me = models.IntegerField(null=True, blank=True, help_text='Kolicina')
def __str__(self):
return self.organization.name.encode("utf-8")
def get_absolute_url(self):
return reverse('invoice-detail', args=[str(self.id)])
My views:
class AddInvoice(LoginRequiredMixin, generic.View):
login_url = '/accounts/login/'
redirect_field_name = 'redirect_to'
form_class = InvoiceCreate
template_name = 'invoce/invoce_form.html'
def get(self, request):
form = self.form_class(None)
return render(request, self.template_name, {'form': form})
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
invoice = form.save(commit=False)
invoice.organization = request.user.groups.first()
invoice.input_peo = self.request.user.get_full_name()
invoice.supplier = form.cleaned_data['supplier']
invoice.invoice_number = form.cleaned_data['invoice_number']
invoice.price = form.cleaned_data['price']
invoice.sum_me = form.cleaned_data['sum_me']
invoice.save()
return HttpResponseRedirect('/')
return render(request, self.template_name, {'form': form})
'''
*
AUTOCOMPLETE
*
'''
class SupplierAutoComplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
qs = Supplier.objects.all()
if self.q:
qs = qs.filter(name__istartswith=self.q)
return qs
urls:
urlpatterns += [
url(
r'^autocomplete/$',
views.SupplierAutoComplete.as_view(model=Supplier),
name='supplier-autocomplete',
),
]
If I search just for autocomplete (/autocomplete/) in browser this is what i get:
my forms.py:
class InvoiceCreate(forms.ModelForm):
class Meta:
model = Invoice
fields = [
'supplier',
'invoice_number',
'price',
'sum_me',
]
widgets = {
'supplier': autocomplete.ModelSelect2(url='supplier-autocomplete')
}
and finally my template for form:
{% extends "base_generic.html" %}
{% block content %}
<div class="jumbotron">
<div class="row" style="margin-top:60px">
<form action="" method="post">
{% csrf_token %}
<!-- Left Inputs -->
<div class="col-xs-6 wow animated slideInLeft" data-wow-delay=".5s">
<!-- Supplier -->
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.supplier.errors }}
<label>Supplier:</label>
<div class="container">
{{ form.supplier }}
</div>
</div>
<!-- invoice_number -->
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.invoice_number.errors }}
<input type="text" name="invoice_number" id="id_invoice_number" placeholder="Invoice Number" class="form"/>
</div>
<!-- price -->
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.price.errors }}
<input type="text" name="price" id="id_price" placeholder="Price" class="form"/>
</div>
<!-- sum_me -->
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.sum_me.errors }}
<input type="number" name="sum_me" id="id_sum_me" placeholder="Sum" class="form"/>
</div>
</div><!-- End Left Inputs -->
<!-- Bottom Submit -->
<div class="relative fullwidth col-xs-12">
<!-- Send Button -->
<button type="submit" class="form-btn semibold">Add</button>
</div><!-- End Bottom Submit -->
<!-- Clear -->
<div class="clear"></div>
</form>
</div>
</div>
{{ form.media }}
{% endblock %}
This is traceback I get when I try to search:
[19/Aug/2017 14:29:54] "GET /invoice/autocomplete/?q=frnej HTTP/1.1" 500 16154
[2017-08-19 14:29:54,630] - Broken pipe from ('127.0.0.1', 55490)
Internal Server Error: /invoice/autocomplete/
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/django/core/handlers/exception.py", line 41, in inner
response = get_response(request)
File "/usr/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 187, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/usr/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 185, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python2.7/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/dal/views.py", line 48, in dispatch
return super(ViewMixin, self).dispatch(request, *args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/django/views/generic/base.py", line 88, in dispatch
return handler(request, *args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/django/views/generic/list.py", line 160, in get
self.object_list = self.get_queryset()
File "/Users/miha/Desktop/#application/django/einvoice/invoice/views.py", line 255, in get_queryset
qs = qs.filter(name__istartswith=self.q)
File "/usr/local/lib/python2.7/site-packages/django/db/models/query.py", line 784, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/django/db/models/query.py", line 802, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/usr/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1261, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "/usr/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1287, in _add_q
allow_joins=allow_joins, split_subq=split_subq,
File "/usr/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1212, in build_filter
raise FieldError('Related Field got invalid lookup: {}'.format(lookups[0]))
FieldError: Related Field got invalid lookup: istartswith
Related
ValueError: invalid literal for int() with base 10: 'slug-1-2'
2nd time i am facing this error again. I am trying to allow users to edit their comments in any blog post but it seems that there is a problem with this line:
comment = get_object_or_404(Comment, id=post_id)
This has worked for other functions (eg when i created a function that can delete comments) but not this one. Any idea how I can resolve this? I got a feeling its sth to do with when I add comments in the url I use slug and <post_id> when I edit comments url. But it worked for my delete function and i did use post_id for that function. Thanks
models.py
class Comment(models.Model):
post = models.ForeignKey(BlogPost, related_name='comments', on_delete=models.CASCADE)
name = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='name', on_delete=models.CASCADE)
body = models.TextField()
class BlogPost(models.Model):
title = models.CharField(max_length=50, null=False, blank=False, unique=True)
body = models.TextField(max_length=5000, null=False, blank=False)
slug = models.SlugField(blank=True, unique=True)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
views.py
def edit_own_comment(request, post_id):
context = {}
comment = get_object_or_404(Comment, id=post_id)
if request.method == 'POST':
form = UpdateCommentForm(request.POST, instance=comment)
if comment.name == request.user and form.is_valid():
obj = form.save(commit=False)
obj.save()
messages.success(request, 'Your comment has been edited', extra_tags='editedcomment')
return redirect(reverse("HomeFeed:detail", kwargs={'slug': comment.post.slug }))
form = UpdateCommentForm(
initial = {
"body": comment.body,
}
)
context['form'] = form
return render(request, 'HomeFeed/edit_comment.html', context)
class AddCommentView(LoginRequiredMixin, DetailView, FormView):
login_url = 'must_authenticate'
model = BlogPost
form_class = CommentForm
template_name = 'HomeFeed/add_comment.html'
def form_valid(self, form):
comment = form.save(commit=False)
comment.name = self.request.user
comment.post = self.get_object()
comment.save()
return redirect(reverse("HomeFeed:detail", kwargs={'slug': comment.post.slug }))
def delete_any_comment(request, post_id):
if request.method == 'POST':
comment = get_object_or_404(Comment, id=post_id)
if comment.post.author == request.user:
comment.delete()
return redirect(reverse("HomeFeed:detail", kwargs={'slug': comment.post.slug }))
forms.py
class UpdateCommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ['body']
def save(self, commit=True):
comment = self.instance
comment.body = self.cleaned_data['body']
if commit:
comment.save()
return comment
urls.py
path('comments/<slug>', AddCommentView.as_view(), name= "add_comment"),
path('editowncomments/<post_id>', edit_own_comment, name= "edit_own_comment"),
path('deleteanycomments/<post_id>', delete_any_comment, name= "deleteanycomments"),
html
<form class="create-form" method="POST" enctype="multipart/form-data">{% csrf_token %}
<div class="form-group">
<label for="id_body">Body</label>
<textarea class="form-control" rows="8" type="text" name="body" id="id_body" required>{{form.initial.body}}</textarea>
</div>
<button class="submit-button btn btn-lg btn-primary btn-block" type="submit">Edit Comment</button>
</form>
TraceBack
Internal Server Error: /HomeFeed/editowncomments/slug
Traceback (most recent call last):
File "lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "lib/python3.8/site-packages/django/core/handlers/base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "lib/python3.8/site-packages/django/core/handlers/base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/lib/python3.8/site-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view
return view_func(request, *args, **kwargs)
File "HomeFeed/views.py", line 995, in edit_own_comment
comment = get_object_or_404(Comment, id=post_id)
File "lib/python3.8/site-packages/django/shortcuts.py", line 93, in get_object_or_404
return queryset.get(*args, **kwargs)
File "/lib/python3.8/site-packages/django/db/models/query.py", line 399, in get
clone = self.filter(*args, **kwargs)
File "/lib/python3.8/site-packages/django/db/models/query.py", line 892, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "lib/python3.8/site-packages/django/db/models/query.py", line 910, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1290, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1315, in _add_q
child_clause, needed_inner = self.build_filter(
File "/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1251, in build_filter
condition = self.build_lookup(lookups, col, value)
File "/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1116, in build_lookup
lookup = lookup_class(lhs, rhs)
File "/lib/python3.8/site-packages/django/db/models/lookups.py", line 20, in __init__
self.rhs = self.get_prep_lookup()
File "lib/python3.8/site-packages/django/db/models/lookups.py", line 70, in get_prep_lookup
return self.lhs.output_field.get_prep_value(self.rhs)
File "/lib/python3.8/site-packages/django/db/models/fields/__init__.py", line 972, in get_prep_value
return int(value)
ValueError: invalid literal for int() with base 10: 'slug'
SLDEM's suggestion:
#login_required(login_url=reverse_lazy("must_authenticate"))
def edit_own_comment(request, post_id):
context = {}
comment = get_object_or_404(Comment, id='slug')
if comment.name != request.user:
return HttpResponse('You did not write the comment.')
if request.method == 'POST':
form = UpdateCommentForm(request.POST or None, instance=comment)
if comment.name == request.user and form.is_valid():
obj = form.save(commit=False)
#this prints a success message after it is safe
obj.save()
return redirect(reverse("HomeFeed:detail", kwargs={'slug': comment.post.slug }))
form = UpdateCommentForm(
initial = {
"body": comment.body,
}
)
context['form'] = form
return render(request, 'HomeFeed/edit_comment.html', context)
path('editowncomments/<int:post_id>', edit_own_comment, name= "edit_own_comment"),
html
{% if not blog_post.comments.all %}
<p>No comments yet... Add a comment</p>
{% else %}
Add a comment
<br>
{% for comment in blog_post.comments.all %}
<strong>
{{ comment.name}}
{{ comment.date_added }}
</strong>
{{ comment.body }}
{% if comment.name == request.user and blog_post.author != request.user %}
<form action = "{% url 'HomeFeed:deletecomments' comment.id %}" method = "POST"> {% csrf_token %}
<button class="btn btn-sm btn-danger">Delete</button>
</form>
{% endif %}
{% if blog_post.author == request.user %}
<form action = "{% url 'HomeFeed:deleteanycomments' comment.id %}" method = "POST"> {% csrf_token %}
<button class="btn btn-sm btn-danger">Delete</button>
</form>
{% endif %}
{% if comment.name == request.user %}
<a class="btn btn-sm btn-warning col-lg-4" href="{% url 'HomeFeed:edit_own_comment' comment_id %}">Edit comment</a>
{% endif %}
{% endfor %}
{% endif %}
detail views.py
class DetailBlogPostView(BlogPostMixin,DetailView):
template_name = 'HomeFeed/detail_blog.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
blog_post=self.get_object()
blog_post.save()
context['blog_post'] = blog_post
account = Account.objects.all()
context['account'] = account
#aka if blog post does belong to me
if blog_post.author != self.request.user:
if self.request.user.is_authenticated and \
blog_post.interest_set.filter(user__id=self.request.user.id).exists():
submittedinterest = True
context["interest_pk"]=blog_post.interest_set.first().pk
#if blog post belongs to me
else:
submittedinterest = False
context['submittedinterest'] = submittedinterest
if blog_post.interest_set.exists():
context["interest_pk"]=blog_post.interest_set.first().pk
return context
Well looks like the issue here is with your url, make it like this:
path('edit-own-comments/<int:post_id>', edit_own_comment, name="edit_own_comment"),
(Add the specification that the passed variable is actually an integer) And then use the value of your Comment instance id in your view.
Ok so based on your edits:
Where you have your html to edit the comment:
{% if comment.name == request.user %}
<a class="btn btn-sm btn-warning col-lg-4" href="{% url 'HomeFeed:edit_own_comment' comment.id %}">Edit comment</a> <!-- here change comment_id to comment.id to pass the correct value to the url -->
{% endif %}
In your view where you are getting the comment:
comment = get_object_or_404(Comment, id=post_id) # also rename post_id to something like comment_id here and in the url to make it more readable
And it should work.
# models.py
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from phonenumber_field.modelfields import PhoneNumberField
class UserprofileCity(models.manager):
def get_queryset(self):
return super(UserprofileCity,self).get_queryset().filter(city='surat')
class UserProfile(models.Model):
user= models.OneToOneField(User,on_delete=models.CASCADE)
# you an add extra fields as per requirements after
city = models.CharField(max_length=100,default='')
description = models.CharField(max_length= 500,default='')
phone_number = PhoneNumberField(default='+91',max_length=13,help_text='enter mobile number with country code')
age = models.IntegerField(default=18)
image = models.ImageField(upload_to='profile_image',blank=True)
def __str__(self):
return self.user.username
def create_profile(sender,**kwargs):
if kwargs['created']:
user_profile = UserProfile.objects.create(user=kwargs['instance'])
post_save.connect(create_profile,sender=User)
# views.py:
from django.shortcuts import render,redirect
from django.urls import reverse
from .forms import RegistrationForm,EditProfileForm,ProfileForm
from django.contrib.auth.models import User
from django.contrib.auth.forms import PasswordChangeForm
from django.contrib.auth import update_session_auth_hash
def register(request):
if request.method =='POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
return redirect(reverse('accounts:login'))
else:
form = RegistrationForm()
args = {'form':form}
return render(request,'accounts/reg_form.html',args)
def profile_view(request,pk=None):
if pk:
user = User.objects.get(pk=pk)
else:
user = request.user
args = {'user':user}
return render(request,'accounts/profile.html',args)
def profile_edit(request):
if request.method =='POST':
form = EditProfileForm(request.POST,instance=request.user)
profile_form = ProfileForm(request.Post,request.FILES,instance=request.user.userprofile)
if form.is_valid() and profile_form.is_valid():
user_form = form.save()
custom_form = profile_form.save(False)
custom_form.user = user_form
custom_form.save()
return redirect(reverse('accounts:profile_view'))
else:
form = EditProfileForm(instance=request.user)
profile_form = ProfileForm(instance=request.user.userprofile)
args = {
'form':form, 'profile_form':profile_form
}
return render(request,'accounts/profile_edit.html',args)
def password_change(request):
if request.method=='POST':
form = PasswordChangeForm(data = request.POST,user=request.user)
if form.is_valid():
form.save()
update_session_auth_hash(request,form.user)
return redirect(reverse('accounts:profile_view'))
else:
return redirect(reverse('accounts:change_password'))
else:
form = PasswordChangeForm(user = request.user)
args = {'form':form}
return render(request,'accounts/password_change.html',args)
# urls.py
from django.urls import reverse_lazy
from . import views
from django.urls import path
from django.contrib.auth.views import (
LoginView,
LogoutView,
PasswordResetView,
PasswordResetDoneView,
PasswordResetCompleteView,
PasswordResetConfirmView,
)
app_name = 'accounts'
urlpatterns = [
###
#user
###
path('login/',LoginView.as_view(template_name = 'accounts/login.html'),name='login'),
path('logout/',LogoutView.as_view(template_name='accounts/logout.html'),name = 'logout'),
path('register/',views.register,name='register'),
###
#profile
###
path('profile/',views.profile_view,name='profile_view'),
path('profile/<pk>/',views.profile_view,name='other_profile_view'),
path('profile/edit/',views.profile_edit,name='profile_edit'),
###
#change_password
###
path('change-password/',views.password_change,name='password_change'),
###
# reset password
###
path('reset-password/',PasswordResetView.as_view(
template_name = 'accounts/password_reset.html',
email_template_name = 'accounts/password_reset_email.html',
subject_template_name = 'accounts/password_reset_subject.txt',
success_url = reverse_lazy('accounts:password_reset_done'),
),name='password_reset'),
path('password_reset/done/',PasswordResetDoneView.as_view(
template_name = 'accounts/password_reset_done.html',
),name = 'password_reset_done'),
path('reset/<uidb64>/<token>/',PasswordResetConfirmView.as_view(
success_url = reverse_lazy('accounts:password_reset_complete'),
template_name = 'accounts/password_reset_confirm.html',
),name='password_reset_confirm'),
path('reset/done/',PasswordResetCompleteView.as_view(
template_name = 'accounts/password_reset_complete.html',
),name='password_reset_complete'),
# profile.html
{% extends 'base.html' %}
{% load static %}
{% block title %}
Profile
{% endblock %}
{% block body %}
<div class="jumbotron">
<div class="col-md-8">
<h1>{{user}} Profile</h1>
<hr>
<p> Username : {{user}} </p>
<p> First Name : {{user.first_name}} </p>
<p> Last Name : {{user.last_name}} </p>
<p> Age : {{ user.userprofile.age }} </p>
<p> Email : {{ user.email}} </p>
<p> Description : {{ user.userprofile.description }} </p>
<p> Phone : {{ user.userprofile.phone_number }}</p>
<p> city : {{ user.userprofile.city }} </p>
<p> Website : {{ user.userprofile.website }} </p>
</div>
<div class="col-md-4">
{% if user.userprofile.image %}
<img src="{{ user.userprofile.image.url }}" width="400"><br>
{% endif %}
<br>
<div class="col-md-6">
<a class="btn btn-info" href="{% url 'accounts:profile_edit' %}">Edit Profile</a>
</div>
<div class="col-md-6">
<a class="btn btn-info" href="{% url 'accounts:password_change' %}">Change Password</a>
</div>
</div>
</div>
{% endblock %}
When I run with these files, I get this error:
traceback:
The above exception (invalid literal for int() with base 10: 'edit') was the direct cause of the following exception:
File "D:\python\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "D:\python\lib\site-packages\django\core\handlers\base.py", line 179, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Kraj\Desktop\practice\demo4\post\accounts\views.py", line 25, in profile_view
user = User.objects.get(pk=pk)
File "D:\python\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "D:\python\lib\site-packages\django\db\models\query.py", line 418, in get
clone = self._chain() if self.query.combinator else self.filter(*args, **kwargs)
File "D:\python\lib\site-packages\django\db\models\query.py", line 942, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "D:\python\lib\site-packages\django\db\models\query.py", line 962, in _filter_or_exclude
clone._filter_or_exclude_inplace(negate, *args, **kwargs)
File "D:\python\lib\site-packages\django\db\models\query.py", line 969, in _filter_or_exclude_inplace
self._query.add_q(Q(*args, **kwargs))
File "D:\python\lib\site-packages\django\db\models\sql\query.py", line 1358, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "D:\python\lib\site-packages\django\db\models\sql\query.py", line 1377, in _add_q
child_clause, needed_inner = self.build_filter(
File "D:\python\lib\site-packages\django\db\models\sql\query.py", line 1319, in build_filter
condition = self.build_lookup(lookups, col, value)
File "D:\python\lib\site-packages\django\db\models\sql\query.py", line 1165, in build_lookup
lookup = lookup_class(lhs, rhs)
File "D:\python\lib\site-packages\django\db\models\lookups.py", line 24, in __init__
self.rhs = self.get_prep_lookup()
File "D:\python\lib\site-packages\django\db\models\lookups.py", line 74, in get_prep_lookup
return self.lhs.output_field.get_prep_value(self.rhs)
File "D:\python\lib\site-packages\django\db\models\fields\__init__.py", line 1776, in get_prep_value
raise e.__class__(
Exception Type: ValueError at /accounts/profile/edit/
Exception Value: Field 'id' expected a number but got 'edit'.
Screenshot here
There is a typo, POST method should be in caps in the edit profile function. Fixing it over here.
def profile_edit(request):
if request.method =='POST':
form = EditProfileForm(request.POST,instance=request.user)
profile_form = ProfileForm(request.POST,request.FILES,instance=request.user.userprofile)
if form.is_valid() and profile_form.is_valid():
user_form = form.save()
custom_form = profile_form.save(False)
custom_form.user = user_form
custom_form.save()
return redirect(reverse('accounts:profile_view'))
else:
form = EditProfileForm(instance=request.user)
profile_form = ProfileForm(instance=request.user.userprofile)
args = {
'form':form, 'profile_form':profile_form
}
return render(request,'accounts/profile_edit.html',args)
''i want to add functionality to my Publish button in HTML. i have made a method under my Post(model) and made a view for that button with a url. i dont know why my button fuctn is not working.
''
My Post Model
class Post(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
description = models.TextField()
created_on = models.DateTimeField(default=timezone.now)
published = models.BooleanField(default=False)
def publish(self):
self.published=True
self.save()
def __str__(self):
return self.title
My Views.py
#login_required
def publish_button(request,pk):
post = get_object_or_404(Post,pk)
post.publish()
return redirect('blog_detail',pk=post.pk)
my urls.py
urlpatterns = [
path('comment/<int:pk>/', comment_post, name='comment_form'),
path('publish/',PublicList.as_view(),name='publish'),
path('publish/<int:pk>/',publish_button,name='p_button'),
path('', index, name='indexpage'),
]
My html
{% extends 'base.html' %}
{% block content %}
<div class="container">
<h1>Blog Details:</h1>
<hr>
<div class="jumbotron">
<h3 align = 'center'>{{ detail.title }}</h3>
<hr>
<div class="mb-5">
<h4>{{ detail.description }}</h4>
</div>
<p>Posted By: {{ detail.user }}<span class="ml-5">{{ detail.created_on }} </span><br>
</div>
{{ detail.pk }}
Publish
<p></p>
<h6>Wanna add comment? <span class="ml-3">
<a href="{% url 'comment_form' pk=detail.pk %}">
<input class="btn btn-dark" type="button" name="" value="Comment">
</a></span>
</h6>
<hr>
<h4>Comments:-</h4>
<hr>
{% for comment in detail.comments.all %}
<h5>{{comment.text}}</h5>
<p>by: #{{comment.author}}<span class='ml-5'>{{comment.commented_on}} </span></p>
<hr>
{% endfor %}
</div>
{% endblock %}
TraceBack:
File "C:\Users\AngryBuLLz\AppData\Local\conda\conda\envs\madeenv \lib\site-packages\django\core\handlers\exception.py" in inner
34. response = get_response(request)
File "C:\Users\AngryBuLLz\AppData\Local\conda\conda\envs\madeenv\lib\site-packages\django\core\handlers\base.py" in _get_response
126. response = self.process_exception_by_middleware(e, request)
File "C:\Users\AngryBuLLz\AppData\Local\conda\conda\envs\madeenv\lib\site-packages\django\core\handlers\base.py" in _get_response
124. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\AngryBuLLz\AppData\Local\conda\conda\envs\madeenv\lib\site-packages\django\contrib\auth\decorators.py" in _wrapped_view
21. return view_func(request, *args, **kwargs)
File "C:\Users\AngryBuLLz\Desktop\Django\prac_18\firstapp\views.py" in publish_button
71. post = get_object_or_404(Post,pk)
File "C:\Users\AngryBuLLz\AppData\Local\conda\conda\envs\madeenv\lib\site-packages\django\shortcuts.py" in get_object_or_404
93. return queryset.get(*args, **kwargs)
File "C:\Users\AngryBuLLz\AppData\Local\conda\conda\envs\madeenv\lib\site-packages\django\db\models\query.py" in get
390. clone = self.filter(*args, **kwargs)
File "C:\Users\AngryBuLLz\AppData\Local\conda\conda\envs\madeenv\lib\site-packages\django\db\models\query.py" in filter
844. return self._filter_or_exclude(False, *args, **kwargs)
File "C:\Users\AngryBuLLz\AppData\Local\conda\conda\envs\madeenv\lib\site-packages\django\db\models\query.py" in _filter_or_exclude
862. clone.query.add_q(Q(*args, **kwargs))
File "C:\Users\AngryBuLLz\AppData\Local\conda\conda\envs\madeenv\lib\site-packages\django\db\models\sql\query.py" in add_q
1263. clause, _ = self._add_q(q_object, self.used_aliases)
File "C:\Users\AngryBuLLz\AppData\Local\conda\conda\envs\madeenv\lib\site-packages\django\db\models\sql\query.py" in _add_q
1287. split_subq=split_subq,
File "C:\Users\AngryBuLLz\AppData\Local\conda\conda\envs\madeenv\lib\site-packages\django\db\models\sql\query.py" in build_filter
1161. arg, value = filter_expr
Exception Type: TypeError at /publish/5/
Exception Value: cannot unpack non-iterable int object
get_object_or_404 takes a filter expression, exactly as if you were calling Products.objects.get()`. So it should be:
post = get_object_or_404(Post, pk=pk)
ManagementForm data missing error while formset validation
I get this error when I try to save a parent form with intermediate m2m table child formset. I don't know how to solve because the lack of information about this error in Traceback. Please help!
models.py
class Material(models.Model):
name = models.CharField(max_length=200)
familiy = models.ForeignKey(Material_family, on_delete=models.CASCADE, null=True)
…
class Purchase(models.Model):
number = models.IntegerField()
date = models.DateField()
…
class Purchase_detail(models.Model):
material = models.ForeignKey(Material, on_delete=models.CASCADE)
purchase = models.ForeignKey(Purchase, on_delete=models.CASCADE)
quantity = models.IntegerField()
unit_value = models.IntegerField(default=0)
forms.py
class PurchaseModelForm(forms.ModelForm):
class Meta:
model = Purchase
fields = (‘number’,’date’ , ’…’)
def __init__(self, *args, **kwargs):
super(PurchaseModelForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_tag = False
self.helper.form_id = 'id-purchase-form'
self.helper.form_method = 'post'
class Purchase_detailModelForm(forms.ModelForm):
class Meta:
model = Purchase_detail
fields = ('material','quantity','unit_value')
def __init__(self, *args, **kwargs):
super(Purchase_detailModelForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_tag = False
self.helper.form_id = 'id-purchase-form'
self.helper.form_method = 'post'
self.helper.form_class = 'form-inline'
self.helper.field_template = 'bootstrap3/layout/inline_field.html'
DetailFormSet = forms.inlineformset_factory(Purchase, Purchase_detail, form=Purchase_detailModelForm, extra=1)
views.py
def purchase_new(request, purchase_id=None, *args, **kwargs):
template = 'erp/purchase_form.html'
if purchase_id:
inst = Purchase.objects.get(pk=purchase_id)
else:
inst = Purchase()
if request.method == 'POST':
form = PurchaseModelForm(request.POST or None, request.FILES, prefix='purchase', instance=inst)
formset = DetailFormSet(request.POST or None, request.FILES, prefix='detail')
form_valid = form.is_valid()
if form_valid:
purchase = form.save()
formset.save(commit=False)
for f in formset:
f.compra = purchase
f.save()
return redirect('...')
else:
form = PurchaseModelForm(prefix='purchase',instance=inst)
formset = DetailFormSet(prefix='purchase')
context = { 'form': form, 'formset': formset }
return render(request, template, context )
This is the template
<form method='POST' action="">
{% csrf_token %}
<div>
<h5 style="font-weight: bold;">Datos de la Compra</h5>
{% crispy form form.helper %}<hr/>
<h5 style="font-weight: bold;">Detalle de la Compra <a class="btn btn-rounded btn-sm btn-icon btn-default add-new-form"><i class="fa fa-plus text-success"></i></a></h5>
</div>
{{ formset.management_form|crispy }}
{% for x in formset %}
<div class="form-inline">
{{ x|crispy }}
<hr>
</div>
{% endfor %}
<div class="form-inline" id="empty-row">
{{ formset.empty_form|crispy }}
<hr>
</div>
<button class="btn btn-block btn-primary" >Guardar</button>
</form>
And the traceback is :
Traceback:
File "/Users/jlattus/Dev/italuzbi/lib/python3.5/site-packages/django/core/handlers/exception.py" in inner
41. response = get_response(request)
File "/Users/jlattus/Dev/italuzbi/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
187. response = self.process_exception_by_middleware(e, request)
File "/Users/jlattus/Dev/italuzbi/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
185. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/jlattus/Dev/italuzbi/lib/python3.5/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
23. return view_func(request, *args, **kwargs)
File "/Users/jlattus/Dev/italuzbi/src/erp/views.py" in purchase_new
415. formset.save(commit=False)
File "/Users/jlattus/Dev/italuzbi/lib/python3.5/site-packages/django/forms/models.py" in save
666. return self.save_existing_objects(commit) + self.save_new_objects(commit)
File "/Users/jlattus/Dev/italuzbi/lib/python3.5/site-packages/django/forms/models.py" in save_existing_objects
768. if not self.initial_forms:
File "/Users/jlattus/Dev/italuzbi/lib/python3.5/site-packages/django/forms/formsets.py" in initial_forms
189. return self.forms[:self.initial_form_count()]
File "/Users/jlattus/Dev/italuzbi/lib/python3.5/site-packages/django/utils/functional.py" in get
35. res = instance.dict[self.name] = self.func(instance)
File "/Users/jlattus/Dev/italuzbi/lib/python3.5/site-packages/django/forms/formsets.py" in forms
144. for i in range(self.total_form_count())]
File "/Users/jlattus/Dev/italuzbi/lib/python3.5/site-packages/django/forms/formsets.py" in total_form_count
116. return min(self.management_form.cleaned_data[TOTAL_FORM_COUNT], self.absolute_max)
File "/Users/jlattus/Dev/italuzbi/lib/python3.5/site-packages/django/utils/functional.py" in get
35. res = instance.dict[self.name] = self.func(instance)
File "/Users/jlattus/Dev/italuzbi/lib/python3.5/site-packages/django/forms/formsets.py" in management_form
98. code='missing_management_form',
Exception Type: ValidationError at /compra/new/
Exception Value: ['Los datos de ManagementForm faltan o han sido manipulados
I have a Django ModelForm that isn't displaying field errors properly in the template. I have several fields that are required, and what I believe to be the correct logic to capture and display the errors to the user.
When submitting the form, I get the following error:
Traceback (most recent call last):
File "/home/thevariable/.virtualenvs/va_jobs/lib/python2.7/site-packages/django/core/handlers/base.py", line 114, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/thevariable/.virtualenvs/va_jobs/lib/python2.7/site-packages/django/views/generic/base.py", line 69, in view
return self.dispatch(request, *args, **kwargs)
File "/home/thevariable/webapps/va_jobs/va_jobs/jobs/views.py", line 29, in dispatch
return super(ApplicationCreateView, self).dispatch(*args, **kwargs)
File "/home/thevariable/.virtualenvs/va_jobs/lib/python2.7/site-packages/django/views/generic/base.py", line 87, in dispatch
return handler(request, *args, **kwargs)
File "/home/thevariable/.virtualenvs/va_jobs/lib/python2.7/site-packages/django/views/generic/edit.py", line 205, in post
return super(BaseCreateView, self).post(request, *args, **kwargs)
File "/home/thevariable/.virtualenvs/va_jobs/lib/python2.7/site-packages/django/views/generic/edit.py", line 170, in post
if form.is_valid():
File "/home/thevariable/.virtualenvs/va_jobs/lib/python2.7/site-packages/django/forms/forms.py", line 129, in is_valid
return self.is_bound and not bool(self.errors)
File "/home/thevariable/.virtualenvs/va_jobs/lib/python2.7/site-packages/django/forms/forms.py", line 121, in errors
self.full_clean()
File "/home/thevariable/.virtualenvs/va_jobs/lib/python2.7/site-packages/django/forms/forms.py", line 274, in full_clean
self._clean_form()
File "/home/thevariable/.virtualenvs/va_jobs/lib/python2.7/site-packages/django/forms/forms.py", line 300, in _clean_form
self.cleaned_data = self.clean()
File "/home/thevariable/webapps/va_jobs/va_jobs/jobs/forms.py", line 23, in clean
resume_ext = resume.name.lower().split('.')[1]
AttributeError: 'NoneType' object has no attribute 'name'
Here is my forms.py:
from django.forms import ModelForm
from .models import Application
class ApplicationForm(ModelForm):
class Meta:
model = Application
fields = [
'first_name',
'last_name',
'email_address',
'phone_number',
'salary_requirement',
'resume',
'portfolio_url',
'description',
'can_relocate',
'start_date',
]
def __init__(self, *args, **kwargs):
super(ApplicationForm, self).__init__(*args, **kwargs)
self.fields['first_name'].required = True
self.fields['last_name'].required = True
self.fields['email_address'].required = True
self.fields['phone_number'].required = True
self.fields['salary_requirement'].required = False
self.fields['resume'].required = True
self.fields['portfolio_url'].required = False
self.fields['description'].required = False
self.fields['can_relocate'].required = True
self.fields['start_date'].required = False
def clean(self):
cleaned_data = super(ApplicationForm, self).clean()
resume = cleaned_data.get('resume')
resume_ext = resume.name.lower().split('.')[1]
if not resume_ext in ('pdf', 'doc', 'docx'):
del cleaned_data["resume"]
msg = u"Your file must be a PDF or DOC file type."
raise forms.ValidationError(msg)
#self._errors["resume"] = self.error_class([msg])
return cleaned_data
Here is my view:
class ApplicationCreateView(CreateView):
model = Application
form_class = ApplicationForm
success_url = 'submitted/'
def dispatch(self, *args, **kwargs):
self.job = get_object_or_404(Job, slug=kwargs['slug'])
return super(ApplicationCreateView, self).dispatch(*args, **kwargs)
def form_valid(self, form):
#Get associated job and save
self.object = form.save(commit=False)
self.object.job = self.job
self.object.save()
# Gather cleaned data for email send
first_name = form.cleaned_data.get('first_name')
last_name = form.cleaned_data.get('last_name')
email_address = form.cleaned_data.get('email_address')
phone_number = form.cleaned_data.get('phone_number')
salary_requirement = form.cleaned_data.get('salary_requirement')
description = form.cleaned_data.get('description')
portfolio_url = form.cleaned_data.get('portfolio_url')
can_relocate = form.cleaned_data.get('can_relocate')
start_date = form.cleaned_data.get('start_date')
resume = self.object.resume
job = self.object.job
#Compose message
email = EmailMessage()
email.body = 'Name: ' + first_name + last_name + '\n' + 'Email: ' + email_address + '\n' + 'Phone number: ' + str(phone_number) + '\n' + 'Salary requirement: ' + str(salary_requirement) + '\n' + 'Description: ' + description + '\n' + 'Portfolio URL: ' + portfolio_url + '\n' + 'Can relocate: ' + str(can_relocate) + '\n' + 'Start date: ' + str(start_date)
email.subject = 'A new application has been submitted for %s' % (job)
email.from_email = 'noreply#abc.com'
email.to = ['jobs#abc.com',]
email.bcc = ['abc#abc.com',]
email.attach(resume.name, resume.read())
email.send()
return HttpResponseRedirect(self.get_success_url())
def get_context_data(self, *args, **kwargs):
context_data = super(ApplicationCreateView, self).get_context_data(*args, **kwargs)
context_data.update({'job': self.job})
return context_data
And here is my template (using Django widget tweaks https://pypi.python.org/pypi/django-widget-tweaks):
<p><em>Note: Fields with an asterisk are required.</em></p>
<form role="form" action="" enctype="multipart/form-data" method="post">
{% csrf_token %}
{% for field in form.visible_fields %}
<div class="form-group">
{% if field.errors %}
<ul class="list-unstyled list-inline">
{% for error in field.errors %}
<li class="text-warning"><span class="glyphicon glyphicon-warning-sign"></span> {{ error|escape }}</li>
{% endfor %}
</ul>
{% endif %}
{{ field.label_tag }}
{% if field.name == "portfolio_url" %}
{% if job.portfolio_required %} <small><span class="glyphicon glyphicon-asterisk"></span></small>
{% endif %}
{% endif %}
{% if field.field.required %} <small><span class="glyphicon glyphicon-asterisk"></span></small>{% endif %}
{% if field.name == "resume" or field.name == "can_relocate" %}
{{ field|add_class:"form-control short" }}
{% elif field.name == "start_date" %}
<input id="id_start_date" class="form-control short" name="start_date" type="date" /><input id="initial-id_start_date" name="initial-start_date" type="hidden" />
{% elif field.name == "portfolio_url" %}
{% if job.portfolio_required %}
<input class="form-control" id="id_portfolio_url" maxlength="200" name="portfolio_url" type="url" required />
{% endif %}
{% else %}
{{ field|add_class:"form-control" }}
{% endif %}
{% if field.help_text %}<p class="help-block">{{ field.help_text }}</p>{% endif %}
</div>
{% endfor %}
<input type="submit" class="btn btn-default" value="Apply">
</form>
For the record, my solution was as follows (in forms.py):
def clean(self):
cleaned_data = super(ApplicationForm, self).clean()
if cleaned_data.get('resume'):
resume = cleaned_data.get('resume')
resume_ext = resume.name.lower().split('.')[1]
if not resume_ext in ('pdf', 'doc', 'docx'):
del cleaned_data["resume"]
msg = u"Your file must be a PDF or DOC file type."
self._errors["resume"] = self.error_class([msg])
return cleaned_data
else:
return cleaned_data
This was inspired by a comment on the original question (Django ModelForm not showing field errors).
All simple, in stack-trace says: "Object resume have no attribute name"
resume = cleaned_data.get('resume')
Maybe resume not in cleaned data ?
try to print it, or put pudb there.
Here is Exception, cuz he is None:
resume_ext = resume.name.lower().split('.')[1]