Django CreateView: 'str' object is not callable - django

I'm trying to use django's CreateView, but I get the following error:
File "/Users/PycharmProjects/gusta/venv/lib/python3.8/site-packages/django/views/generic/edit.py", line 33, in get_form
return form_class(**self.get_form_kwargs())
TypeError: 'str' object is not callable
views.py:
from django.views.generic import ListView, CreateView, DeleteView, DetailView, UpdateView
from .models import Employee, Event, detailEvent, Department, Poste
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse, reverse_lazy
# ----------------------------------------------------- Views for postes.
class PostelistView(LoginRequiredMixin, ListView):
template_name = "postes/post_list.html"
context_object_name = "Poste"
def get_queryset(self):
# initial queryset of leads for the entire organisation
queryset = Poste.objects.all()
return queryset
class PosteCreateView(LoginRequiredMixin, CreateView):
template_name = "postes/post_create.html"
form_class = "Poste"
def get_success_url(self):
return reverse_lazy("employee:post_list")
def form_valid(self, form):
instance = form.save(commit=False)
instance.save()
self.Poste = instance
return super(PosteCreateView, self).form_valid(form)
my models.py
from django.utils.translation import ugettext_lazy as _
class Poste(models.Model):
intitule = models.TextField(_("Name"), max_length=250, default='')
Why is this happening?

In PosteCreateView, you set
form_class = "Poste"
This isn't a class, its a string. Django expects it to be a class and will later try to instantiate an object. You can see this in the error message, which gives you the line where the exception occurs:
return form_class(**self.get_form_kwargs())
To solve it, set form_class to the actual class:
form_class = Poste

Related

Django DetailView get one record from QuerySet

