Listview Class based view is not working properly - python

I am using class based views in my app but I am stuck at one point. I am using ListView and created two classes which are sub-classes of ListView.
views.py
class blog_home(ListView):
paginate_by = 3
model= Blog
context_object_name = 'blog_title'
template_name = 'blog.html'
class blog_search(ListView):
paginate_by = 4
context_object_name = 'blog_search'
template = 'blog_search.html'
def get_queryset(self):
self.search_result = Blog.objects.filter(title__contains = 'Static')
return self.search_result
urls.py
urlpatterns = [
url(r'^$', index, name='index'),
url(r'^grappelli/', include('grappelli.urls')),
url(r'^blog/', blog_home.as_view(), name='blog_home'),
url(r'^admin/', include(admin.site.urls)),
url(r'^blog/search/',blog_search.as_view(),name='blog_search'),
]
In my above code in blog_Search(), get_queryset() method is not getting called. I mean it's not working. If I use same same method in blog_home it does work.
blog_search not filtering. I added print statement also but not get called.
Can I create two classes with ListView in same file? Is this the problem?

You need to terminate your blog/ URL entry. Without termination, it matches all URLs beginning with "blog/", including "blog/search", so no requests ever make it to the blog_search view.
url(r'^blog/$', blog_home.as_view(), name='blog_home'),
url(r'^admin/', include(admin.site.urls)),
url(r'^blog/search/$',blog_search.as_view(),name='blog_search'),

Related

Having trouble in routing ( giving urls or path) in Django Rest Framework

This is my main project urls . Now I have an app which is routed by path('', include('mysite.urls')),. Now I have a folder named crmAPi for creating apis. This api folder is not an app though, just a folder. I route the urls by using path('api', include("mysite.crmapi.urls")),.
urlpatterns = [
path('', include('mysite.urls')),
path('admin/', admin.site.urls),
path('api', include("mysite.crmapi.urls")),
]
Now, this is my crmApi urls. The problem is I can access to first path, i can see airilnes list. No, matter what i do, i cannot acces flightdetails. What is the problem with the route?? help pleaseee?? even i create a different listview, again I cannot the route, only the arilines one, I can access.
urlpatterns = [
path('', views.AirlinesListAPIView.as_view(), name='api'),
path('api/flightdetails', views.FlightDetailsListAPIView.as_view(), name='flightdetails'),
]
This is my view.
class AirlinesListAPIView(ListAPIView):
# permission_classes = [AllowAny]
serializer_class = AirlinesListSerailizer
queryset = Airlines.objects.all()
permission_classes = (IsAdminUser,)
class FlightDetailsListAPIView(ListAPIView):
# permission_classes = [AllowAny]
serializer_class = FlightDetailsListSerailizer
queryset = FlightDetails.objects.all()
permission_classes = (IsAdminUser,)
Well, you included the api.urls under api/ path. And inside api.urls you also have api/flightdetails, which contains api.
My assumption is that you're trying to access http://127.0.0.1/api/flightdetails, but it doesn't actually exist, because FlightDetailsListAPIView is accessible under http://127.0.0.1/api/api/flightdetails.
If you want access it via http://127.0.0.1/api/flightdetails, you should rename the path to:
path('flightdetails/', views.FlightDetailsListAPIView.as_view(), name='flightdetails'),

Django,DRF, get another app's view name for a reverse

