I'm using jinja for this flask app that I'm making and when ever i run it jinja2.exceptions.UndefinedError: 'user' is undefined appears - jinja2

So, what I am using it for is to render a template that I have.
Here is the code it has a problem with.
`
#views.route('/')
def home():
return render_template("home.html")
`
By the way this is the code in home.html
{% extends "base.html" %} {% block title %}Home{% endblock %} {% block content
%}
<h1 align="center">Notes</h1>
<ul class="list-group list-group-flush" id="notes">
{% for note in user.notes %}
<li class="list-group-item">
{{ note.data }}
<button type="button" class="close" onClick="deleteNote({note,id })"
<span aria-hidden="true">×</span>
</button>
</li>
{% endfor %}
</ul>
<form method="POST">
<textarea name="note" id="note" class="form-control"></textarea>
<br />
<div align="center">
<button type="submit" class="btn btn-primary">Add Note</button>
</div>
</form>
{% endblock %}
I run it. It gives me a link to website. Everything there, No. I run it. It gives me a link to website. And then jinja2.exceptions.UndefinedError: 'user' is undefined is on my website

Check your html file, you may accidently got a variable called user in there

Related

sending data from a "form action" to a views function in django

How are you community, I'm a little confused between my newbies and lack of knowledge, I'm working on a small project in Django and I'm also trying to send data from a form action in the html to another view function but I'm not understanding it well How does this work and on top of that I have to send several data not just one and it confuses me even more, I have the following HTML:
{% extends "base.html" %}
{% block content %}
<main class="container">
<div class="row">
<div class="col-md-10 offset-md-1 mt-5">
<form action="/interface/" method="POST" class="card card-body">
<h1>Interface</h1>
<h4>{{ error }}</h4>
<select name="dv">
<option selected disabled="True">Select Device</option>
{% for device in devicess %}
<option>{{ device.id }} - {{ device.name }}</option>
{% endfor %}
</select>
<br>
{% csrf_token %}
<br>
<button type="submit" class="btn btn-primary">Send</button>
</form>
<br>
{% for interface in interfaces %}
<section class="card card-body">
<h2>{{interface.Interface}}</h2>
{% if interface.Description == "" %}
<p class="text-secondary">none description</p>
{% else %}
<P class="text-secondary">{{interface.Description}}</P>
{% endif %}
<form action= "{% url 'send_description' %}"method="POST">
{% csrf_token %}
<input type="text" name="command" class="form-control" placeholder="Change description">
<br>
<button type="submit" class="btn btn-primary align-content-lg-center">Send change</button>
</form>
<br>
{% if interface.Status == "up" %}
<p class="text-secondary">Interface State: 🟢 Free</p>
{% else %}
<p class="text-secondary">Interface State: 🔴 Used</p>
{% endif %}
</section>
<br>
{% endfor %}
</div>
</div>
</main>
{% endblock %}
and aesthetically to better understand the first POST executed like this:
So far everything is perfect, if I press the "Send change" button it redirects me perfectly, the problem is that I need to send various data such as device.id, interface to that function that I am executing in the action= "{% url 'send_description' %} .Interface and also the content of the input that is inside the same form. Could you give me a hand or a guide on where to find the best way?
regards!
Let me start by saying that this would work way better with JS and AJAX. But, to answer your question, data is passed via Django http request object, in your case, since you have several different forms, it is possible to pass this data by adding a hidden field inside each form with the desired value:
<input type="hidden" name="interface" value="{{ interface.id }}">
And fetch this value form the request object in the view:
interface = request.POST.get('interface')
A full example:
models.py
class Device(models.Model):
name = models.CharField(max_length=100)
class Interface(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length=100, default='interface description field')
status = models.BooleanField(default=False)
device = models.ForeignKey(Device, on_delete=models.CASCADE, related_name='interfaces')
views.py
from django.core.exceptions import ObjectDoesNotExist
def list_interfaces(request):
devices = Device.objects.all()
interfaces = None
try:
selected_device = Device.objects.get(id=request.POST.get('dv'))
interfaces = selected_device.interfaces.all()
except ObjectDoesNotExist:
selected_device = Device.objects.all().first()
if selected_device:
interfaces = selected_device.interfaces.all()
else:
selected_device = None
context = {
'devices': devices,
'selected_device': selected_device,
'interfaces': interfaces
}
return render(request, 'list_device_interfaces.html', context)
def send_description(request):
command = request.POST.get('command')
device = request.POST.get('seleted_device')
interface = request.POST.get('interface')
print(f'command: {command}')
print(f'device_id: {device}')
print(f'device_id: {interface}')
return redirect('core:list-device-interfaces')
urls.py
from core import views
from django.urls import path
app_name = 'core'
urlpatterns = [
path("list/device/interfaces/" , views.list_interfaces, name="list-device-interfaces"),
path("send/description/" , views.send_description, name="send-description"),
]
list_device_interfaces.html
{% extends "base.html" %}
{% block content %}
<main class="container">
<div class="row">
<div class="col-md-10 offset-md-1 mt-5">
<form action="{% url 'core:list-device-interfaces' %}" method="POST" class="card card-body">
{% csrf_token %}
<h1>Device</h1>
<h4>{{ error }}</h4>
<select name="dv">
<option selected disabled="True">Select Device</option>
{% for device in devices %}
<option value="{{ device.id }}" {% if device.id == selected_device.id %} selected {% endif %}>{{ device.id }} - {{ device.name }}</option>
{% endfor %}
</select>
<br>
<br>
<button type="submit" class="btn btn-primary">Send</button>
</form>
<br>
<hr>
<h2>Interfaces</h2>
{% for interface in interfaces %}
<section class="card card-body">
<h2>{{interface.name}}</h2>
{% if interface.description == "" %}
<p class="text-secondary">none description</p>
{% else %}
<P class="text-secondary">{{interface.description}}</P>
{% endif %}
<form action= "{% url 'core:send-description' %}"method="POST">
{% csrf_token %}
<input type="text" name="command" class="form-control" placeholder="Change description">
<input type="hidden" name="seleted_device" value="{{ selected_device.id }}">
<input type="hidden" name="interface" value="{{ interface.id }}">
<br>
<button type="submit" class="btn btn-primary align-content-lg-center">Send change</button>
</form>
<br>
{% if interface.status %}
<p class="text-secondary">Interface State: 🟢 Free</p>
{% else %}
<p class="text-secondary">Interface State: 🔴 Used</p>
{% endif %}
</section>
<br>
{% endfor %}
</div>
</div>
</main>
{% endblock %}

