Authentication request in template isnt getting recognized

I’m using a template tag to load my header element into every page I have. In this header template I’m using the following code

                    {% if user.is_authenticated %}
                        <a class="btn btn-primary display-4" href="{% url 'home:profil' %}">{{ username }}</a>
                    {% else %}
                        <a class="btn btn-sm btn-black display-4" href="{% url "home:login" %}">Login</a>
                    {% endif %}

The implementation of this templatetag is working fine but the Backend doesnt seem to work.
The system doesnt check the authentication and doesnt see the {{username}} context allthough I passed it in the context of the view.

This is my register file of the tag:

from django import template

register = template.Library()


@register.inclusion_tag('partials/header2.html')
def header2(element):
    return {'element': element, }

My view:

def profil_view(request):
    packet = Account.objects.get(user=request.user)
    username= packet.username
    context = {
        'username': username,
    }
    return render(request, 'profil.html', context)

and my template:

<head>{% load static %}
</head>
<body>
  {% load header2_template %}
  {% header2 element %}
</body>

Thanks for all your help!

Your template being included is being passed a context with the key ‘element’ and the value of the parameter being passed to it. So, if I’m reading this correctly, your template would need to check / render entries of the form element.username. Additionally, it doesn’t get the full context passed to it by default, which means that template isn’t going to have the user object available to it - that’s the purpose for the takes_context parameter.

See the docs and examples at Inclusion tags for more details.

I’ve now read the docs about the takes_contextparameter.

This is my updated code:

template:

<head>{% load static %}
</head>
<body>
  {% load header2_template %}
  {% header2 context %}
</body>

Register File:

from django import template

register = template.Library()


@register.inclusion_tag('partials/header2.html')
def header2(context):
    return {
        "context": context, 
        "user": context["user"]
            
            }

Now I caused the following error:

string indices must be integers, not 'str'

in this line:

        "user": context["user"],

Guess its just a formatting error, but I cant help myself here.

Where are you passing a variable named “context” into this view? (I don’t see where you have a key named “context” in your context.)

“Context” is the parameter of my inclusion tag function. I’m passing the whole header2.html file to the template with it.

With {% header2 context %} I’m inserting this code into my tempate.

My question now would be how I pass my user value to the template to make the authentification work.

I tried it with:

"user": context["user"],

But I dont get to test it because the error above is stopping me from continueing

Yes, that means you need to pass something to it.

Well, kinda, but the issue is, you’re not passing anything named context into this template. You’re trying to use a variable named context, but there isn’t one being passed in the context that is rendering this template.

Let’s take a step back for a moment. If you were to write:
{{ a_var }}
You would need to have a key named a_var in your context that you are passing to the rendering engine.

(e.g., return render(request, 'profil.html', {'a_var': some_variable}) )

This is no different than if you were to write:
{{ some_tag a_var }}
In this case, some_tag is the custom tag, and a_var is the variable that you are passing to this tag.

However a_var still needs to be passed into the rendering engine in the context.

So, you have a template:

This needs to be defined in the context being passed to the render function so that it can be passed as the parameter to the header2 tag.

Okay, I now understand what my mistake is when it comes to pass a specific variable to the template.

But how can I pass the whole html file for this header template as it was before?

I mean I already did, I passed the complete header template to the template without passing it in the views.py like you said above

register:

@register.inclusion_tag('partials/header2.html')
def header2(element):
    return {
        "element": element, 

            }

template:

  {% load header2_template %}
  {% header2 element %}

view:

@login_required(login_url='home:login')
def profil_view(request):

    return render(request, 'profil.html')

To this exiting, working code I want to add the specific context like the user element but still deliver the element template. I read in the docs that the context parameter needs to be in first place to make it work. But as I tried that like in my response before the code caused errors because it says I have to pass “element” in the views aswell. So my question now would be how I pass the header2.html file in the views to the profil.html

I’m sorry, you’ve completely lost me with what you’re trying to describe here.

From what I can tell from what you’ve written, your original post at the top is a lot closer to what you’re trying to do here, but that’s based on my not being able to understand what you think you’re trying to do at this point.

You don’t pass templates to templates.

You pass templates to rendering engines to be rendered.

You also pass a context to the rendering engine to supply data to be rendered.

I suggest you go back to what you had in your original post and move forward from there.

So I’ll try to explain to you again what I mean.

With the bottom version of my code I set the header HTML code which is in my external header2.html file. The inclusion tag is the placeholder which passes my header with the parameter element.

For this current, existing and functioning version, I want to add an authentication in the HTML inclusion tag template. To do this, I have to fit the context into the template as discussed. If I do that, my element parameter flies out of the inclusion tag and my header is no longer working.

I’m now trying to find a method to give both my header to the template and the user element to make the query in the header.

Do you understand roughly what I mean?

Unfortunately, I don’t know which “this” version you’re talking about.

From what I can see here, your very first version in the original approach is the closest to what you want to do.

Starting with the code in the original post, in your view, you are defining the context as:

Add the user object as another key to this dict.
Example:

  context = {
    'username': username,
    'user': request.user
}

Then, in your header2.html template being rendered by header2, you should find that you can access these as element.username and element.user.<whatever>.