I'm trying to create a link for another app in my serializer using the solution provided here:
https://stackoverflow.com/a/45850334/12177026
I'm trying to match the view's name but every way I try I get this error:
Reverse for 'KnownLocationView' not found. 'KnownLocationView' is not a valid view function or pattern name.
serializers:
class MissionSerializer(HyperlinkedModelSerializer):
gdt = ChoiceField(choices=lazy(get_locations, tuple)())
location = SerializerMethodField(label='Open Location')
def get_location(self, obj):
request = self.context.get('request')
return request.build_absolute_uri(reverse('KnownLocationView', kwargs={'Name': obj.gdt}))
class Meta:
model = Mission
fields = ('MissionName', 'UavLatitude', 'UavLongitude', 'UavElevation', 'Area',
'gdt', 'location')
KnownLoction/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import KnownLocationView
app_name = 'KnownLocation'
router = DefaultRouter()
router.register(r'knownlocations', KnownLocationView)
urlpatterns = [
path('', include(router.urls)),
]
I tried replacing view_name with either of the following:
'knownlocations'
'KnownLocation:knownlocations'
'KnownLocation:KnownLocationView'
But get the same error
even tried to reorder the installed apps.
api/urls.py:
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('django.contrib.auth.urls')),
path('', include('landingpage.urls')), # API Landing Page
path('', include('ThreeLocations.urls')), # Triangulation between two Known GDTs and uav location.
path('', include('SecondGDT.urls')), # Options For Second GDT Positioning.
path('', include('KnownLocation.urls', namespace='knownlocations')),
# Add Known Location To the map.
] + staticfiles_urlpatterns()
KnownLocation/views.py
from rest_framework.renderers import AdminRenderer
from rest_framework.viewsets import ModelViewSet
from .models import KnownLocation
from .serializers import KnownLocationSerializer
class KnownLocationView(ModelViewSet):
"""
List of Known Locations In which we can place one of our ground positions.
press create to add a new location.
"""
serializer_class = KnownLocationSerializer
queryset = KnownLocation.objects.all()
def get_serializer_context(self):
data = KnownLocationSerializer(self.queryset, many=True, context={'request': self.request})
return data
renderer_classes = [AdminRenderer]
I think you should try to change how you are calling the reverse.
You can find reference to it below
Note: If using namespacing with hyperlinked serializers you'll also need to ensure that any view_name parameters on the serializers correctly reflect the namespace. In the examples above you'd need to include a parameter such as view_name='app_name:user-detail' for serializer fields hyperlinked to the user detail view.
The automatic view_name generation uses a pattern like %(model_name)-detail. Unless your models names actually clash you may be better off not namespacing your Django REST Framework views when using hyperlinked serializers.
Try using this
reverse('KnownLocationView:mission-detail, kwargs={'Name': obj.gdt})
Or
reverse('mission-detail, kwargs={'Name': obj.gdt})

CreateView weird behaviour. Goes to the wrong view?

In my urls.py I have a ListView and a CreateView. When I have both the views in the urls patterns, the CreateView shows the html linked to the ListView. But when I remove the ListView from the url patterns, then the CreateView shows the correct html.
urls.py
If I have it like this, CreateView shows ListView html
urlpatterns = [
path("", views.TopicListView.as_view(), name="topic"),
path("<topic>/", views.PostListView.as_view(), name="post"),
path("create/", views.CreatePostView.as_view(), name="create_post")
]
This way, the CreateView behaves like I want it to. Shows the correct HTML
urlpatterns = [
path("", views.TopicListView.as_view(), name="topic"),
path("create/", views.CreatePostView.as_view(), name="create_post")
]
views.py
class PostListView(ListView):
model = models.ForumPost
template_name = "forum/post_list.html"
def get_context_data(self):
context = super().get_context_data()
return context
def get_queryset(self):
query_set = super().get_queryset()
return query_set
class CreatePostView(CreateView):
model = models.ForumPost
fields = ("title", "description")
template_name = "forum/create_post.html"
The reason as urls are checking one by one from up to down. So when you have 3 urls:
urlpatterns = [
path("", views.TopicListView.as_view(), name="topic"),
path("<topic>/", views.PostListView.as_view(), name="post"),
path("create/", views.CreatePostView.as_view(), name="create_post")
]
And try to use create/ it actually matches <topic>/ pattern as a string were passed. So what I recommend is to place it to very down:
urlpatterns = [
path("", views.TopicListView.as_view(), name="topic"),
path("create/", views.CreatePostView.as_view(), name="create_post")
path("<topic>/", views.PostListView.as_view(), name="post"),
]
But also it would be better if you add some additional path to urls in order it won't be double-minded like list/<topic>/.

Django: Class-based views, URL and template_name

I am trying to use something like polls:detailin a class-based view, such as this:
class QuestionDetail(DetailView):
template_name = 'polls:result'
However, I get a TemplateDoesNotExist at /polls/2/result
polls:result error...
The urls.py is:
from django.conf.urls import url
from polls.views import IndexView, DetailView, ResultsView
from . import views
app_name = 'polls'
urlpatterns = [
url(r'^$', IndexView.as_view(), name='index'),
url(r'^(?P<pk>\d+)/$', DetailView.as_view(), name='detail'),
url(r'^(?P<pk>\d+)/result$', ResultsView.as_view(), name='result'),
url(r'^(?P<pk>\d+)/vote$', views.vote, name='vote'),
]
I guess the main question is, how do I use the names of URLs in class-based views, instead of explicitly providing the template name, such as polls/question_results.html?
Is there anything other than template_name?
I was reading that it's a good practice to use names in URLS so in case the URL itself changes, the rest of the code still works, so that's what I'm trying to do.
Url name and template name are very absolutely things.
template_name is a path to the .html file.
Url's name parameter you can use to reverse url from name using django.urls.reverse
You can use the name of URL like this:
django.urls.reverse('polls:detail', args=[object.id])
And you have to change the template_name settings as well and to create a template detail.html in your current template folder.
template_name = 'polls/detail.html'

Add context to every Django Admin page

How do I add extra context to all admin webpages?
I use default Django Admin for my admin part of a site.
Here is an url entry for admin:
urlpatterns = [
url(r'^admin/', admin.site.urls),
]
And my apps register their standard view models using:
admin.site.register(Tag, TagAdmin)
My problem, is that I want to display an extra field in admin template header bar and I have no idea how to add this extra context.
My first bet was adding it in url patterns like below:
urlpatterns = [
url(r'^admin/', admin.site.urls, {'mycontext': '123'}),
]
But that gives an error:
TypeError at /admin/tickets/event/4/change/
change_view() got an unexpected keyword argument 'mycontext'
Can you give any suggestion? I really do not want to modify every AdminModel class I have to insert this context, as I need it on every admin page.
Thanks.
Found the solution, url registration has to be:
urlpatterns = [
url(r'^admin/', admin.site.urls, {'extra_context': {'mycontext': '123'}}),
]
Its a context dictionary inside of a dictionary with 'extra_context' as a key.
Another technique, more complex but allows different context per request (probably unavailable at OP time):
my_project/admin.py (create if missing)
from django.contrib import admin
from django.contrib.admin.apps import AdminConfig
class MyAdminConfig(AdminConfig):
default_site = 'my_project.admin.MyAdminSite'
class MyAdminSite(admin.AdminSite):
def each_context(self, request):
context = super().each_context(request)
context.update({
"whatever": "this is",
"just a": "dict",
})
return context
settings.py
INSTALLED_APPS = [
...
'my_project.admin.MyAdminConfig', # replaces 'django.contrib.admin'
...
The replace / extend admin class code is taken from the official docs except this is all in one file.

Categories