I cannot go to the page I want

Hello I have a post blog where I have a homepage with posts and if you click on it you are redirected to the post_detail page. Now I want the users to allow to delete their comments which I achieved but I want them to stay on the same post_detail page. I could not come over it and hope that someone can help me. Thanks in advance.
post_detail.html
<div class="container">
<br>
<h1 style="text-align:center;">{{post.post}} </h1>
<p style="font-size:small;text-align:center;">{{post.created_on}}</p>
<button type="button" class="btn btn-secondary float-right" data-toggle="modal" data-target="#exampleModal" data-whatever="#mdo">Yorum At</button>
<br>
<br>
<br>
{% for i in commentmodel_list%}
<h4 >{{i.comment}}</h4>
{% if i.author_security == user%}
<a style="float:right;color:red;"href="{% url 'forum:delete' slug=post.slug comment_id=i.id %}"><i class="fas fa-minus-circle"></i></a>
{% endif %}
{% if i.author is none %}
<p style="font-size:small;">Anonim | {{i.created_on}}</p>
{% else%}
<p style="font-size:small;"><a style="text-decoration:none;" href="#">#{{i.author}}</a> | {{i.created_on}}</p>
{% endif %}
<hr>
<br>
{% endfor %}
</div>
urls.py
app_name='forum'
urlpatterns=[
path('', views.PostList.as_view(), name='post'),
path('<slug:slug>/', views.PostDetail.as_view(), name='post_detail'),
path('delete/<slug:slug>/<comment_id>/',views.delete_post,name='delete')
]
views.py
def delete_post(request,slug=None,comment_id=None):
comment_delete=Comment.objects.get(id=comment_id)
comment_delete.delete()
post = Post.objects.get(slug=slug)
return redirect('forum:post_detail', slug= post)
I would highly recommend to delete the comments via submitting a POST request with CSRF token, otherwise it's prone to CSRF attack. When you'll be submitting the form, you can add there an input with a value representing the current page which you'll redirect to afterwards. Pseudocode:
<form action="{% url 'forum:delete' slug=post.slug comment_id=i.id %}"
method="POST">
{% csrf_token %}
<input type="hidden" name="current_post" value="{{ post.slug }}">
<input type="submit>
</form>
view:
def delete_post(request, comment_id=None):
Comment.objects.filter(id=comment_id).delete()
return redirect('forum:post_detail', slug= request.POST['current_post'])
It's not obvious if by "I want them to stay on the same post_detail page" you mean that you dont want to perform the redirect in browser and you'd rather delete it via ajax. If that's the case, please check the Django documentation about AJAX request with CSRF, as there's an example how to do exactly that.

Getting "|as_crispy_field got passed an invalid or inexistent field" with a field that exists

