Passing a model's string parameter to URL with TemplateView - python

I am listing data from a search result matching the name parameter of my Model. For each result I have a link to the detail page with the key parameter (which is a string) passed in the url, Like this
<ul>
{% for x in results %}
<li><a href = 'login/index/{{x.key}}'>{{x.name}}</a></li>
{% endfor %}
</ul>
My url.py looks like this
app_name = 'kpi'
urlpatterns = [
path('login/index/search', views.SearchView.as_view(), name="search"),
path('login/index/<slug:key>', views.EpicDetailView.as_view(), name="detail")
]
And my views.py look like this:
class SearchView(LoginRequiredMixin, TemplateView):
template_name = 'KPI/search.html'
def get(self, request, *args, **kwargs):
self.q = request.GET.get('q','')
self.results = Epic.objects.filter(name__icontains= self.q)
return super().get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(SearchView, self).get_context_data(**kwargs)
context['results'] = self.results
return context
class EpicDetailView(LoginRequiredMixin, TemplateView):
template_name = 'KPI/epic_detail.html'
def get_context_data(self, **kwargs):
context = super(EpicDetailView, self).get_context_data(**kwargs)
context['lone_epic2'] = Epic.objects.get(key=self.kwargs['key'])
I know I am missing a step here, probably how i created the url path, or needing logic in my views. With the code above i get a page not found error because the template view link doesn't recoginze/match the EpicDetailView url
What I'm Trying to Accomplish
The purpose is to be able to click on the search result, push the key to the url, and store that key value as a variable to use in the EpicDetailView page
NOTE: Although I'm not showing it in the code above, my detail view will be displaying data from multiple model querysets so that is why i'm using TemplateView instead of DetailView for my EpicDetailView

You should pass the slug into your URL like so in your template:
<li>{{x.name}}</li>
Make sure that kpi is properly registered as the namespace for your KPI app. More info on the URL dispatcher here: https://docs.djangoproject.com/en/2.1/ref/templates/builtins/#url

Related

Pass QuerySet in Django url

I'm looking to pass a list as the queryset parameter to a Django ListView. I know you can do this by overwriting the get_queryset method but ideally I would like to avoid this. The reason is, I am referring from another view and already have the queryset I need so I don't want to run the same query twice.
Currently I am linking to my view as follows:
{{active|length}
active is the prepopulated list I want to use as the queryset.
My view looks as follows:
class ProjectListOngoing(ListView):
template_name = "<name of my template>"
model = Project
context_object_name = "projects"
paginate_by = 10
def dispatch(self, request, *args, **kwargs):
self.projects = request.GET.get('projects', [])
return super().dispatch(request, *args, **kwargs)
def get_queryset(self):
return self.projects
This does seem to populate the correct queryset however the primary keys are blank for some reason.
I have the following in my template:
{% for project in projects %}
<li></li>
{% endfor %}
And I get the following error:
Reverse for 'project_detail' with keyword arguments '{'pk': ''}' not found. 1 pattern(s) tried: ['project/(?P<pk>\\d+)/$']

How to retrieve data from an existing db file and display it on webpage using Django?

This is the views.py file:
from django.shortcuts import render
from django.views.generic import TemplateView
from .models import Report
import random
class HomePageView(TemplateView):
def get(self, request, **kwargs):
args = {}
data = Report.objects.all()
args['data'] = data
return render(request, 'index.html',args)
I'm finding it difficult to understand the framework since I'm a beginner. So please help me.
You are trying to use class base view which will be different from function base view, to pass context data to template in class base view you need to override get_context_data method as below:
class HomePageView(TemplateView):
""" Home page view """
template_name = "index.html"
def get_context_data(self, **kwargs):
# first of all calling it's parent class method to get context (if any)
context = super(HomePageView, self).get_context_data(**kwargs)
# now you can update context dictionary as below:
context['data'] = Report.objects.all()
return context
Now you can access data in your template using {{ data }}
You can display the FileField content by passing the following
{{ context_obj.file_field_name.url }} in the template.

Django - Multiple <pk> in urls.py with DetailViews

I'm trying to build a script using Django Generic display views.
My urls.py
url(r'^page/(?P<pk>[0-9]+)/$', PageDetails.as_view(), name='page-details'),
My views.py
class PageDetails(DetailView):
model = Pages
def get_context_data(self, **kwargs):
context = super(PageDetails, self).get_context_data(**kwargs)
return context
The problem
How can I set multi <pk> in my urls like this?
url(r'^page/(?P<pk>[0-9]+)/subpage/(?P<pk>[0-9]+)$', PageDetails.as_view(), name='page-details'),
In my views I need to take data from first and second <pk>.
Change the second pk argument in your url to something else, for example pk_alt:
^page/(?P<pk>[0-9]+)/subpage/(?P<pk_alt>[0-9]+)$
The url parameter pk_alt will then be available in your views function as part of the self.kwargs dictionary, so you can access it using:
self.kwargs.get('pk_alt', '')
You could then update your views to something like the following:
class PageDetails(DetailView):
model = Pages
def get_context_data(self, **kwargs):
context = super(PageDetails, self).get_context_data(**kwargs)
page_alt = Pages.objects.get(id=self.kwargs.get('pk_alt', ''))
context['page_alt'] = page_alt
return context
You will then be able to access the alternative model in your template using {{ page_alt }}
If you need two arguments in the url try this:
url(r'^page/(?P<pk_1>[0-9]+)/subpage/(?P<pk_2>[0-9]+)$', PageDetails.as_view(), name='page-details'),
Then you have pk_1 and pk_2 available as kwargs

Passing 2 variables through django url

I try to pass 2 variables through url config
url.py
url(r'^essays/(?P<category>[-\w]+)/(?P<slug>[-\w]+)/$', views.EssayDetailView.as_view(), name='essay_view'),
view.py
class EssayDetailView(DetailView):
model = Essay
def get_context_data(self, **kwargs):
context = super(EssayDetailView, self).get_context_data(**kwargs)
context['category'] = Category.objects.get(slug=self.kwargs['category'])
return context
but if I use in template url tag like this
{{essay.title}}
I've error NoReverseMatch. With 1 parameter it works right. For example url:
url(r'^(?P<slug>[-\w]+)/$', views.ArticleDetailView.as_view(), name='article_view'),
how can i pass 2 variables to generic view? Or should I wright my own view method?
It was mistyping in
def get_absolute_url(self):
return reverse('articles:essay_view', args=[self.category.slug, self.slug])
now works tnx

Accessing get method data in Django Template

I have read docs and other things, tried many tuts but still no luck. What I am trying to achieve is to show a custom error message.
I have this: /?message=success
And want to access this data in my Django template
class mysite(TemplateView):
template_name = 'index.html'
def get_context_data(self, **kwargs):
context = super(mysite, self).get_context_data(**kwargs)
return context
def get(self, request, *args, **kwargs):
return super(mysite, self).get(request, *args, **kwargs)
How I am accessing it in my template file:
{{ message }}
This gives no output. What I need is success to be read. Then I will do a conditional block on its base.
You can add message to the template context by changing your get_context_data method to
def get_context_data(self, **kwargs):
context = super(mysite, self).get_context_data(**kwargs)
context['message'] = self.request.GET.get('message', '') # default to empty string if not in GET data
return context
Then access message in your template with:
{{ message }}
Alternatively, make sure you are using the request template context processor, to make the request object available in your templates.
Then in your template, you can access the GET data with:
{{ request.GET }}
and the message parameter with:
{{ request.GET.message }}

Categories