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)
Related
I'm trying to get all the urls for specific Django project detail pages for instance:
path('/mysite/speical/<pk>',views.DetalView.as_view(),name='detail')
/mysite/special/1390u20
/mysite/special/930nfdn
/mysite/special/29093nn
How do I print all these urls into an xml file in the shell? I'm not sure where to even start.
In your urls.py:
from django.contrib.sitemaps.views import sitemap
from .sitemap import SpeicalSitemap
sitemaps = {
yoursitemap: YourSitemap
}
path('sitemap.xml', sitemap, {'sitemaps': sitemaps}, name='sitemap'),
Create a file named sitemap.py inside your app:
from django.contrib.sitemaps import Sitemap
from yourapp.models import Yourmodel
class YourSiteMap(Sitemap):
changefreq = 'monthly'
priority = 0.9
def items(self):
return yourmodel.objects.all()
def lastmod(self, obj):
return obj.last_mod_date "Here your put a last mod date defined in your model if you have it."
To create the right route to your objects, you need to put a method in your model called "get_absolute_url", let's create:
from django.urls import reverse
class YourModel(models.Model):
def get_absolute_url(self):
return reverse('name_of_your_route', kwargs={'pk': self.pk})
as_view only accepts arguments that are already attributes of the class
This make no sense to me since template_name is an attribute. I checked for similar questions but couldn't find an indication of where I went wrong with the code. Here is my code.
urls.py:
from django.conf.urls import url
from .views import PostList
urlpatterns = [
url(r'^$',
PostList.as_view(
template_name='blog/post_list.html'),
name='blog_post_list'),
]
views.py
from django.views.generic import View
from .models import Post
class PostList(View):
def get(self, request):
return render(
request,
'blog/post_list.html',
{'post_list': Post.objects.all()})
The View class, doesn't have a template_name attribute, you either want to use TemplateView, or it would make more sense to use a ListView
class PostList(ListView):
context_object_name = 'post_list'
template_name = 'blog/post_list.html'
def get_queryset(self):
return Post.objects.all()
Note: Either way, since you already set the template name in your view, you don't actually need to include it in the call to as_view anyway
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
I created a very simple example code using Django, but cannot get model value to be displayed on my page:
----------------------------- home/models.py
from django.db import models
class Home(models.Model):
msg = models.CharField(max_length=100)
#classmethod
def create(cls, msg):
home = cls(msg=msg)
# do something with the book
return home
home = Home.create("Hello World!")
------------------------------------home/views.py
from django.views.generic import TemplateView
from project.models import Home
class IndexView(TemplateView):
model = Home
template_name = 'home/index.html'
------------------------------------------ templates/home/index.html
{{ home.msg }}
this is a test page. I am expecting to see this....
------------------------------------------- urls.py
from django.conf.urls.defaults import patterns, include, url
from django.contrib import admin
from django.views.generic import TemplateView
admin.autodiscover()
urlpatterns = patterns('',
# Home pagetentacl.urls
url(r'^$', TemplateView.as_view(template_name='home/index.html')),
# Uncomment the admin/doc line below to enable admin documentation:
# url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
# Uncomment the next line to enable the admin:
url(r'^admin/', include(admin.site.urls)),
)
-------------------------------------- result page on browser:
this is a test page. I am expecting to see this....
I don't want to have DB access for my example. I want my model returns "hello world" string. home.msg on index.html doesn't return anything. What is missing here?
You're not giving the template an instance of Home. You need to create one and pass it to the template as a Context, in the form {'msg': msg}.
EDIT: Adding some code
First of all, you should create your instance of home in your view. I've never used TemplateViews, so I'm going to use a regular view method instead.
def IndexView(request):
home=Home.create("Hello World!")
return render(request, 'index.html', {'home': home},)
As #Daniel rightly points out, you're not giving your template an instance of Home to work with.
If you want to use class-based views, subclass TemplateView and override get_context_data():
class IndexView(TemplateView):
template_name = "home/index.html"
def get_context_data(self, **kwargs):
context = super(HomePageView, self).get_context_data(**kwargs)
context["home"] = Home.create("Hello World!")
return context
And make sure your urls.py is using IndexView.as_view() - your version above is just referencing the generic TemplateView.
The fact that you added a model field to your subclass of TemplateView makes me think you're confusing it with DetailView. See the documentation for the difference.
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'