I'm building a web app using the Django framework. I'm attempting to use some JavaScript to disable a button that users can press to submit a text-based review.
The JavaScript in the listing.js file looks as follows:
document.addEventListener('DOMContentLoaded', function () {
hide_submit_review_button();
});
// Hide the 'Submit Review'button until the user begins typing a review
// Prevent the user from typing more than 100 characters
function hide_submit_review_button() {
var submit_review_button = document.getElementById('submit-review-button');
if (submit_review_button !== null) {
document.getElementById('submit-review-button').disabled = true;
document.getElementById('review-contents').onkeyup = () => {
if ((document.getElementById('review-contents').value.length > 0 &&
document.getElementById('review-contents').value.length <= 100 )) {
document.getElementById('submit-review-button').disabled = false;
} else {
document.getElementById('submit-review-button').disabled = true;
}
};
}
}
In my listing.html file, I identify the review-contents and submit-review-button. Here's the code:
{% extends "layout.html" %}
{% load static %}
{% block body %}
{% if user.is_authenticated %}
<form action="{% url 'review' listing.id %}" method="POST">
{% csrf_token %}
<input type="text" class="form-control" name="review" id="review-contents" placeholder="Write a review...">
<input class="btn btn-primary mt-1" type="submit" id="submit-review-button" value="Submit Review">
</form>
{% endif %}
{% endblock %}
{% block script %}
{% if user.is_authenticated %}
{{ block.super }}
<script src="{% static 'listing.js' %}"></script>
{% endif %}
{% endblock %}
An example of a page where the button appears is: http://127.0.0.1:8000/listings/7
And, here is what the urls.py file looks like (if it matters):
urlpatterns = [
path('', views.index, name='index'),
path('listings/<int:listing_id>', views.listing, name='listing'),
]
Can anyone see why this button doesn't disable?
Thanks!
The problem resulted from not having the following in the header tag in the layout.html file:
{% block script %}
{% endblock %}
Related
I'm trying to create a way to export the HTML table to xlsx, but I have a large amount of data in the queries. So I need to use pagination with Paginator so the browser doesn't load the data all at once and end up causing TimeOut. But when applying the Paginator and exporting, it only exports what is on the current page. Any suggestions to improve this code, such as creating a loop so that it can export all pages?
View function:
def export_project_data(request, pk):
if str(request.user) != 'AnonymousUser': # só vai ter acesso se for diferente de AnonymousUser
individuals_list = Individual.objects.filter(Project=pk)
traps = Sample_unit_trap.objects.filter(Project=pk)
page = request.GET.get('page', 1)
paginator = Paginator(individuals_list, 1000)
try:
individuals = paginator.page(page)
except PageNotAnInteger:
individuals = paginator.page(1)
except EmptyPage:
individuals = paginator.page(paginator.num_pages)
path_info = request.META['PATH_INFO']
context = {
'individuals': individuals,
'pk': pk,
'traps': traps,
'header': 'export_project_data',
'path_info': path_info
}
return render(request, 'inv/index.html', context)
HTML paginator code:
<div class="table-div">
{% if individuals.has_other_pages %}
<ul class="pagination pagination-sm">
{% if individuals.has_previous %}
<li>«</li>
{% else %}
<li class="disabled"><span>«</span></li>
{% endif %}
{% for i in individuals.paginator.page_range %}
{% if individuals.number == i %}
<li class="active"><span>{{ i }} <span class="sr-only">(current)</span></span></li>
{% else %}
<li>{{ i }}</li>
{% endif %}
{% endfor %}
{% if individuals.has_next %}
<li>»</li>
{% else %}
<li class="disabled"><span>»</span></li>
{% endif %}
</ul>
{% endif %}
</div>
{% endif %}
Javascript html to xlsx code:
<script>
function html_table_to_excel(type)
{
var data = document.getElementById('data');
var file = XLSX.utils.table_to_book(data, {sheet: "Dados_Ecológicos"});
XLSX.write(file, { bookType: type, bookSST: true, type: 'base64' });
XLSX.writeFile(file, 'file.' + type);
}
const export_button = document.getElementById('export_button');
export_button.addEventListener('click', () => {
html_table_to_excel('xlsx');
});
</script>
It keep on saying:
"PAGE" is not defined.
My code:
{% if queryset.has_other_pages %}
<div class="pagination">
<ul class="container">
{% if queryset.has_previous %}
<li><a href="?page={{queryset.previous_page_number}}" class="btn page-link"
data-
page="{{queryset.previous_page_number}}">❮ Prev</a></li>
{% endif %}
{% for page in custom_range %}
{% if page == queryset.number %}
<li><a href="?page={{page}}" class="btn page-link btn--sub" dtata-page=
{{page}}">{{page}}</a></li>
{% else %}
<li><a href="?page={{page}}" class="btn page-link" dtata-page="{{page}}">
{{page}}</a></li>
{% endif %}
{% endfor %}
<!-- The below code works for Next button -->
{% if queryset.has_next %}
<li><a href="?page={{queryset.next_page_number}}" class="btn page-link"
data-page="{{queryset.next_page_number}}">Next ❯</a></li>
{% endif %}
</ul>
</div> {% endif %}
<script type="text/javascript">
//Get Page Search form and page links
let searchForm = document.getElementById('searchForm')
let pageLinks = document.getElementsByClassName('page-link')
// Ensure Search Form Exist
if(searchForm){
for (let i = 0; pageLinks.length > i; i++){
pageLinks[i].addEventListener('click', function (e) {
e.preventDefault()
//Get The Data Attribute
let page= this.dataset.page
//Add Hideen Search Input To Form
searchForm.innerHTML += `<input value=${page} name="page" hidden/>`
searchForm.submit()
})
}
} </script>
this is in additional scripts section of shopify and im trying to send a pixel event for certain rules. i have pricing rules in place which work fine but this one isnt saving(assuming because it's wrong
{% for line in checkout.line_items %}
{% assign found_collection = false %}
{% for collection in line.product.collections %}
{% if collection.title == 'Collection NAME' %}
{% assign found_collection = true %}
{% endif %}
{% endfor %}
{% if found_collection == true %}
i was wondering if there is a way i can change the body of for loop in django using javascript each time i press a button.
in my case i want to display matches this week and when i press next i want to change the list using javascript and then pass it django template in the regroup part, i want to change the matches list.
i know how to write the code to make the new list and the previous and next buttons using javascript but i don't know how to pass it to django template
or maybe another way could be to write django code in javascript, anyone can help with either way?
in views.py , matches return a list of dictionaries from today to 6 days later
def home(request):
start = datetime.now().date()
end = today + timedelta(6)
matches = request_games(today, after_week)
return render(request, "sporty/home.html",{
"matches": matches,
"start" : start,
"end": end
})
in home.html
{% extends "sporty/layout.html" %}
{% load static %}
{% block body %}
<div class="box">
{{start}},{{end}}
{% regroup matches by date as date_list %}
{% for date in date_list %}
<div class="the_date">
{{date.grouper}}
</div>
{% for match in date.list %}
<div class="match_container">
<div class="status">
{% if match.status_code == 1%}
{{match.minute}}'
{% elif match.status_code == 11%}
HT
{% elif match.status_code == 3 %}
Finished
{% endif %}
</div>
<div class="match">
<div class="home">
{{match.home_name}} <img src="{{match.home_logo}}">
</div>
<div class="score">
{% if match.status_code == 0 %}
{{match.time}}
{% elif match.status_code == 17 %}
TBD
{% elif match.status_code == 1%}
{{match.home_score}} : {{match.away_score}}
{% elif match.staus_code == 11%}
{{match.home_score}} : {{match.away_score}}
{% elif match.status_code == 3 %}
{{match.home_score}} : {{match.away_score}}
{% endif %}
</div>
<div class="away">
<img src="{{match.away_logo}}">
{{match.away_name}}
</div>
</div>
</div>
{% endfor %}
{% endfor %}
</div>
{% endblock %}
def request_games(start, end):
params = (
("season_id","1511"),
("date_from",start.strftime("%Y-%m-%d")),
("date_to",end.strftime("%Y-%m-%d"))
);
headers = {
"apikey": //my api key
}
response = requests.get('https://app.sportdataapi.com/api/v1/soccer/matches', headers=headers, params=params)
r = response.json()
data = r["data"]
number = len(data)
matches = []
for i in range(number):
match = {}
match['status'] = data[i]["status"]
match['status_code'] = data[i]["status_code"]
match['minute'] = data[i]['minute']
full_date = data[i]["match_start"]
dt = datetime.strptime(full_date, '%Y-%m-%d %H:%M:%S')
match['date'] = dt.date()
match['time'] = dt.time()
match['start'] = full_date
home_team = data[i]["home_team"]
match['home_name'] = home_team['name']
match['home_logo'] = home_team['logo']
away_team = data[i]["away_team"]
match['away_name'] = away_team['name']
match['away_logo'] = away_team['logo']
stats = data[i]['stats']
match['home_score'] = stats['home_score']
match['away_score'] = stats['away_score']
matches.append(match)
matches.sort(key = lambda x: datetime.strptime(x['start'], '%Y-%m-%d %H:%M:%S'))
return matches
First thing first, once you decide to start working on pages that do not refresh but still query the server and change, one of your solutions is to start using AJAX calls to query the server for different data.
This would add a bit of code to your project.
For example, your home.html template will need to be split into two. Make sure to also add jQuery to your head.
sporty/home.html
{% extends "sporty/layout.html" %}
{% load static %}
{% block body %}
<div id="matchweek" class="box">
{% include "sporty/matchweek.html" %}
</div>
<button type="button" value="p" onclick="weekControl(this)">Previous</button>
<button type="button" value="n" onclick="weekControl(this)">Next</button>
{% comment %}
Either place weekupdate.js in /static/ or give the path within static,
best would be to have a folder for javascript in static and use 'js/weekupdate.js'
{% endcomment %}
<script src="{% static 'js/weekupdate.js' %}"></script>
{% endblock %}
and sporty/matchweek.html
{{start}},{{end}}
{% regroup matches by date as date_list %}
{% for date in date_list %}
<div class="the_date">
{{date.grouper}}
</div>
{% for match in date.list %}
<div class="match_container">
<div class="status">
{% if match.status_code == 1%}
{{match.minute}}'
{% elif match.status_code == 11%}
HT
{% elif match.status_code == 3 %}
Finished
{% endif %}
</div>
<div class="match">
<div class="home">
{{match.home_name}} <img src="{{match.home_logo}}">
</div>
<div class="score">
{% if match.status_code == 0 %}
{{match.time}}
{% elif match.status_code == 17 %}
TBD
{% elif match.status_code == 1%}
{{match.home_score}} : {{match.away_score}}
{% elif match.staus_code == 11%}
{{match.home_score}} : {{match.away_score}}
{% elif match.status_code == 3 %}
{{match.home_score}} : {{match.away_score}}
{% endif %}
</div>
<div class="away">
<img src="{{match.away_logo}}">
{{match.away_name}}
</div>
</div>
</div>
{% endfor %}
{% endfor %}
Because you will need to update the entire content of matchweek div every time.
views.py
def home(request):
if request.is_ajax():
template = 'matchweek.html'
direction = request.GET.get('dir')
if direction == 'n':
request.session['weekoffset'] += 1
elif direction == 'p':
request.session['weekoffset'] -= 1
else:
template = 'home.html'
request.session['weekoffset'] = 0
offset = request.session['weekoffset']
start = datetime.now().date() + timedelta(days=7*offset)
end = start + timedelta(days=6)
matches = request_games(start, end)
return render(request, f"sporty/{template}",{
"matches": matches,
"start": start,
"end": end
})
What you see in the function is a check if the request is coming from the AJAX call or not and determination on what to do from there.
/static/js/weekupdate.js
function weekControl(id) {
var value = id.value;
$.ajax({
url: '', // The url suffix that leads to your home function, example: '/home/'
type: "GET", // Http method
data: {'dir': value}, // The data to be sent to the server.
success: function (htmlres) { // What to do on success and response reaching back
$("#matchweek").html(htmlres);
}
});
}
What you see here is the AJAX get call to your django view with the data of 'dir' and its value. When it is returned, jQuery will change the content of the matchweek div with the new content.
I haven't tested this but let me know if this works and if you have any questions.
am getting this error trying to set a blog category page
NoReverseMatch at /blog/
Reverse for 'category_detail' with arguments '('',)' not found. 1 pattern(s) tried: ['blog\/category\-detail\/(?P[-a-zA-Z0-9_]+)$']
Here is my url.py
from django.urls import path,include
from .import views
urlpatterns = [
path('blog/',views.post_list,name="post_list"),
path('blog/post-detail/<slug:slug>',views.post_detail,name="post_detail"),
path('blog/category-detail/<slug:slug>',views.category_detail,name="category_detail"),
]
views.py
from django.shortcuts import render,get_object_or_404
from.models import Post,Category
# Create your views here.
def post_list(request):
object_list=Post.objects.all()
context={
'object_list': object_list,
}
return render(request,"blog.html",context)
def post_detail(request,slug=None):
post=get_object_or_404(Post,slug=slug)
context={
'post':post,
}
return render(request,"post_detail.html",context)
def category_detail(request,slug=None):
category=get_object_or_404(Category,slug=slug)
post=Post.objects.filter(category=category,status='Published')
context={
'category':category,
'post':post,
}
return render(request,"category_detail.html",context)
blog.html
{% for obj in object_list %}
{% if obj.status == 'Published' %}
<article>
<div class="embed-responsive embed-responsive-16by9">
<img src="images/blog1.jpg" alt="" />
</div>
<div class="post-content">
<h2>{{obj.title}}</h2>
<div>
{{obj.created}} Author {{obj.user}} <h4>{{obj.Category}}</h4>
<hr/>
<p>{{obj.body}}</p>
<a class="mtr-btn button-navy ripple" href= "{% url 'post_detail' obj.slug %}">Continue reading →</a><br>
</div>
</article>
{% endif %}
{% endfor %}
category_detail.html
{% extends "base.html" %}
{% load static %}
{% block seo_title %}{{category.seo_title}}{% endblock %}
{% block seo_description %}{{category.seo_description}}{% endblock %}
{% block Content %}
<h2>{{category.title}}</h2>
<p>{{category.description}}</p>
{% for item in post %}
{{item.title}}
{{item.body|truncatechars:50}}
{% endfor %}
{% endblock Content %}
NOTE THE OTHER VIEWS.PY ARE WORKING FINE JUST THE category_detail function
As the error said, the argument is missing here. Maybe you need to change {% url 'category_detail' slug=post.Category.slug %} with {% url 'category_detail' slug=obj.category.slug %} because I do not see any post variable reference in the blog.html template.
update
You have not shared your Model codes, but I am assuming your Post Model has Foreign Key to Category Model and it looks like Category=models.ForeignKey(Category). So you need to update the view like this:
def category_detail(request,slug=None):
category=get_object_or_404(Category,slug=slug)
post=Post.objects.filter(Category=category,status='Published')