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'
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
My code is:
views.py
class supplierListView(LoginRequiredMixin, ListView):
template_name = "supplier/Supplier_list.html"
def get_queryset(self):
organisation = self.request.user.userprofile.company
return Supplier.objects.filter(organisation=organisation)
class supplierCreateView(LoginRequiredMixin, CreateView):
template_name = "supplier/supplier_create.html"
form_class = SupplierModelForm
def get_success_url(self):
return reverse("supplier:supplier_list")
def form_valid(self, form):
supplier = form.save(commit=False)
supplier.organisation = self.request.user.userprofile.company
supplier.supplier_created_by = self.request.user
supplier.save()
my urls:
from awesomeinventory.supplier.views import (
supplierListView,
supplierDetailView,
supplierCreateView,
supplierContactListView,
supplierContactCreateView,
supplierContactDetailView,
)
app_name = "supplier"
urlpatterns = [
path("supplier_list/", view=supplierListView.as_view(), name="supplier_list"),
path("supplier_create/", view=supplierCreateView.as_view(), name="supplier_create"),
path("<int:pk>/detail/", view=supplierDetailView.as_view(), name="supplier_detail"),
path("<int:pk>/update/", view=supplierDetailView.as_view(), name="supplier_update"),
path("<int:pk>/delete/", view=supplierDetailView.as_view(), name="supplier_delete"),
path("supplierContact_list/", view=supplierContactListView.as_view(), name="supplierContact_list"),
path("<int:suppk>/supplierContact_create/", view=supplierContactCreateView.as_view(), name="supplierContact_create"), # int is supplier_id
path("<int:pk>/Contact/detail/", view=supplierContactDetailView.as_view(), name="supplierContact_detail"),
]
I m able to go to supplier:supplier_list page and it works well.
But when I want to create a supplier with supplierCreateView, supplier is create but it seems to have an issue with get_success_url as I have error
The view awesomeinventory.supplier.views.supplierCreateView didn't return an HttpResponse object. It returned None instead
The method form_valid is supposed to return the response or redirect the user. In your implementation you only save the object and return nothing essentially returning None which gives you an error. Instead of using form.save(commit=False) you can simply modify the instance wrapped by the form and leave all the processing to the super classes form_valid:
class supplierCreateView(LoginRequiredMixin, CreateView):
template_name = "supplier/supplier_create.html"
form_class = SupplierModelForm
def get_success_url(self):
return reverse("supplier:supplier_list")
def form_valid(self, form):
form.instance.organisation = self.request.user.userprofile.company
form.instance.supplier_created_by = self.request.user
return super().form_valid(form)
Note: A class name should ideally be in PascalCase so SupplierCreateView instead of supplierCreateView
This will work for you.
from django.urls import reverse_lazy
class supplierCreateView(LoginRequiredMixin, CreateView):
template_name = "supplier/supplier_create.html"
form_class = SupplierModelForm
def get_success_url(self):
# pay attention I'm using reverse_lazy instead of reverse
return reverse_lazy("supplier:supplier_list")
You can read more about reverse_lazy here.
I have an django app,But i want to make its API so just i created it
after runing the server
Page not found (404)
But my django app is running,After the running the url of API i got the error of Page not found
List/views.py
from django.http import Http404
from django.shortcuts import render
from django.views.generic import ListView,DetailView
from .models import List
from django.http import HttpResponse,JsonResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from List.serializers import ListSerializers
class MainListView(ListView):
queryset = List.objects.all()
# temp = List.objects.all()
template_name = "main_list.html"
def get_context_data(self, *args, **kwargs):
context = super(MainListView, self).get_context_data(*args, **kwargs)
context['temp'] = List.objects.all()
return context
class MainListView(ListView):
queryset = List.objects.all()
# temp = List.objects.all()
template_name = "List/list.html"
def get_context_data(self, *args, **kwargs):
context = super(MainListView, self).get_context_data(*args, **kwargs)
context['temp'] = List.objects.all()
return context
class MainDetailSlugView(DetailView):
queryset = List.objects.all()
template_name = "news/detail.html"
#csrf_exempt
def head_list(request):
if request.method == 'GET':
queryset = List.objects.all()
serializer = ListSerializer(queryset, many=True)
return JsonResponse(serializer.data, safe=False)
elif request.method == 'POST':
data = JSONParser().parse(request)
serializer = ListSerializer(data=data)
if serializer.is_valid():
serializer.save()
return JsonResponse(serializer.data, status=201)
return JsonResponse(serializer.errors, status=400)
#csrf_exempt
def head_detail(request, pk):
try:
head = List.objects.get(pk=pk)
except List.DoesNotExist:
return HttpResponse(status=404)
if request.method == 'GET':
serializer = ListSerializer(list)
return JsonResponse(serializer.data)
elif request.method == 'PUT':
data = JSONParser().parse(request)
serializer = SnippetSerializer(head, data=data)
if serializer.is_valid():
serializer.save()
return JsonResponse(serializer.data)
return JsonResponse(serializer.errors, status=400)
elif request.method == 'DELETE':
head.delete()
return HttpResponse(status=204)
List/urls.py
from django.urls import path
from List import views
from .views import(
# ListlistView,
MainListView,
MainDetailSlugView,
head_list,
head_detail
)
urlpatterns = [
# url(r'^$',ListlistView.as_view()),
path('',MainListView.as_view(),name='list'),
path('(<pk>\d+)(?:/(<slug>[\w\d-]+))',MainDetailSlugView.as_view(), name='List'),
path('list/',views.list_list),
path('lists/<int:pk>/',views.list_detail),
]
List/serializers.py
from rest_framework import serializers
from List.models import List
class ListSerializers(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
title = serializers.CharField(required=True, allow_blank=False,max_length=120)
slug = serializers.SlugField(required=False,)
description= serializers.CharField(required=True, allow_blank=False)
image = serializers.ImageField(required=True,)
timestamp = serializers.DateTimeField(required=True,)
code = serializers.CharField(style={'base_template': 'textarea.html'})
language = serializers.CharField(default='python')
style = serializers.CharField(default='friendly')
def create(self, validated_data):
return List.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.title = validated_data.get('title', instance.title)
instance.descritption = validated_data.get('descritption', instance.descritption)
instance.image = validated_data.get('image', instance.image)
instance.timestamp = validated_data.get('timestamp',instance.timestamp)
instance.language = validated_data.get('language',instance.language)
instance.style = validated_data.get('style',)
instance.save()
return instance
List/models.py
import random
import os
from django.db import models
from django.urls import reverse
from django.db.models.signals import pre_save, post_save
from lokswar.utils import unique_slug_generator
from pygments.lexers import get_all_lexers
from pygments.styles import get_all_styles
LEXERS = [item for item in get_all_lexers() if item[1]]
LANGUAGE_CHOICES = sorted([(item[1][0],item[0]) for item in LEXERS])
STYLE_CHOICES = sorted((item,item) for item in get_all_styles())
def get_filename_ext(filepath):
base_name = os.path.basename(filepath)
name, ext = os.path.splitext(base_name)
return name,ext
def upload_image_path(instence, filename):
new_filename = random.randint(1,396548799)
name, ext = get_filename_ext(filename)
final_filename = '{new_filename}{ext}'.format(new_filename=new_filename, ext= ext)
return "card/{new_filename}/{final_filename}".format(new_filename=new_filename,
final_filename=final_filename)
class ListQuerySet(models.query.QuerySet):
def active(self):
return self.filter(active=True)
class ListManager(models.Manager):
def get_queryset(self):
return ListQuerySet(self.model, using=self._db)
def all(self):
return self.get_queryset().active()
class List(models.Model):
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=120)
slug = models.SlugField(blank=True, unique=True)
description= models.TextField()
image = models.ImageField(upload_to=upload_image_path,null=True, blank=True)
active = models.BooleanField(default=True)
timestamp = models.DateTimeField(auto_now_add=True)
code = models.TextField(default=True)
language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100)
style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)
objects = ListManager()
class Meta:
ordering = ('created',)
def get_absolute_url(self):
return reverse('List', kwargs={'pk': self.pk, 'slug': self.slug })
def __str__(self):
return self.title
def __unicode__(self):
return self.title
Please help me to solve this error.
I am trying to run my API through this url http://127.0.0.1:8000/List/list/
urls.py
from django.contrib import admin
from django.urls import path,include
from django.conf import settings
from django.conf.urls.static import static
from .views import HomeListView
urlpatterns = [
path('List',include('List.urls'), name="List"),
path('news/',include('news.urls'), name="news"),
path('', HomeListView.as_view(), name='home'),
path('sports/',include('sports.urls'), name="sports"),
path('movie/',include('movie.urls'), name="movie"),
path('business/',include('business.urls'), name="business"),
path('api-auth/', include('rest_framework.urls')),
path('admin/', admin.site.urls),
]
You make a small mistake in url at url.py file.
Change:
path('List',include('List.urls'), name="List"),
Into:
path('List/',include('List.urls'), name="List"),
urlpatterns = [
path('',MainListView.as_view(),name='list'),
path('(<pk>\d+)(?:/(<slug>[\w\d-]+))',MainDetailSlugView.as_view(), name='List'),
path('list/',views.list_list),
path('lists/<int:pk>/',views.list_detail),
]
As you can see above, you have two urls defined that apply here
/list/
/lists/<int> # which applies to something like /lists/293749
you're URL calling is /List/list, which doesn't apply to any URLs here unless you define a project-level URLs.py with something like
urlpatterns = [
path('list/', include('List.urls'))
]
Couple things:
Take a look at python conventions. Classes are capitalized and PascalCase whereas variables, methods and functions are snake_case. No reason for you to have a module capitalized
Don't use the same names as python/django builtins and reserved words. That causes issues and is a good habit to get into.
I believe django treats urls as case sensitive when they come in the URL parser. You call /List, but the url definition is /list
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'])