Which to use in Django: ListView or list_detail? - django

I was reading some tutorials and books about generic views.
In part 4 of the official tutorial, they wrote an example like this
from django.conf.urls import patterns, include, url
from django.views.generic import DetailView, ListView
from polls.models import Poll
urlpatterns = patterns('',
url(r'^$',
ListView.as_view(
queryset=Poll.objects.order_by('-pub_date')[:5],
context_object_name='latest_poll_list',
template_name='polls/index.html')),
url(r'^(?P<pk>\d+)/$',
DetailView.as_view(
model=Poll,
template_name='polls/detail.html')),
url(r'^(?P<pk>\d+)/results/$',
DetailView.as_view(
model=Poll,
template_name='polls/results.html'),
name='poll_results'),
url(r'^(?P<poll_id>\d+)/vote/$', 'polls.views.vote'),
)
I have also been reading The Definitive Guide to Django: Web Development Done Right, Second Edition and when they talked about generic views, they wrote their example like this
from django.conf.urls.defaults import *
from django.views.generic import list_detail
from mysite.books.models import Publisher
publisher_info = {
'queryset': Publisher.objects.all(),
'template_name': 'publisher_list_page.html',
}
urlpatterns = patterns('',
(r'^publishers/$', list_detail.object_list, publisher_info)
)
Should I be using ListView or list_detail? They both come from django.views.generic. If they can both be used, then what's the difference (advantage and disadvantage comparison)?
In case it helps, I'll explain my objective: In my project, I want to list work orders, and then I want a detailed view of each work order that will also contain a list of comments for that order (similar to comments per blog post).

I'm finding Classy useful as an easy way to view an outline of each CBV: http://ccbv.co.uk/projects/Django/1.6/django.views.generic.list/ListView/
It feels like a missing part of the Django docs now.

ListView (class-based) is intended to replace object_list (function-based) because there is limited flexibility to extending a function's behavior.
As the Django (1.4) documentation notes, the function-based generic views are deprecated in favor of the class-based versions. So use ListView, since Django removed object_list.
Either way, I prefer to put all the customizations in views.py to avoid cluttering up urls.py, which tends to be a dumping ground of things.

Related

Add extra context to a Django Flatpages template

The flatpage() view in Django's Flatpages app passes a single context item to templates, flatpage. I'd like to add more data to the context and the only way I can think of is to copy both the flatpage() and render_flatpage() functions from the original views.py into a new app. And then in my urls.py where I have this:
from django.contrib.flatpages import views
from django.urls import path
urlpatterns = [
path("about/", views.flatpage, {"url": "/about/"}, name="about"),
]
instead import from myapp import views to use my new custom view.
Both of my copies of the functions would be exactly the same as originals, except render_flatpage() would add more context data.
This seems over the top, copying so much code unchanged. But I don't have a better idea.
I don't want to create a custom context_processor for this, because this context is specific to each Flatpage, and should not be used on on other pages.

Python - Django add multiple urlpatterns for multiple views of template