I'm using django-crispy-forms, and have run across an issue where one of my form fields won't render. The error I'm getting is telling me that the form field is either inexistent or invalid, but it definitely exists, and it's pretty much copied from other form fields that work properly on other pages. So I don't really see how it is either of those.
Here's the relevant code:
forms.py
class AddSkillsForm:
all_skills = forms.CharField(
label="Skills ",
widget=forms.HiddenInput(),
required=False
)
view.html
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block title %}{{ course.name }}{% endblock %}
{% block content %}
{% include 'course/partial/nav.html' with course=course active_breadcrumb=None %}
<div class="card">
<div class="card-header">
{% include 'course/partial/menu.html' with course=course %}
</div>
<div class="card-body">
<dl class="row">
<dt class="col-sm-3">Name:</dt>
<dd class="col-sm-9">{{ course.name }}</dd>
<dt class="col-sm-3">Number of Students:</dt>
<dd class="col-sm-9">{{ total_students }}</dd>
<dt class="col-sm-3">Sections:</dt>
<dd class="col-sm-9">
{% for section in sections %}
<p>{{ section.name }}</p>
{% endfor %}
</dd>
</dl>
</div>
<div class="card-body">
<p>First, you'll need to import any existing students and groups from Canvas</p>
<a class="btn btn-primary" href="{% url 'import_students_and_groups' course.id%}">
Import Students and Groups from Canvas
</a>
<div id="skill_box">
<p>If you would like to use self-reported student skills to form teams, you can define the skills relevant to this course here</p>
<div id="skill_container"></div>
<button type="button" class="btn btn-primary">Add Skill</button>
<form method="post">
{% csrf_token %}
{{ form.all_skills|as_crispy_field }}
<button type="submit" class="btn btn-primary"></button>
</form>
</div>
</div>
</div>
{% endblock %}
In case anyone comes across the same issue, I did find the solution.
In forms.py, each form must take forms.Form as a parameter in order to function properly with django-crispy-forms. I had a different form that I wasn't accessing regularly that also did not do this, so I didn't realize that all the functional forms did. Here's the revised code
forms.py
class AddSkillsForm:
all_skills = forms.CharField(
label="Skills ",
widget=forms.HiddenInput(),
required=False
)

Change button wording depending on url

I am looking to change the wording of a button depending on a url path. I have tried to use some {% if blocks %} but unable to get it to work.
I have tried to the following if block
<div class="form-group">
{% if url == 'http://localhost:8000/client/<int:pk>/update/' %}
<button class="btn btn-outline-info" type="submit">Update</button>
{% else %}
<button class="btn btn-outline-info" type="submit">Post</button>
{% endif %}
</div>
This is my url in my apps urls.py
path('client/<int:pk>/update/', PostUpdateView.as_view(), name="post-update"),
Any help would be handy.
You can store the url in a temporary variable and then use it against if condition.
In django template:
{% url 'post-update' pk=1 as the_url %}
{% if request.path == the_url %}
<button class="btn btn-outline-info" type="submit">Update</button>
{% else %}
<button class="btn btn-outline-info" type="submit">Post</button>
{% endif %}
Here request.path is your current url.

How to add a button to nav-bar?

How can I add another button/dropdown to the navbar in sonata admin listing template for my MapAdmin class?
I just want this button in one admin class.
You have to override the default template (layout: 'SonataAdminBundle::standard_layout.html.twig') with your own in coding your logique here
Here is an extract of existing code :
{% block sonata_admin_content_actions_wrappers %}
{% if _actions|replace({ '<li>': '', '</li>': '' })|trim is not empty %}
<ul class="nav navbar-nav navbar-right">
{% if _actions|split('</a>')|length > 2 %}
<li class="dropdown sonata-actions">
{{ 'link_actions'|trans({}, 'SonataAdminBundle') }} <b class="caret"></b>
<ul class="dropdown-menu" role="menu">
{{ _actions|raw }}
</ul>
</li>
{% else %}
{{ _actions|raw }}
{% endif %}
</ul>
{% endif %}
{% endblock sonata_admin_content_actions_wrappers %}
It requires adding a custom action and overriding a certain template. You can follow the documentation on symfony.com.
Read up to the following code block:
{# src/AppBundle/Resources/views/CRUD/list__action_clone.html.twig #}
<a class="btn btn-sm" href="{{ admin.generateObjectUrl('clone', object)}}">clone</a>
I have just come across with the same problem. I am using Symfony 3.4.6 and Sonata Admin Bundle 3.9.1.These are the steps I've followed:
1. Find the standard template which lives in:/vendor/sonata-project/admin-bundle/src/Resources/views/standard_layout.html.twig.
2. Go to /app/config/config.yml and under the key sonata_admin, you just override that template as shown below
sonata_admin:
templates:
# Layout
layout: '#MyBundle/Admin/Default/Layout/standard_layout.html.twig'
3. Within your newly created template (standard_layout.html.twig) make sure you have extended the sonata standard template file like so : {% extends '#SonataAdmin/standard_layout.html.twig' %}. Now, all you need to do is override any block you want from the original sonata template file as I described in point 1, in my case I've just overridden the block tab_menu_navbar_header and Added my custom button like so:
{% block tab_menu_navbar_header %}
{% if _navbar_title is not empty %}
<div class="navbar-header">
<a class="navbar-brand" href="#">{{ _navbar_title|raw }}</a>
{% if object.state is defined and object.state is not null and object.state is same as('finished') %}
<button type="button" class="btn btn-info" style="margin-top: 10px;">
<i class="fa fa-check-square" aria-hidden="true"> History</i>
</button>
{% endif %}
</div>
{% endif %}
{% endblock %}