Django How to pass username in a predefined template - python

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.

Related

How can I open a page with only one django model object's info after clicking it's ImageField on another page?

I am displaying django models on one of my website's pages. When I press one's ImageField on the page, I want it to open another page including only that one object. How do I do that ?
I thought about using the filter method in my views.py for filtering through my objects and finding that exact one, but I don't know what arguments to use.
Any ideas? (I am a beginner in django)
VIEWS.PY
from django.shortcuts import render
import requests
from . import models
def index(request):
return render(request, 'base.html')
def new_search(request): ********NOT IMPORTANT (I THINK)********
search = request.POST.get('search')
models.Search.objects.create(search=search)
objects = models.Object.objects.all()
results = objects.filter(name__contains=search).all()
args = { 'results': results }
return render(request, "my_app/new_search.html", args)
def individual_page(request):
link = request.GET.get('object-link')
objects = models.Object.objects.all()
return render(request, "my_app/individual_page.html")
MY TEMPLATE
{% extends "base.html" %}
{% block content %}
{% load static %}
<h2 style="text-align: center">{{ search | title }}</h2>
<div class="row">
{% for result in results %}
<div class="col s4">
<div class="card medium">
<div class="card-image">
<a name="object-link" href="{% url 'individual_page' %}"><img src="{{ result.image.url }}" alt=""></a>
</div>
<div class="card-content">
<p>{{result.name}}</p>
</div>
<div class="card-action">
View listing: Price TEST
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock %}
So, the thing I want to do is: when I press the anchor tag that includes the image, I get redirectioned to another page which contains only that one object's info.

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

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/

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!

Django authentication system

i'm using the django built in authentication system and in my login template i have this code :
login.html:
{% block title %}Login{% endblock %}
{% block content %}
<h2>Login</h2>
{% if user.is_authenticated%}
you are already logged in
{% else %}
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
</form>
{% endif %}
{% endblock %}
but what i really want to do is to redirect the user to the home page if he tries to access login page while already logged in, but i am new to django so i don't know how to do that.
For django>=1.11 you can set redirect_authenticated_user parameter to True in its url in url_patterns to do the redirect, like this:
from django.contrib.auth import views as auth_views
urlpatterns = [
url(r'^login/', auth_views.LoginView.as_view(redirect_authenticated_user=True), name='login'),
]
read the document for more information.
and also set LOGIN_REDIRECT_URL in your setting file to your index url or its name:
LOGIN_REDIRECT_URL = '/index/'
In your `settings.py' add this:
LOGIN_REDIRECT_URL = 'index'
if the url name of your index is 'index', else put the correct url name
You can do it in your views.py file.
def login(request):
if request.method =="get":
if request.user.is_authenticated:
return render(// youre code)

Clean url in django app. without ?page=1 pattern

I want to have my url pattern like the below pattern:
host:8000/archive/2/
I define page_kwarg in my view but I still receive: host:8000/en/2
Code form main url.py file:
url(_(r'^archive'), include('events.urls_archive', namespace='archive')),
start edit1
and link form main site to my app:
<a href="{% url 'archive:list' %}" title="{% trans 'Archive' %}">
{% trans 'Archive' %}
</a>
end edit1
start edit2
This is the url in my app urls_archive.py:
urlpatterns = [
url('^/(?P<page>\d+)/$', ArchiveListView.as_view(), name="list"),
url('^/(?P<slug>[-\w]+)/(?P<pk>\d+)$', ArchiveDetailView.as_view(), name="detail"),
]
end edit2
The code for my view:
class ArchiveListView(ListView):
model = Booking
queryset = Booking.objects.filter(period__type='archive').order_by('-date_start')
paginate_by = 80
page_kwarg = 'page'
Here is my template code:
{% if is_paginated %}
{% if page_obj.has_previous %}
<h4>Previous</h4>
{% endif %}
<span class="arrow header"><h4>Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}</h4></span>
{% if page_obj.has_next %}
<h4>Next</h4>
{% endif %}
{% endif %}
Please provide any help.
Thanks.
page_kwarg sets the key that the page number is passed in as. It doesn't affect how it is used in the page. For some reason, you are outputting that directly as /{{ page_obj.previous_page_number }}, which resolves to just /2. You should output it in the same format as it is passed in:
?page={{ page_obj.previous_page_number}}
Edit
If you want your page number to be specified as part of the path arguments, you should use the url tag, like any other URL:
{% url 'archive' page=page_obj.previous_page_number %}

Categories