How to send object from detail view to another view in Django? - python

I have a detail view that uses a Quiz object to display data stored in that object, like title and author. I want to have a button that links to a new page that displays different data from the same object. I don't know how to pass this data/object.
I can render the view and pass it the context of a specific quiz using an id but I want the id to change to be the id of the object from the initial page.
#assessement view
def assessment(request):
context = {
'quiz':Quiz.objects.get(id=1),
}
return render(request, 'quiz_app/assessment.html', context)
#detailview template for quiz
{% extends "quiz_app/base.html" %}
{% block content %}
<article class="quiz-detail">
<h1>{{ object.title }}</h1>
<h2>{{ object.question_amount }} Questions</h2>
<a class="btn" href="{% url 'quiz-assessment' %}">Start Quiz</a>
</article>
{% endblock content %}
#assessment template
{% extends "quiz_app/base.html" %}
{% block content %}
<h2>Assessment</h2>
<h2>Title is {{ quiz.title }}</h2>
{% endblock content %}

Then you should make another view for url quiz-assessment and pass the quiz pk as you did above in your assessment view.
def quiz_assessment(request,pk):
quiz = Quiz.objects.get (pk=pk)
return render (request,'assessment_template', {'quiz':quiz}
And in your url,pass the quiz id like this:
path ('<int:pk>/quiz/assessment /',views.quiz_assessment,name='quiz_assessment')
And in your template you can give url like this:
< a class="btn" href="{% url 'quiz_assessment' object.pk %}>

As suggested in the comments by #Robin Zigmond, you can do like this.
#assessement view
def assessment(request, qid):
context = {
'quiz':Quiz.objects.get(id=qid),
}
return render(request, 'quiz_app/assessment.html', context)
In the HTML file
#detailview template for quiz
{% extends "quiz_app/base.html" %}
{% block content %}
<article class="quiz-detail">
<h1>{{ object.title }}</h1>
<h2>{{ object.question_amount }} Questions</h2>
<a class="btn" href="{% url 'quiz-assessment' qid=object.id %}">Start Quiz</a>
</article>
{% endblock content %}
and in your urls.py change as:
path('quiz_asswssment/?P<int:qid>/', views.assessment, name="quiz_assessment")

Besides, what SammyJ has suggested, You can use the django sessions library or the django cache framework. You can temporarily store the information you need for the next view and access it whenever you want to.
In what Sammy J had suggested, you will always to have make sure that the queryset is passed in the context, otherwise it will not be rendered.
def assesment(self, request, id):
q = Quiz.objects.get(pk=id)
request.session["someData"] = q.name
request.session["qAmount] = q.amount
In your template file
<p>The title is : {{request.session.title}} and the amount is {{request.session.qamount}}
Note: Django sessions do not allow you to set a queryset as a session record, for that, you can use Django Cache framework.
Example
from django.core.cache import cache
cache.set('quiz', q)
getting cache -> cache.get('quiz')
Sessions framework docs : https://docs.djangoproject.com/en/2.2/topics/http/sessions/
Cache framework docs: https://docs.djangoproject.com/en/2.2/topics/cache/

Related

Django How to pass username in a predefined template

I created a templates for header/footer and imports, if I want to acess the username in my header template I cant do that because it has no views. How can I pass the username to the header template?
header_template.py
from django import template
register = template.Library()
#register.inclusion_tag('home/partials/header.html')
def header(element):
return {'element': element, }
Import in Template
{% load header_template %}
{% header context %}
Usage in the template:
{% if user.is_authenticated %}
<a class="btn btn-primary display-4" href="{% url 'home:profil' %}">Profil</a>
{% else %}
<a class="btn btn-primary display-4" href="{% url 'home:login' %}">Login</a>
{% endif %}
Thanks for your help.
You can take context in your tag:
#register.inclusion_tag('home/partials/header.html', takes_context=True)
def header(context, element):
return context | {'element': element}
Read more here:
https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#inclusion-tags
My opinion, you are don't need this, The cause for every new tag in template - a wrong logic.

In Django, how to implement boilerplate HTML variables with Dynamic URLs used in templates and DB objects?

In Django, in my DB I've created string variables containing boilerplate HTML with dynamic URLs, and I can't quite get them to work in my templates.
I'm using render_as_template (https://github.com/danielrozenberg/django-render-as-template/blob/master/render_as_template/templatetags/render_as_template.py) so the dynamic URLs work. I tried custom template tags, but when I use those with render_as_template, it fails to load.
I then tried a custom context processor. I created two functions in the context processor, one for hyperlinks, and one for tooltips. I got the tooltips processor to work, but I can only reference them in the template via their number in the auto-generated dict from the queryset.
I did the same with the hyperlink processor, then tried modifying it to use string keys instead of integers, but it doesn't load all of the field. I must be missing something.
custom_tags.py
from django import template
register = template.Library()
#register.simple_tag
def rdo_hyper():
value = Boilerplate.objects.filter(name='RDO').values_list('hyperlink',flat=True)
return value[0]
# It's only going to return one field.
# Expected output: <a href="{% url 'guides:rdo' %}" target=”_blank” rel=”noopener noreferrer”>Foobar</a>
# tried a non-DB version, just in case
#register.simple_tag
def rdo_hyper2():
value = "<a href=\"{% url \'guides:rdo\' %}\" target=\”_blank\” rel=\”noopener noreferrer\”>Foobar</a>"
return value
# Expected output: <a href="{% url 'guides:rdo' %}" target=”_blank” rel=”noopener noreferrer”>Foobar</a>
custom_context.py
from myapp.apps.wizard.models import Boilerplate
def boilerplate_hyperlink_processor(request):
boilerplate_hyper = {
"foo": Boilerplate.objects.filter(name='Aftermarket').values_list('hyperlink',flat=True),
"bar": Boilerplate.objects.filter(name='Sights').values_list('hyperlink',flat=True)
}
return {'boilerplate_hyper': boilerplate_hyper}
# Expected output of boilerplate_hyper.foo:
#<a href="{% url 'guides:aftermarket' %}" target=”_blank” rel=”noopener noreferrer”>Aftermarket Support</a>
#
# Expected output of boilerplate_hyper.bar:
# <a href="{% url 'guides:sights' %}" target=”_blank” rel=”noopener noreferrer”>Sights</a>
def boilerplate_tooltip_processor(request):
boilerplate_tooltip = Boilerplate.objects.values_list('tooltip',flat=True)
return {'boilerplate_tooltip': boilerplate_tooltip}
# Expected output of boilerplate_tooltip.0:
#<sup></sup>
template.html
{% load static %}
{% load custom_tags %}
{% rdo_hyper as rdo_hyper %}
{% rdo_hyper2 as rdo_hyper2 %}
{% load render_as_template %}
...
<html>
{% autoescape off %}
1. {% rdo_hyper %}
2. {{ rdo_hyper }}
3. {% rdo_hyper2 %}
4. {{ rdo_hyper2 }}
5. {% render_as_template rdo_hyper %}
6. {{ boilerplate_hyper.foo }}
7. {% render_as_template boilerplate_hyper.foo %}
8. {% render_as_template boilerplate_tooltip.0 %}
{% endautoescape %}
{# The hyperlink value is:
<a href="{% url 'guides:aftermarket' %}" target=”_blank” rel=”noopener noreferrer”>
Aftermarket Support</a> #}
</html>
In template.html, the following occurs:
Renders, but the dynamic URL fails.
Doesn't render the variable at all. Otherwise page loads fine.
Renders, but the dynamic URL fails.
Doesn't render the variable at all. Otherwise page loads fine.
Doesn't render the variable at all. Otherwise page loads fine.
Only renders "Aftermarket Support']>" instead of the full hyperlink field from the DB.
Throws this error:
TemplateSyntaxError:
In template <unknown source>, error at line 1.
Could not parse the remainder: '\'guides:aftermarket\'' from '\'guides:aftermarket\''
1 <QuerySet ['<a href="{% url \'guides:aftermarket\' %}" target=”_blank” rel=”noopener noreferrer”>Aftermarket Support</a>']>
Works fine.
It's great that {% render_as_template boilerplate_tooltip.0 %} works, but I would much rather reference variables in templates through a string key. After all, the ethos of Django's templating language is that its templates can be read and written by non-programmers. Any ideas?
I went back to trying custom tags and this seems to work:
custom_tags.py
#register.simple_tag(takes_context=True)
def rdo_hyper2(context):
value = "<a href=\"{% url \'guides:rdo\' %}\" target=\”_blank\” rel=\”noopener noreferrer\”>Foobar</a>"
rendered = context.template.engine.from_string(value).render(context)
return rendered
template.html
{% load custom_tags %}
...
{% rdo_hyper2 %}
When including {% rdo_hyper2 %} or other custom tags inside a DB field, I also have to use {% load custom_tags %} at the top of that field every time or else it throws:
Invalid block tag on line 12: 'rdo_hyper2'. Did you forget to register or load this tag?
Hopefully that's not resource intensive!

How to render data to a {% included a.html %} template in Django

I have a rank.html which is a publicly sharing template for many other templates through {% include rank.html %} method.
This template will display the 48 hours hot news base on the click number.
Here is the view.py:
def rank(self, request):
hot_news_48h = h_mostViewed(48, News, '-pv')
return render(request, "rank.html", {
'hot_news_48h': hot_news_48h,})
h_mostViewed(48, News, '-pv') is a function,that can fetch most viewed(clicked) post within 48 hours.It works.
Here is the rank.html:
<ul>
{% for hot_view in hot_news_48h %}
<li>
<a href="{% url 'news:news_detail' hot_view.pk %}" >
<img src="{{ MEDIA_URL }}{{ hot_view.image }}" >
</a>
<a href="{% url 'news:news_detail' hot_view.pk %}">
<h6>{{ hot_view.title }}</h6>
</a>
</div>
</li>
{% endfor %}
</ul>
Here is the url.py:
path('hot_news', views.rank, name="hot_news")
The problem is,I can only get the html ,but can't receive the data.
But if I give up {% include rank.html %} method and insert the rank.html's code directly inside each template which need this function, I can get the data.
Take new_detail.html template as an example:
Here is the view.py:
def newsDetailView(request, news_pk):
news = get_object_or_404(News, id=news_pk)
all_comments = NewsComments.objects.filter(news=news)
news.comment_nums = all_comments.count()
news.save()
News.objects.filter(id=news_pk).update(pv=F('pv') + 1)
hot_news_48h = h_mostViewed(48, News, '-pv')
relative_news = News.objects.filter(tag__id__in=news.tag.all()).exclude(id=news_pk)[:6]
return render(request, "news_detail.html", {
'news': news,
'all_comments': all_comments,
'hot_news_48h': hot_news_48h,
'relative_news': relative_news
})
Here is the urls.py:
path('-<int:news_pk>', views.newsDetailView, name="news_detail"),
So above,I directly inserted rank.html's code into new_detail.html and it works I can get the data.
My question is what should I do or correct,so that I can get the data in {% include rank.html %} method. Because {% include rank.html %} is simple and flexible.I don't want to repeat the same code in several same template.
Thank you so much for your patience!
How about this:
- Create a folder "templatetags" in your application and add a file "news_tags.py" or name it what you want. Then you can define the tags you need:
from django.template import Library
from your_app.models import your_model
register = Library()
#register.inclusion_tag('your_app/your_template.html')
def hot_news(num, order):
objects = News.objects.order_by(order)[:num]
result['objects'] = objects
return result
In your templates you then do the following:
{% load news_tags %}
{% hot_news 48 '-pv' %}
Then create a template as your already did and reference it in the inclusion tag. Then it should work properly.
If you want it to work for multiple models you can have a look at this: https://docs.djangoproject.com/el/2.1/ref/applications/
The apps framework allows you to fetch models from a string input.
I finally solved the issue by Creating custom context processor.https://www.youtube.com/watch?v=QTgkGBjjVYM

simple loop in rendered template django cms plugin

I want to loop data taken from database in rendered template. Using cms plugin.
I dont have problem looping data in html template. But if i use CMSPlugin to insert new app in placeholder, nothing shows.
If i run url localhost:port/test.html.I got input what i want. But rendered template doesnt loop data.
{% for post in posts %}
{{ post.firstoption }}
{% endfor %}
if I use code below, nothing shows in my rendered template. Values are passed in rendered template. Because, if i try {{instance.firstoption}} i get value shown in template. Problem is i cant loop data with tag instance.
{% for post in instance.posts %}
{{ post.firstoption }}
{% endfor %}
I also tried {% for post in instance.posts_set.all %}
and {% for post in instance.posts.all %}
cms_plugins.py
class pricing(CMSPluginBase):
model = mymodel
name = _("myplugin")
render_template = "template.html"
cache = False
def render(self, context, instance, placeholder):
context.update({'instance': instance})
return context
models.py
class mymodel(CMSPlugin):
firstoption = models.CharField(max_length=200)
def __str__(self):
return self.firstoption
It is probably because you need to call all on your posts
{% for post in instance.posts.all %}
{{ post.firstoption }}
{% endfor }

What is a good way to get the dynamic title of a page in Django?

I'm trying to customize a share on Twitter button and I'm using to this to share:
http://twitter.com/intent/tweet?status=[TITLE]+[URL]
I'm able to get the URL with {{ request.get_host }} and {{ request.path }}, but I can't seem to get the title working. Are there any request objects I can use to get the title of my current page title? Thanks.
The easiest way to do this is:
Insert the following code in your base.html
#base.html
{% block title %} {% endblock %}
and following in your index or any Html file with your title
#index.html
{% extends 'base.html'%}
{% block title %} My Page Title {% endblock %}
Place your context object key in double paranthesis.
Lets take am making a dynamic teacher's page in a school management system
#urls.py
path("teacher/<str:pk>/",views.teacher,name="teacher"),
The vew
#view
def teacher(request,pk):
teacher = Teacher.objects.get(id=pk)
context= {"teacher":teacher}
return render(request,'main/teacher.html',context)
The template
<title>{{teacher.fname}} Page</title>

Categories