I have a database of both movies and tv shows. I want to filter these like so:
/productions/ = index (all), /productions/films/ = only films, and /productions/series/ = only tv shows
## urls.py
from django.conf.urls import patterns, url
from productions import views
urlpatterns = patterns('',
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^films/$', views.IndexView.as_view(), name='films'),
url(r'^series/$', views.IndexView.as_view(), name='series'),
)
## views.py
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
from django.views import generic
from productions.models import Production, Director
class IndexView(generic.ListView):
template_name = 'productions/index.html'
context_object_name = 'productions_list'
def get_queryset(self):
return Production.objects.order_by('-release')
What would be the best practice for something like this? Create a new method in views.py for each, or could I reuse the main method, and call something like if(productions.is_movie) by somehow parsing the URL segments?
I'd capture the string from url, like this:
urlpatterns = patterns('',
url(r'^(?<query>(films|series|))/$', views.IndexView.as_view(), name='films_series'),
)
Then, in get_queryset() method I'd check whether you need to return all, films or series:
class IndexView(generic.ListView):
template_name = 'productions/index.html'
context_object_name = 'productions_list'
def get_queryset(self):
# analyze `self.kwargs` and decide should you filter or not, just for example:
is_all = self.kwargs['query'] == ''
is_movie = self.kwargs['query'] == 'films'
is_series = self.kwargs['query'] == 'series'
return Production.objects.order_by('-release') # TODO: filter movies or series
Related
I am learning how to use class-based generic views but I keep getting a type error
from invoice.models import Invoice
from invoice.serializers import InvoiceSerializer
from rest_framework import generics
class InvoiceList(generics.ListCreateAPIView):
queryset = Invoice.objects.all()
serializer_class = InvoiceSerializer
class InvoiceDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Invoice.objects.all()
serializer_class = InvoiceSerializer
serialzers.py
from rest_framework import serializers
from .models import Invoice
class InvoiceSerializer(serializers.ModelSerializer):
class Meta:
model = Invoice
fields = "__all__"
urls.py
from django.urls import path
from invoice import views
from rest_framework.urlpatterns import format_suffix_patterns
urlpatterns = [
path('invoice/', views.InvoiceList),
path('invoice/<int:pk>/', views.InvoiceDetail),
]
urlpatterns = format_suffix_patterns(urlpatterns)
I get a type error with the message "init() takes 1 positional argument but 2 were given"
Your import in urls.py looks wrong.
In urls.py, try something like this:
from django.urls import path
from .views import InvoiceList
path('invoice/', InvoiceList.as_view(), name="invoice"), # name can be anything you want.
I never used the format_suffix_patterns, so you can try to take off that line to see if it works.
In my models.py file i made a variable called hero_name. For instance, if the hero name is Bart, I want the url to be ./heroes/Bart
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('<str:hero_name>/', views.heropage, name='heropage'),
]
views.py
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse
from .models import Heroes
def index(request):
return render(request, 'heroes/index.html')
def heropage(request, hero_name):
get_object_or_404(Heroes, pk=hero_name)
return render(request, 'heroes/heropage.html')
models.py
from django.db import models
class Heroes(models.Model):
hero_name = models.CharField(max_length=200)
I think that you need to replace your implementation of get_object_or_404 with one that gets the object based on hero_name and not pk, since in your model, hero_name is not your primary key.
I hope this helps.
It's not clear exactly what you are asking. But you certainly need to use the relevant field to query the object, and pass the result to the template:
hero = get_object_or_404(Heroes, hero_name=hero_name)
return render(request, 'heroes/heropage.html', {"hero": hero})
Set the field you want to primary_key.
class Heroes(models.Model):
hero_name = models.CharField(primary_key=True)
I was referring to this page of django documentation to write views. Can someone explain what I did wrong ? And what could be the solution
self.object_list = self.get_queryset()
File "/vagrant/projects/kodeworms/course/views.py", line 23, in get_queryset
self.Course = get_object_or_404(Course, name=self.args[0])
IndexError: tuple index out of range
My views.py file
# Create your views here.
from django.views.generic import ListView, DetailView
from django.shortcuts import get_object_or_404
from .models import Course, Content
class PublishedCourseMixin(object):
def get_queryset(self):
queryset = super(PublishedCourseMixin, self).get_queryset()
return queryset.filter(published_course=True)
class CourseListView(PublishedCourseMixin, ListView):
model = Course
template_name = 'course/course_list.html'
class CourseContentListView(ListView):
model = Content
template_name = 'course/content_list.html'
def get_queryset(self):
self.Course = get_object_or_404(Course, name=self.args[0])
return Content.objects.filter(course=self.course, published=True)
My urls.py file
from django.conf.urls import patterns, url
from . import views
urlpatterns = patterns('',
url(r"^$", views.CourseListView.as_view(), name="list" ),
url(r"^(?P<slug_topic_name>[\w-]+)/$", views.CourseContentListView.as_view(), name="list"),
)
You are using self.args[0] which is for positional arguments, but you are passing in a keyword argument to your view.
As you have no positional arguments self.args is a zero-length tuple which is why you get that exception.
You should be using self.kwargs['slug_topic_name'] since you have a keyword argument in your url.
if you are going to this url
url(r"^$", views.CourseListView.as_view(), name="list" ),
there is no self.args, you should check it
I suppose, it will work if you will go to this url
url(r"^(?P<slug_topic_name>[\w-]+)/$", views.CourseContentListView.as_view(), name="list"),
Before I decide to use DetailView, I had a url redirect using this solution.
Now that I am using DetailView how do I achieve the same redirect? The name has to be the same since I am using that for LOGIN_REDIRECT_URL in settings.py.
Here is what part of the urls.py looks like
urlpatterns = patterns( 'doors.views',
url(
r'^users/$',
ListView.as_view(
model = User,
template_name = 'doors/users/list.html'
),
),
url(
r'^users/(?P<pk>\d+)/$',
DetailView.as_view(
model = User,
template_name = 'doors/users/detail.html'
),
name = 'users_detail'
),
url( r'^users/self/$', # do some kind of redirect 'users_self_detail', name = 'users_self_detail' ),
)
Check the docs out for decorating urls when using class based views
from django.contrib.auth.decorators import login_required
urlpatterns = patterns( 'doors.views',
url(r'^users/$',login_required(ListView.as_view(model = User,template_name = 'doors/users/list.html')),
...
),
Let's not call this redirecting, because that gets confused with HTTP redirects. Let's just say we want the views to behave the same, ie they should end up in the same code & template. This is where I'd subclass DetailView myself. Something like:
class UserDetailView(DetailView):
model = User
template_name = 'doors/users/detail.html'
class SelfUserDetailView(UserDetailView):
def get_object(self):
return self.request.user
Then in urls.py:
from django.contrib.auth.decorators import login_required
from myapp.views import UserDetailView, SelfUserDetailView
url(r'^users/(?P<pk>\d+)/$', UserDetailView.as_view(), name='users_detail'),
url(r'^users/self/$', login_required(SelfUserDetailView.as_view()), name='users_self_detail'),
These are 2 ways to do it in Django 2.
You can create view and define template path in
1) Create view in url file and define path there
from django.urls import path
from django.views.generic import ListView, DetailView
from crm.models import Organisation
urlpatterns = [
path('org/<int:pk>', DetailView.as_view(model=Organisation,
template_name = 'crm/org/org_detail_main.html'))
2) Create separate view in views and define explicit template there
So here is urls
from django.urls import include, path
from crm.views import OrganisationDetailView
urlpatterns = [
path('org/<int:pk>',OrganisationDetailView.as_view(),
name='organisation_detail')
And views
from .models import Activity, Organisation
from django.views.generic.detail import DetailView
class OrganisationDetailView(DetailView):
model = Organisation
template_name = 'crm/org/org_detail_main.html'
I'm trying to build out a Google News Sitemap in addition to a normal sitemap.xml to avoid having to put additional numerical characters in my URLs.
I've build out the sitemap.xml using Django's contrib system and it works great, but I'm having trouble passing the context to the (unverified) patch updating the framework to gererate a news_sitemap.xml.
This is the patch I've integrated: http://code.djangoproject.com/ticket/10907, but the context isn't passing. I think the issue is with the format I'm using to build the object in my views.py.
The code I have running:
views.py
from django.template import RequestContext
from django.shortcuts import render_to_response
from basic.blog.models import Post
from pages.models import Page
from datetime import date, datetime
from django.contrib.sitemaps import Sitemap, NewsSitemap
'''Builds the sitemap.xml section for all news posts.'''
class PostSitemap(Sitemap):
changefreq = "daily"
priority = 0.3
def items(self):
return Post.objects.published()
def lastmod(self, obj):
return obj.modified
'''Builds the sitemap.xml section for all main pages.'''
class PageSitemap(Sitemap):
changefreq = "daily"
priority = 0.8
def items(self):
return Page.objects.filter(status=1)
def lastmod(self, obj):
return obj.last_modification_date
'''Builds the news_sitemap.xml from blog module.'''
class SiteappNews(Sitemap):
def items(self):
return Post.objects.published()
def publication_date(self, obj):
return obj.publish
urls.py
from django.conf.urls.defaults import *
from django.contrib.sitemaps import Sitemap, FlatPageSitemap, NewsSitemap
from siteapp.views import homepage, news_homepage, qc_contact, PostSitemap, PageSitemap, SiteappNews
from basic.blog.feeds import *
from basic.blog.models import Post
from pages.models import Page
''' Enables Django Admin.'''
from django.contrib import admin
admin.autodiscover()
'''Add Feeds functionality.'''
feeds = {
'latest': BlogPostsFeed,
}
'''http://docs.djangoproject.com/en/1.0/ref/contrib/sitemaps/'''
sitemaps = {
'pagesitemap': PageSitemap,
'postsitemap': PostSitemap,
'flatpages': FlatPageSitemap,
}
news_sitemaps = {
'newssitemap': NewsSitemap,
}
urlpatterns = patterns('',
(r'^admin/doc/', include('django.contrib.admindocs.urls')),
(r'^admin/(.*)', admin.site.root),
(r'^sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}),
(r'^news_sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': news_sitemaps, 'template': 'news_sitemap.xml'}),
The template outputs just wrapper. I'm missing something obvious i think, though there might be an issue with the patch applied. Here's the relevant code for that:
Within sitemaps contrib init.py
class NewsSitemap(Sitemap):
# This limit is defined by Google. See the index documentation at
# http://www.google.com/support/webmasters/bin/answer.py?hl=en&answer=74288
limit = 1000
def get_url_info(self, item, current_site):
url_info = super(NewsSitemap, self).get_url_info(item, current_site)
url_info.update({
'publication_date': self._get('publication_date', item, None),
'keywords': self._get('keywords', item, None),
})
return url_info
Sorted this one out myself after a little digging.
Changed the urls.py lines to:
news_sitemaps = {
'newssitemap': SiteappNews,
}
And changed the code in views.py to build out the relevant Google News fields from the custom module.
Yours will vary future reader (hello!), but it will be something like:
class SiteappNews(Sitemap):
def items(self):
return Post.objects.published()
def publication_date(self, obj):
return obj.publish
def keywords(self, obj):
return obj.tags
check your SQL fields for your models to sub in the correct data for 'publish', 'tags', etc.