How to connect Detail Class Based View to Template URL Mapping?
Here is views.py file in myapp:
class ModelDetailView(DetailView):
model = models.mymodel
template_name = 'mymodel_detail.html'
Here is urls.py of myapp
.....path('<pk>', ModelDetailView.as_view(), name = 'detail')...........
Here is mymodel_detail.html file:
........<li>{{ object.title }}</li>.......
I want that when I click on object.title, it leads me to its detailed view? How do I do that?
Have also tried: (urls.py)
path('(?P<pk>[-\W]+)/', ModelDetailView.as_view(), name = 'detail')
and
path('detail<pk>', ModelDetailView.as_view(), name = 'detail'),
path('detail/<int:pk>/', ModelDetailView.as_view(), name ='detail'),
Related
I'm trying to create an app that stores problems (specifically math problems), and displays them to the user. I haven't add much of the functionality that I want to yet, and as I'm fairly new to Django, I have been following along with the Django Tutorial project, and changing it according to my needs. However, I'm encountering a NoReverseMatch error even though I seem to be passing in the correct parameters. My code is below.
models.py
import imp
from django.db import models
from django.urls import reverse
import uuid
# Create your models here.
class Source(models.Model):
'''Model that represents the source of a problem (e.g. AMC, AIME, etc.)'''
problem_source = models.CharField(max_length=20)
problem_number = models.PositiveSmallIntegerField()
def __str__(self):
'''toString() method'''
return f'{self.problem_source} #{self.problem_number}'
class Topic(models.Model):
'''Model that represents the topic of a problem (e.g. Intermediate Combo)'''
problem_topic = models.CharField(max_length=50)
problem_level = models.CharField(max_length=15)
def __str__(self):
return f'{self.problem_level} {self.problem_topic}'
class Problem(models.Model):
'''Model that represents each problem (e.g. AIME #1, AMC #11, etc.)'''
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
source = models.OneToOneField(Source, on_delete=models.RESTRICT, null=True, unique=True)
problem_text = models.TextField()
topic = models.ManyToManyField(Topic)
def __str__(self):
"""String for representing the Model object."""
return f'{self.source}'
def get_absolute_url(self):
"""Returns the url to access a detail record for this book."""
return reverse('problem-detail', args=[str(self.id)])
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('problems/', views.ProblemListView.as_view(), name='problems'),
path('problem/<int:pk>', views.ProblemListView.as_view(), name='problem-detail'),
]
views.py
import imp
from django.shortcuts import render
# Create your views here.
from .models import Problem, Source, Topic
def index(request):
'''View function for home page of site'''
# generate counts of the main objects
num_problems = Problem.objects.all().count()
context = {
'num_problems': num_problems,
}
return render(request, 'index.html', context=context)
from django.views import generic
class ProblemListView(generic.ListView):
model = Problem
class ProblemDetailView(generic.DetailView):
model = Problem
Links to my HTML files are below:
base_generic.html: link
problem_list.html: link
problem_detail.html: link
My workspace is structured as follows:
trivial
catalog
migrations
static/css
styles.css
templates
catalog
problem_detail.html
problem_list.html
base_generic.html
index.html
__init.py
admin.py
apps.py
models.py
tests.py
urls.py
views.py
trivial
__init__.py
asgi.py
settings.py
urls.py
wsgi.py
db.sqlite3
manage.py
I have read other StackOverflow posts, but none seem to apply to my situation. Also, in problem_list.html, if the value in the href link is Problem.get_absolute_url, the site will load, but clicking the link for "all problems" will lead back to the same page. But, if I put prob.get_absolute_url in the href link, I get a NoReverseMatch error.
Here is the exact error that I am getting:
NoReverseMatch at /catalog/problems/
Reverse for 'problem-detail' with arguments '('41b936f7-3c08-4fb9-a090-2d466348d34d',)' not found. 1 pattern(s) tried: ['catalog/problem/(?P<pk>[0-9]+)\\Z']
Request Method: GET
Request URL: http://127.0.0.1:8000/catalog/problems/
Django Version: 4.0.2
Exception Type: NoReverseMatch
Exception Value:
Reverse for 'problem-detail' with arguments '('41b936f7-3c08-4fb9-a090-2d466348d34d',)' not found. 1 pattern(s) tried: ['catalog/problem/(?P<pk>[0-9]+)\\Z']
Django is telling me that the error stems from calling prob.get_absolute_url in problem_list.html
The problem is that your id on the Problem model is a UUID, but your URL pattern is expecting an integer value as the pk - because you have prefixed the named pattern with int::
path('problem/<int:pk>', views.ProblemListView.as_view(), name='problem-detail'),
It should work if you change it to:
path('problem/<uuid:pk>', views.ProblemListView.as_view(), name='problem-detail'),
I want to create a custom plugin for Django CMS. As the guide was showing, I created some examples. But now the goal is to create a plugin that will get the data from (mysql) database. It will load all titles that belong to the menu, because I want to have some similar to table of contents.
To get data from an custom model, the code goes like this:
models.py:
from cms.models.pluginmodel import CMSPlugin
from django.db import models
class Hello(CMSPlugin):
guest_name = models.CharField(max_length=50, default='Guest')
cms_plugins.py:
from cms.plugin_base import CMSPluginBase
from cms.plugin_pool import plugin_pool
from django.utils.translation import ugettext_lazy as _
from .models import Hello
class HelloPlugin(CMSPluginBase):
model = Hello
name = _("Hello Plugin")
render_template = "hello_plugin.html"
cache = False
def render(self, context, instance, placeholder):
context = super(HelloPlugin, self).render(context, instance, placeholder)
return context
plugin_pool.register_plugin(HelloPlugin)
But as cms_title belongs to the Django-CMS by default, what options are possible here? Where can I find the definition of CMS model with name Title? Would setting it to CMSPlugin instance be a bad way?
Well, after few hours of struggling with this case, I finally succeeded to resolve my problem.
First of all, to answer the part of the question with CMS model and parameter title (in db: cms_title). Creating a new model with the FK to CMS title is the right way.
In models.py:
class TitlePlugin(CMSPlugin):
title = models.ForeignKey(Title)
As next, you need to import it to cms_plugins.py, so it will look like this:
from .models import TitlePlugin
class MyTitlePluginClass(CMSPluginBase):
model = TitlePlugin
render_template = "titles.html"
cache = False
As you see, the model that we load is TitlePlugin, we defined in models.py (which has FK to original cms_title).
And now, render it:
def render(self, context, instance, placeholder):
context = super(MyTitlePluginClass, self).render(context, instance, placeholder)
return context
But my goal was to load it into template for the purpose of 'table of contents', right? So I had to change some things.
I removed models.py content (not needed!)
The new cms_plugins.py had modifications too:
first:
from cms.models.pagemodel import Page
#we import the Page model
and the renewed class:
class MyTitlePluginClass(CMSPluginBase):
model = CMSPlugin
render_template = "titles.html"
cache = False
def render(self, context, instance, placeholder):
pages = Page.objects.filter(in_navigation=True, publisher_is_draft=False)
#context = {
#'pages' : pages,
#}
# edit: append to 'pages' existing list!
context['pages'] = pages
context = super(MyTitlePluginClass, self).render(context, instance, placeholder)
return context
plugin_pool.register_plugin(MyTitlePluginClass)
And in the template, we simply print it using for loop
titles.html:
{% for page in pages %}
<div class="panel callout ">
{{ page }}
</div>
{% endfor %}
I am a newbie in djnago. I am trying to understand the openstack project. In one place they are calling class AdminIndexView through url in urls.py. I understand how the url works, but in class AdminIndexView there are some methods like def get_data(self):, def has_more_data. I wanted to know where they call these methods. And in urls.py they are using something like url(r'^$', views.AdminIndexView.as_view(), name='index'). What do as_view and name='index' mean?
views.py
class AdminIndexView(tables.DataTableView):
table_class = project_tables.AdminInstancesTable
template_name = 'admin/instances/index.html'
page_title = _("Instances")
def has_more_data(self, table):
return self._more
def get_data(self):
instances = []
marker = self.request.GET.get(
project_tables.AdminInstancesTable._meta.pagination_param, None)
search_opts = self.get_filters({'marker': marker, 'paginate': True})
# Gather our tenants to correlate against IDs
try:
tenants, has_more = api.keystone.tenant_list(self.request)
except Exception:
tenants = []
msg = _('Unable to retrieve instance project information.')
exceptions.handle(self.request, msg)
if 'project' in search_opts:
ten_filter_ids = [t.id for t in tenants
if t.name == search_opts['project']]
del search_opts['project']
if len(ten_filter_ids) > 0:
search_opts['tenant_id'] = ten_filter_ids[0]
else:
self._more = False
return []
urls.py
from django.conf.urls import patterns
from django.conf.urls import url
from openstack_dashboard.dashboards.admin.instances import views
INSTANCES = r'^(?P<instance_id>[^/]+)/%s$'
urlpatterns = patterns(
'openstack_dashboard.dashboards.admin.instances.views',
url(r'^$', views.AdminIndexView.as_view(), name='index'),
In Django you can hook up URL patterns to a handler. These handlers are either functions are can be "class based". In short class based views are good! and .as_view() basically sets up the class to accept requests from a URL pattern.
I suggest you look here for more info on class based views: https://docs.djangoproject.com/en/1.8/topics/class-based-views/.
The name parameter is an arbitrary name you can give to a URL so that you can find it later, for example you if you needed to construct the URL of a certain view instead of creating the url yourself each time, you would call a method.
reverse("<app_name>:<name>")
Where app_name is the name of your application and name is the value in the name parameter (in Django 1.8 + names of urls are name spaced by app_name)
As for the get_data methods, these are called by the superclass of your view see here for more info on that:
http://docs.openstack.org/developer/horizon/topics/tables.html#fetching-the-row-data
I have content = 'Please get me the Python book you talked about, #friend'
Then this in my views.py:
new_content = re.sub(r'(#\w+)', r"<a href='#'>\g<0></a>>", content)
This returns
new_content = 'Please get me the Python book you talked about, <a href='#'>#friend</a>'
I want if a user clicks of #friend, it should redirect to this url:
url(r'^user/(?P<user_name>\w+)/$', views.profile, name='profile'),
How do I include this url(profile) in #{{user.username}}?
You use reverse()
return HttpResponseRedirect(reverse('url_name'))
You can check this answer for reference.
And the documentation for the function.
You may need to pass arguments. You can do it like this:
reverse('profile', kwargs={'user_name': 'auth'})
For your case you can try:
content = 'Please get me the Python book you talked about, #friend'
new_content = re.sub(r'(#\w+)', r"<a href='%s'>\g<0></a>>" % (reverse('profile', kwargs={'user_name': 'friend_username'})), content)
You already named argument it's user_name
# urls.py
url(r'^user/(?P<user_name>\w+)/$', views.profile, name='profile'),
# views.py
from django.views.generic.detail import DetailView
class UserDetailView(DetailView):
"""
Takes keyword argument 'user_name'
and looks for it in database:
User.objects.get(username='dude')
"""
model = User
slug_field = 'username'
context_object_name = 'user'
slug_url_kwarg = 'user_name'
template_name = 'user_detail.html'
# Pass your keyword argument
#{{ user.username }}
I have a page drag.htmlwhich is served at this URL
http://localhost:8000/dashboard?wid=ca1480f&ref_url=localhost&adpart=left this page have a link
<a id="btn-start" href="/dashboard/save" class="btn">Save Reward</a>
when a user click this link it will redirect to a SaveRewardview where i want to save all the information present in link i.e wid=ca1480f&ref_url=localhost&adpart=left
urls.py
url(r'^dashboard$', login_required(CouponPageView.as_view()), name='dashboard'),
url(r'^dashboard/save$', login_required(SaveRewardView.as_view()), name=''),
model.py
class SaveReward(models.Model):
widget = EmbeddedModelField(Widget)
campaign = EmbeddedModelField(Campaign)
coupon_part = models.CharField(max_length=200)
saved_on = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return self.widget.widget_name
Views.py
class SaveRewardView(TemplateView):
#Here how i will get wid , ref_url, adpart which is present in url parameters
You can directly give parameters in url like this.
<a id="btn-start" href="/dashboard/?{{request.META.QUERY_STRING}}" class="btn">Save Reward</a>
url is:
url(r'^dashboard/$', login_required(CouponPageView.as_view()), name='dashboard'),