Please help me get one record from QuerySet object.
views.py:
from django.contrib.postgres.aggregates import ArrayAgg
from django.http import JsonResponse,
from django.views.generic.list import ListView
from django.views.generic.detail import DetailView
from movies.models import Book
class BooksMixin(ListView):
model = Book
http_method_names = ['get']
def get_queryset(self):
books = Book.objects.values().annotate(authors=ArrayAgg('authors__name',distinct=True)
return books
def render_to_response(self, context, **response_kwargs):
return JsonResponse(context)
class BooksDetail(BooksMixin, DetailView):
def get_context_data(self, *, object_list=None, **kwargs):
queryset = self.get_queryset()
context = queryset.get(id=self.kwargs['pk'])
return context
urls.py:
from django.urls import path
from books import views
urlpatterns = [
path('books/<uuid:pk>/', views.BooksDetail.as_view()),
]
This works, but I want to get one record from the queryset inside the BooksDetail class more elegantly, without using the kwargs['pk'] filter. I tried to use construct like
class BooksDetail(BooksMixin, DetailView):
def get_context_data(self, *, object_list=None, **kwargs):
queryset = self.get_queryset()
context = super(BooksDetail, self).get_context_data(**kwargs)
context['bla'] = queryset
return context
but got the error:
'BooksDetail' object has no attribute 'object'

Django rest serializer can't handle object - TypeError: Object of type Hero is not JSON serializable

I have the below simple rest api set up in Django. Calling the url http://127.0.0.1:8000/listheros/ returns
TypeError: Object of type Hero is not JSON serializable
for a reason I can't seem to figure out.
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializers import HeroSerializer
from .models import Hero
class ListHeros(APIView):
def get(self, request, format=None):
"""
Return a list of all users.
"""
queryset = Hero.objects.all().order_by('name')
serializer_class = HeroSerializer
print('get')
return Response(queryset)
# urls.py
from django.urls import include, path
from applications.api.views import ListHeros
urlpatterns = [
path('listheros/', ListHeros.as_view()),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
# serializers.py
from rest_framework import serializers
from .models import Hero
class HeroSerializer(serializers.ModelSerializer):
class Meta:
model = Hero
fields = ('name', 'alias')
# models.py
from django.db import models
class Hero(models.Model):
name = models.CharField(max_length=60)
alias = models.CharField(max_length=60)
def __str__(self):
return self.name
You don't serialize your queryset of heroes. Your ListHeroes api view should looks like below:
class ListHeros(APIView):
def get(self, request, format=None):
"""
Return a list of all users.
"""
queryset = Hero.objects.all().order_by('name')
serializer = HeroSerializer(queryset, many=True)
return Response(serializer.data)
You can also use generics ListApiView instead of APIView:
from rest_framework.generics import ListAPIView
class ListHeros(ListAPIView):
queryset = Hero.objects.all().order_by('name')
serializer_class = HeroSerializer

Method Not Allowed (POST): /cbvdelete/5/ Method Not Allowed: /cbvdelete/5/

i am not able to run this code
viwes.py
from django.shortcuts import render, redirect
from django.urls import reverse_lazy, reverse
from . models import Task
from . forms import Taskform
from django.views.generic import ListView
from django.views.generic.detail import DetailView
from django.views.generic.edit import UpdateView,DeleteView
class Tasklistview(ListView):
model = Task
template_name = 'home.html'
context_object_name = 'task'
class Detailview(DetailView):
model=Task
template_name = "details.html"
context_object_name = 'task'
class Updateview(UpdateView):
model = Task
template_name = "update.html"
context_object_name = "task"
fields = ('name', 'priority', 'date')
def get_success_url(self):
return reverse_lazy('todoapp:cbvdetail',kwargs={'pk':self.object.id})
class Deleteview(DetailView):
model = Task
template_name = 'delete.html'
success_url = reverse_lazy('todoapp:home')
urls.py
from django.urls import path
from . import views
app_name='todoapp'
urlpatterns = [
path('',views.home,name='home'),
path('delete/<int:id>/',views.delete,name='delete'),
path('edit/<int:id>/',views.update,name='update'),
path('cbvhome/',views.Tasklistview.as_view(),name='home'),
path('cbvdetail/<int:pk>/',views.Detailview.as_view(),name='cbvdetail'),
path('cbvupdate/<int:pk>/',views.Updateview.as_view(),name='edit'),
]
when i run this code i am getting a error this page isn't working right now
i am not able to run this code
gngnitgbnugriujvnnvtvnviuvntnvtvitu
You are inheriting you Deleteview from a DetailView, not a DeleteView, hence the error:
from django.views.generic import DeleteView
class Deleteview(DeleteView):
model = Task
template_name = 'delete.html'
success_url = reverse_lazy('todoapp:home')
I would however strongly advise not to give your views names like Deleteview, since it is easy to confuse this with the Django builtin class-based views. Usually the model is specified in the name, so TaskDeleteView instead of Deleteview:
class TaskDeleteView(DeleteView):
model = Task
template_name = 'delete.html'
success_url = reverse_lazy('todoapp:home')

Django type error: excepted string or byte types like object?

When I tried to publish blog an exception occurs "excepted string or bytes type object".I tried a lot but
I don't know how to fix this .
What I understand is that it is occuring because DateTimeField(default=timezone.now). I'm correct?
This is the error I m getting on writing py manage.py runserver:
File "C:\anaconda\envs\virblogEnv\lib\site-packages\django\db\models\fields\__init__.py", line 1318, in to_python
parsed = parse_datetime(value)
File "C:\anaconda\envs\virblogEnv\lib\site-packages\django\utils\dateparse.py", line 107, in parse_datetime
match = datetime_re.match(value)
TypeError: expected string or bytes-like object
[] "GET / HTTP/1.1" 500 139276
Not Found: /favicon.ico
[] "GET /favicon.ico HTTP/1.1" 404 4283
Here is models.py:-
from django.db import models
from django.utils import timezone
from django.urls import reverse
class Post(models.Model):
author=models.ForeignKey('auth.User',on_delete=models.CASCADE)
title=models.CharField(max_length=200)
text=models.TextField()
created_date=models.DateTimeField(default=timezone.now)
published_date=models.DateTimeField(blank=True,null=True)
def publish(self):
self.published_date=timezone.now
self.save()
def approve_comments(self):
return self.comments.filter(approve_comments=True)
def get_absolute_url(self):
return reverse('post_detail',kwargs={'pk':self.pk})
def __str__(self):
return self.title
class Comment(models.Model):
post=models.ForeignKey('blog.Post',related_name='comments',on_delete=models.CASCADE)
author=models.CharField(max_length=200)
text=models.TextField()
created_date=models.DateTimeField(default=timezone.now)
approve_comment=models.BooleanField(default=False)
def approve(self):
self.approved_comment=True
self.save()
def get_absolute_url(self):
return reverse('post_list')
def __str__(self):
return self.text
Here is views.py:-
from django.shortcuts import render,get_object_or_404,redirect
from django.utils import timezone
from blog.forms import PostForm,CommentForm
from blog.models import Post,Comment
from django.urls import reverse_lazy
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import (TemplateView,ListView,DetailView,
CreateView,UpdateView,DeleteView)
class AboutView(TemplateView):
template_name='about.html'
class PostListView(ListView):
model=Post
#generating a query to db (so this means that grab all object filtered by published
# by date in order of decending)
def get_queryset(self):
return Post.objects.filter(published_date__lte=timezone.now).order_by('-published_date')
class PostDetailView(DetailView):
model=Post
class CreatePostView(LoginRequiredMixin,CreateView):
login_url='/login/'
redirect_field_name='blog/post_detail.html'
form_class=PostForm
model=Post
class PostUpdateView(LoginRequiredMixin,UpdateView):
login_url='/login/'
redirect_field_name='blog/post_detail.html'
form_class=PostForm
model=Post
class PostDeleteView(LoginRequiredMixin,DeleteView):
model=Post
success_url= reverse_lazy('post_list')
class DraftListView(LoginRequiredMixin,ListView):
login_url='/login/'
redirect_field_name='blog/post_list.html'
model='Post'
def get_queryset(self):
return Post.objects.filter(published_date__isnull=True).order_by('created_date')
#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 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/comment_form.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)
Please help me!!
As #unknown suggested, you should change timezone.now -> timezone.now() where is expects value instead of callable.
models.py
class Post(models.Model):
def publish(self):
self.published_date = timezone.now()
self.save()
views.py
class PostListView(ListView):
def get_queryset(self):
return Post.objects.filter(published_date__lte=timezone.now()).order_by('-published_date')
Notice that the other timezone.now should be left unchanged, because the model field default expects callable object.

How can I set success_mesasge with format() in django generic view?

What I want to implement is like this :
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.messages.views import SuccessMessageMixin
from django.views.generic import CreateView
from posts.models import Post
class PostNewView(LoginRequiredMixin, SuccessMessageMixin, CreateView):
model = Post
fields = ['title', 'content', 'image']
success_message = "{} has been created successfully".format(self.post.title)
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
But it occurs error. Any ideas?
This isn't an issue with format(), but with trying to reference an attribute that doesn't exist at that point. Attributes at class level are evaluated at import time, but self.title only exists at runtime, and only within a method.
Rather than setting the message at that level, you should use the get_success_message method:
def get_success_message(self, cleaned_data):
return "{} has been created successfully".format(cleaned_data['title'])