I'm very very new to Python 3 and Django and I get to the following problem: I use a standard Template and now how to set it up when there is 1 view. But I don't get the code right for multiple views. I currently run the page locally
At the moment I have tried to change different orders within urlpatterns, and they do work when only 1 url in in there, but I can't get the second one in
views.py
from django.shortcuts import render, render_to_response
# Create your views here.
def index(request):
return render_to_response('index.html')
def store(request):
return render_to_response('store.html')
urls.py
from django.conf.urls import include, url
from django.contrib import admin
from myapp import views as views
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^store/$', views.store, name='store'),
url(r'^admin/', admin.site.urls)
]
urlpatterns += staticfiles_urlpatterns()
I would like the url pattern that lets me go to the index view and the store view
EDIT:
Full code is shared via: https://github.com/lotwij/DjangoTemplate
The error in the comments shows you are going to http:/127.0.0.1:8000/store.html, but your URL pattern url(r'^store/$', ...) does not include the .html, so you should go to http:/127.0.0.1:8000/store/.
The Django URL system uncouples the URL from the name of the template (sometimes the view doesn't even render a template!). You could change the regex to r'^store.html$ if you really want .html in the URL, but I find the URL without the extension is cleaner.

How to reverse match multiple Django admin sites (Custom admin site namespaces)

When you extend AdminSite to create another admin site how do you go about being able to reverse match each site? It seems the admin namespace is hardcoded reverse('admin:index'), is there a way to supply a custom namespace?
You may be confused with the namespace in django. If you are interested to clarify that confusion, you may read up the discussion here.
If you want to try solve your problem, there is a specific documentation for multiple admin sites.
Below are example solutions mostly copied from official documentation
Example Solution:
# urls.py
from django.conf.urls import url
from .sites import basic_site, advanced_site
urlpatterns = [
url(r'^basic-admin/', basic_site.urls),
url(r'^advanced-admin/', advanced_site.urls),
]
And
# sites.py
from django.contrib.admin import AdminSite
class MyAdminSite(AdminSite):
site_header = 'Monty Python administration'
basic_site = MyAdminSite(name='myadminbasic')
advanced_site = MyAdminSite(name='myadminadvanced')
Reversing
reverse('myadminbasic:index') # /basic-admin/
reverse('myadminadvanced:index') # /advanced-admin/

Django import views multiple times in urls.py

In Django, is it not possible to have multiple views imports from the urls.py?
For example, I have the following code in urls.py:
from mysite.books import views
from mysite.contact import views
urlpatterns = patterns('',
(r'^contact/$', views.contact),
(r'^search/$', views.search),
)
However, the server displays an error unless I disable one of the couples. So my questions are threefold:
1) Is it not possible to have multiple import views statements?
2) How to get around this?
3) What is best practice for where to put all your views.py? One file? Multiple files? etc.
Thank you.
1) Yes it is.
2)
from mysite.books import views as books_views
from mysite.contact import views as contact_views
urlpatterns = patterns('',
(r'^contact/$', contact_views.contact),
(r'^search/$', books_views.search),
)
3) Per Django docs, "This code can live anywhere you want, as long as it’s on your Python path.". I keep all the app views in app/views.py
You can import as many things as you like, but objects have to have unique names for them to be distinguished.
There are a couple of ways of dealing with this. One is to simply import the functions, rather than the module:
from mysite.books.views import books
from mysite.contact.views import contact
This is obviously only good if you only have one or two views in each file. A second option is to import the modules under different names:
from mysite.books import views as books_views
from mysite.contact import views as contact_views
A third option is not to import the views at all, but use strings to refer to them:
urlpatterns = patterns('',
(r'^contact/$', 'contact.views.contact'),
(r'^search/$', 'book.views.search'),
)
A fourth is to have separate urls.py for each application, and include the urlconfs in the main urls.py.
I think that another option would be:
urlpatterns = patterns('mysite.books.views',
(r'^contact/$, 'contact'),
)
urlpatterns += patterns('mysite.contact.views',
(r'^search/$, 'search'),
)
as described in djangobook.

Django static page?

I want to make a static page which will be shown to the user only if he/she clicks on a link provided in one of my models. I can do this by making a Python page alone and calling it, but I want it be called from Django. The user interface should be constructed using the Django API only.
Any suggestions?
With the class-based views in newer Django versions, one can use this in urls.py:
from django.views.generic import TemplateView
url(r'^about',
TemplateView.as_view(template_name='path/to/about_us.html'),
name='about'),
Bypassing views to render a static template, add this line in "urls.py". For example "About Us" page could be
(r'^about', 'django.views.generic.simple.direct_to_template', {'template': 'path/to/about_us.html'}),
Do you mean something like Django's flatpages app? It does exactly what you describe.
If you want to make a static page the flatpages is a good choice. It allows you to easily create static content. Creating static content is not harder than creating a view really.
On Django 2.2.6, loosely following David's answer, I added the path in urls.py:
from django.views.generic import TemplateView
urlpatterns = [
.... .... ....
path('about',
TemplateView.as_view(template_name='path/to/about_us.html'),
name='about'),
And I needed to adjust settings.py to specify the template directory:
TEMPLATES = [{
... ... ...
'DIRS': [os.path.join(BASE_DIR, 'template')],
Then I saved the actual content in template/path/to/about_us.html