Now, since you probably have the default auth context processor, you don’t need to pass this in if you tell your tag to use the existing context:

@register.inclusion_tag('partials/header2.html', takes_context=True)
def header2(element):
    return {
        'username': element['username'],
        'user': element['user'] 
 }

I somehow can’t relate to what you’re saying. You point out that I want to integrate individual values ​​into the template of the inclusion tag, but not how I can correctly integrate the entire tag on the page.

I’ve designed it the way you said.

My Template header2.html which I use for the inclusion tag (this should be implemented in the page at the end because its my navar):

<head>{% load static %}</head>
<section data-bs-version="5.1" class="menu menu1 cid-tgVqtA58dw" once="menu" id="menu01-2">
    
    <nav class="navbar navbar-dropdown navbar-fixed-top navbar-expand-lg">
        <div class="container">
            <div class="navbar-brand">
                <span class="navbar-logo">
                    <a href="{% url "home:index" %}">
                        <img src="{% static 'assets/images/unbenannt-2-236x80.png' %}" alt="BudgetMate" style="height: 3rem;">
                    </a>
                </span>
                
            </div>
            <button class="navbar-toggler" type="button" data-toggle="collapse" data-bs-toggle="collapse" data-target="#navbarSupportedContent" data-bs-target="#navbarSupportedContent" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
                <div class="hamburger">
                    <span></span>
                    <span></span>
                    <span></span>
                    <span></span>
                </div>
            </button>
            <div class="collapse navbar-collapse" id="navbarSupportedContent">
                <ul class="navbar-nav nav-dropdown" data-app-modern-menu="true"><li class="nav-item"><a class="nav-link link text-black show text-primary display-7" href="{% url "home:index" %}" aria-expanded="false">HOME</a></li>
</ul>
                
                <div class="navbar-buttons mbr-section-btn">
                    {% if user.is_authenticated %}
                        <a class="btn btn-primary display-4" href="{% url 'home:profil' %}">{{prename}}</a>
                    {% else %}
                        <a class="btn btn-sm btn-black display-4" href="{% url "home:login" %}">Login</a>
                    {% endif %}
                </div>
            </div>
        </div>
    </nav>
</section>

As you can see I’m working with the values user and prename there.

In my Python File I’m returning these values:

from django import template

register = template.Library()


@register.inclusion_tag('partials/header2.html', takes_context=True)
def header2(context):
    return {
        'prename': context['prename'],
        'user': context['user'] 
            }


And in my views.py I’m filling the values with content

@login_required(login_url='home:login')
def profil_view(request):
    packet = Account.objects.get(user=request.user)
    prename = packet.prename
    surname = packet.surname
    User = get_user_model()
    user = User.objects.get(id=request.user.id)
    email = user.email
    context = {
        'prename': prename,
        "surname": surname,
        "email": email,
        "user": user
    }
    return render(request, 'profil.html', context)

In my template at the end (profil.html) I still have this code

  {% load header2_template %}
  {% header2 context %}

In my understanding the context variable was to deliver the navbar template from the inclusion tag to the template in the end. But you’re saying that I need to name the vars like prename in the template so I can display them. But I want to display them in the template from the inclusion tag because there is the line of code where I need it.

With this version I get this error

'header2' received too many positional arguments

Which makes sense because we declared 2 vars which are getting returned on the header2 function.

SO MY FINAL QUESTION IS

How can I manage delivering my template header2.html into my template profil.html including the vars user and prename in the header2.html via my inclusion tag.

That is not correct.

The purpose of the header2 tag is to cause a tag to be executed.

The purpose of the context parameter is to pass a parameter named context to that function.

However, you still do not have a key named context in the context that you are using in this template.

Again, if you were to try and render {{ context }} in a template, you would not see anything with the context you have defined. The only variables you have defined in your context are ‘prename’, ‘surname’, ‘email’, and ‘user’. So, {{ prename }} would work. Also, each of {{ surname}}, {{email}}, and {{user}} would work. For the same reasons {% <anytag> context %} is not going to work.

However, as you will see below, this ends up being irrelevent.

Side note: Technically, neither of those tags (the load or header2) have anything specifically to do with a template - the first causes the code for the tag to be loaded and the second is just a reference to a function. (It’s fundamentally no different than any other tag - many of which do not themselves result in the rendering of text in the html being created.)

Now, in the tag definition, this decorator:

is saying that this tag function is going to render a template

Good hypothesis, but the wrong conclusion.

This was my fault. I missed another change that is required.

When you use takes_context=True, that means you do not supply a parameter in the tag - it becomes {% header2 %}. This error is cause by the combination of the takes_context parameter with the context parameter in the tag.

Finally, the return value from the tag function is the context to be used to render the identified template. As a result of using the takes_context=True, you’re getting passed a context. You don’t actually need to perform any operations on it. You could define your function as:

@register.inclusion_tag('partials/header2.html', takes_context=True)
def header2(context):
    return context

This will make the complete context available to the rendering of header2.html

You want to change your perspective here. This is not the way to think about it. This tag is going to cause header2 to be rendered, with the result added to profil.html template at that point.