NoReverseMatch from url tag inside include tag - javascript

I am trying to render a link inside an include html template with the url tag.
I have done this before and usually it works, but for some reason this time I can't make it.
I get a NoReverseMatch Error and suspect its because Django tries to load the url tag first but my object isn't ready, so the pk is empty. I believe that because it takes a moment until the dynamic data loads, while the static is already loaded.
The url works if I set pk to a fixed number, but I would like it to change dynamically.
Error:
Reverse for 'transaction' with keyword arguments '{'pk': ''}' not found. 1 pattern(s) tried: ['en/budget/account\\/(?P<pk>[0-9]+)\\/$']
Relevant urls:
from django.urls import path
from django.contrib import admin
from django.contrib.auth import views as auth_views
from . import views
app_name='budgetapp'
urlpatterns = [
path('', views.index, name='index'),
path('account/<int:pk>/', views.transaction, name='transaction'),
path('account/', views.account, name='account'),
]
Relevant views:
from django.shortcuts import get_object_or_404, render, redirect
from django.contrib.auth.models import Group
from django.contrib.auth.decorators import login_required, user_passes_test
from .models import *
from .forms import *
def index(request):
context = {}
context['accounts'] = Account.objects.filter(author=request.user)
return render(request, 'budgetapp/index.html', context)
def account(request):
context = {}
context['account'] = get_object_or_404(Account, pk = request.POST['accountPk'])
return render(request, 'budgetapp/account.html', context)
def transaction(request, pk):
context = {}
context['account'] = get_object_or_404(Account, pk = pk)
return render(request, 'budgetapp/addTransaction.html', context)
index.html:
{% csrf_token %}
<h1>Personal Budget</h1>
<br />
<p>
<label for="accountSelector">Account:</label>
<select required = "" id="accountSelector">
{% for account in accounts %}
<option value="{{account.pk}}">{{account}}</option>
{% endfor %}
</select>
</p>
<hr />
{% include 'budgetapp/account.html' %}
<script>
$(document).ready(function () {
reload();
});
$("#accountSelector").change(function () {
reload();
});
function reload() {
var dictionary = {}
dictionary['csrfmiddlewaretoken'] = $('input[name="csrfmiddlewaretoken"]').val();
dictionary['accountPk'] = $('#accountSelector').val();
$('#accountDiv').load("account/", dictionary);
console.log('Changed account');
}
</script>
account.html:
<div id="accountDiv">
<p>
Name: {{account.name}} Account balance: {{account.balance}} Add a transaction
</p>
</div>
If I change {% url 'budgetapp:transaction' pk=account.pk %} to /budget/account/{{account.pk}} it works, but that feels wrong.
I tried to provide all necessary code, but please let me know if it is to much or something is missing.

If you want to use {% url 'budgetapp:transaction' pk=account.pk %} then account must be in the template context. This has nothing to do with your browser dynamically loading data. The entire template is rendered by the server before the response is sent to the browser.
Using /budget/account/{{account.pk}} won't give an error, but if you look at the rendered HTML you'll see /budget/account/ since {{ account.pk }} will evaluate as ''.

Related

Django and Vue: I keep geetting "Failed to load resource: the server responded with a status of 500 (Internal Server Error)" in my website

I'm doing this project using Vue and Django, but when I run my code, I keep getting this error
"Failed to load resource: the server responded with a status of 500 (Internal Server Error)
127.0.0.1:8000/api/v1/products/winter/yellow-jacket-with-no-zipper:1"
I kept reloading and waited 30 minutes for this error to go away, but it keeps appearing.
I don't know if there is a problem in my javascript, because I don't have any errors when I run the vue project.
Here's my code I think has the problem.
Back end:
urls.py module in product package:
from django.urls import path, include
from product import views
urlpatterns = [
path('latest-products/', views.LatestProductsList.as_view()),
path('products/<slug:category_slug>/<slug:product_slug>', views.ProductDetail.as_view()),
]
Front end:
Product.vue script:
<template>
<div class="page-product">
<div class="columns is-multiline">
<div class="column is-9">
<figure class="image mb-6">
<img v-bind:src="product.get_image">
</figure>
<h1 class="title">{{ product.name }}</h1>
<p>{{ product.description }}</p>
</div>
<div class="column is-3">
<h2 class="subtitle">Information</h2>
<p>Price: <strong>{{ product.price }}</strong></p>
<div class="field has-addons mt-6">
<div class="control">
<input type="number" class="input" min="1" v-model="quantity">
</div>
<div class="control">
<a class="button is-dark">Add to Carts</a>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'Product',
data() {
return {
product: {},
quantity: 1
}
},
mounted() {
this.getProduct()
},
methods: {
getProduct() {
const category_slug = this.$route.params.category_slug
const product_slug = this.$route.params.product_slug
axios
.get(`/api/v1/products/${category_slug}/${product_slug}`)
.then(response => {
this.product = response.data
})
.catch(error => {
console.log("error")
})
}
}
}
</script>
Edit:
After some revision, I think the problem is caused by the views.py module in the product package
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Product
from .serializers import ProductSerializer
class LatestProductsList(APIView):
def get(self, request, format=None):
products = Product.objects.all()[0:4]
serializer = ProductSerializer(products, many=True)
return Response(serializer.data)
#I think its this line of code
class ProductDetail(APIView):
def get_object(self, category_slug, product_slug):
try:
return Product.objects.filter(category_slug=category_slug).get(slug=product_slug)
except Product.DoesNotExist:
raise Http404
def get(self, request, category_slug, product_slug, format=None):
product = self.get_object(category_slug, product_slug)
serializer = ProductSerializer(product)
return Response(serializer.data)
After revision of my code, I found out that I was right. The problem was the views.py module in the product package. It can be seen in the get_object function located in the ProductDetail class.
Original:
class ProductDetail(APIView):
def get_object(self, category_slug, product_slug):
try:
return Product.objects.filter(category_slug=category_slug).get(slug=product_slug)
except Product.DoesNotExist:
raise Http404
The problem was I needed to add another underscore/underline( this thing: _ ) when defining the category slug, so
category_slug=category_slug
becomes
category__slug=category_slug
New version:
class ProductDetail(APIView):
def get_object(self, category_slug, product_slug):
try:
return Product.objects.filter(category__slug=category_slug).get(slug=product_slug)
except Product.DoesNotExist:
raise Http404

How to update a Django html element with javascript and Ajax

I am trying to update an html element on web page with javascript. When the home page loads, it works perfectly, but when I click on New Product link just the context string is displayed on the home page
html
<!-- product/home.html -->
{% load static %}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>
<title>Test context</title>
</head>
<body>
<h1>Test context</h1>
<div class="container">
{% block content %}
Product: <span id="product-code"></span>
<p>New Product<p>
{% endblock content %}
<script type="text/javascript" src="{% static 'js/product.js' %}"></script>
</div>
</body>
</html>
urls.py
# cardplay/urls.py
from django.urls import path
from .views import HomePageView, NewProduct
urlpatterns = [
path('', HomePageView.as_view()),
path('new-product', NewProduct.as_view(), name= 'new-product'),
]
views.py
# /product/views.py
import random
from django.views.generic import View
from django.shortcuts import render
from django.http import JsonResponse
class HomePageView(View):
template = 'product/home.html'
def get(self, request):
context = {}
return render(request, self.template, context)
class NewProduct(View):
def get(self, request):
code = random.choice(['A123','M456', 'X789'])
context = {
'code': code,
}
return JsonResponse(context)
product.js
$(document).ready(function () {
getNewProduct();
});
function getNewProduct() {
$.ajax(
{
type: "GET",
url: 'new-product',
cache: false,
success: function (context) {
displayNewProduct(context);
}
}
);
}
function displayNewProduct(context) {
var productCode = document.getElementById('product-code');
productCode.innerText = context.code;
}
What am I doing wrong?
I was not calling the function as #Swati pointed out
product.js
$(document).ready(function () {
product_link = document.getElementById('product_link')
product_link.onclick = function(){getNewProduct()};
getNewProduct();
});
...
html
...
<p><button id="product_link">New Product</button></p>
...

'NoneType' object is not iterable problem solving

I want to show a list of question on my quiz.html templates... Here is my models.py
from django.db import models
# Create your models here.
DIFF_CHOICE = (
('easy','easy'),
('medium','medium'),
('hard','hard'),
)
class Quiz(models.Model):
name = models.CharField(max_length=120)
topic = models.CharField(max_length=120)
number_of_question = models.IntegerField()
time = models.IntegerField(help_text="Duration in Minutes")
required_score_to_pass = models.IntegerField(help_text="Required Score to Pass in %")
difficulty = models.CharField(max_length=6,choices=DIFF_CHOICE)
def __str__(self):
return f"{self.name}-{self.topic}"
def get_questions(self):
self.question_set.all()[:self.number_of_question]
class Meta:
verbose_name_plural = 'Quizes'
Here is my views.py
def quiz_data_view(request,pk):
quiz = Quiz.objects.get(pk=pk)
questions = []
for q in quiz.get_questions():
answers = []
for a in q.get_answers():
answers.append(a.text)
questions.append({str(q):answers})
return JsonResponse({
'data' : questions,
'time' : quiz.time,
})
and here is my quiz.html....and here i want to show my question list
{% extends "base.html" %}
{% load static %}
{% block scripts %}
<script src="{% static 'quizes/quiz.js' %}" defer></script>
{% endblock scripts %}
{% block title %}
{{obj.name}}
{% endblock title %}
{% block content %}
{{obj.name}}
<hr>
<form id ="quiz-form" class="mt-3 mb-3">
{% csrf_token %}
<div id="quiz-box"></div>
<button type="submit" class="btn btn-primary mt-3">Save
</button>
</form>
{% endblock content %}
Here is my js file...in my js file i used ajax...
const url = window.location.href
const quizBox = document.getElementById('quiz-box')
let data
$.ajax({
type: 'GET',
url: `${url}data`,
success : function(response){
// console.log(response)
data = response.data
data.forEach(el=>{
for(const [question,answers] of Object.entries(el)){
quizBox.innerHTML +=`
<hr>
<div class="mb-2">
<b> ${question}</b>
</div>
`
}
});
},
error : function(error){
console.log(error)
}
})
here is my urls.py
from django.urls import path
from .views import (
QuizListView,quiz_view,quiz_data_view
)
app_name='quizes'
urlpatterns = [
path('',QuizListView.as_view(),name='main-view'),
path('<int:pk>/',quiz_view,name='quiz-view'),
path('<int:pk>/data/',quiz_data_view,name='quiz-data-view'),
]
But I don't get my question list in the template
IT shows=> 'NoneType' object is not iterable

How to pass JavaScript variables to React component

I'm somewhat new to React and I'm having some trouble passing some variables from my Django server to my React components. Here's what I have:
The server is Django, and I have a url mydomain.com/testview/ that gets mapped to a views.py function testview:
def testview(request):
now = datetime.datetime.now()
return render(request, 'testview.html', {
'foo': '%s' % str(now),
'myVar': 'someString'
})
In other words, running testview will render the template file testview.html and will use the variables foo and myVar.
The file testview.html inherits from base.html which looks like this:
<!doctype html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
</head>
<body>
{% block main %}{% endblock %}
</body>
</html>
The file test.html basically inserts the needed code into block main:
testview.html:
{% extends "base.html" %}
{% load render_bundle from webpack_loader %}
{% block main %}
<script type="text/javascript">
var foo = {{ foo }};
var myVar = {{ myVar }};
</script>
<div id="App"></div>
{% render_bundle 'vendors' %}
{% render_bundle 'App' %}
{% endblock %}
Note that just before the div id="App", I created a couple of javascript variables foo and myVar and set them to the values from Django.
Now to REACT: my file App.jsx looks like this:
import React from "react"
import { render } from "react-dom"
import AppContainer from "./containers/AppContainer"
class App extends React.Component {
render() {
return (
<AppContainer foo={props.foo} myVar={props.myVar}/>
)
}
}
render(<App foo={window.foo} myVar={window.myVar}/>, document.getElementById('App'))
In other words, my App.jsx file renders the App component, passing in foo and myVar. Inside class App, I assumed these were props so I pass these to AppContainer using props.foo and props.myVar. My class AppContainer is inside a components folder and looks like this:
import React from "react"
import Headline from "../components/Headline"
export default class AppContainer extends React.Component {
render() {
return (
<div className="container">
<div className="row">
<div className="col-sm-12">
<Headline>Running App! foo is {props.foo}, Here is a string: {props.myVar}</Headline>
</div>
</div>
</div>
)
}
}
However, none of this seems to work. I just get a blank page. What am I doing wrong?
if foo and myVar is string you should declare
var foo = "{{ foo }}";
var myVar = "{{ myVar }}";
So this is what I needed to do to get it to work. First, I used Giang Le's answer above and in my testview.html file (a Django template file), I put quotes around the variables as they were indeed strings. Next, I changed the render statement in my App.jsx file to be this:
render(<App foo={foo} myVar={myVar}/>, document.getElementById('App'))
This used Bruno Vodola Martins' answer to access foo and myVar as javascript globals. I also had to use this.props.foo instead of props.foo in my App class:
class App extends React.Component {
render() {
return (
<AppContainer foo={this.props.foo} myVar={this.props.myVar}/>
)
}
}
And I did the same thing in containers/AppContainer.jsx:
export default class AppContainer extends React.Component {
render() {
return (
<div className="container">
<div className="row">
<div className="col-sm-12">
<Headline>App! foo is {this.props.foo}, Here is a string: {this.props.myVar}</Headline>
</div>
</div>
</div>
)
}
}
Bottom line: put quotes around string variables from Django, and use this.props.foo instead of just props.foo.

How to change the contents of a block dynamically on django?

SEE FIXED CODE BELOW
I'm working on my first web page project using django 1.8. My web page has a section that consists of a product menu and a column displaying a different view based on selected menu item.
At first I tried an approach where each of the menu buttons have a onclick js function assigned that changes the contents of the block. I was thinking that I would then write the html code of each product into separate file where it would be read by the js function. I got it partially working but it feels kinda sketchy.
My second approach was based on using django templates but I run into some errors as a beginner I couldn't quite figure out what exactly is the problem. I would highly appreciate if someone could pinpoint what I'm doing wrong or tell me what's the right approach for changing the contents dynamically.
The errors I'm getting currently:
http://127.0.0.1:8000/productmonitor/
NoReverseMatch at /productmonitor/
Reverse for 'product' with arguments '('',)' and keyword arguments '{}' not found. 1 pattern(s) tried: [u'productmonitor/(?P<product_name>[a-z]+)/$']
http://127.0.0.1:8000/productmonitor/
NoReverseMatch at /productmonitor/dualpol/
Reverse for 'product' with arguments '('',)' and keyword arguments '{}' not found. 1 pattern(s) tried: [u'productmonitor/(?P<product_name>[a-z]+)/$']
urls.py
# -*- coding: utf-8 -*-
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^(?P<product_name>[A-Za-z0-9\-\_]+)/$', views.product, name='product'),
url(r'^information/$', views.information, name='information'),
url(r'^casedatabase/$', views.casedatabase, name='casedatabase'),
url(r'^contact/$', views.contact, name='contact'),
]
views.py
from django.http import HttpResponse
from django.shortcuts import get_object_or_404, render
from django.views import generic
# Create your views here.
from .models import Product
def index(request, product_name='default'):
#template = 'productmonitor/index.html'
if product_name == 'dualpol':
template = 'productmonitor/base_productmonitor_dualpol.html'
if product_name == 'rhi':
template = 'productmonitor/base_productmonitor_rhi.html'
template = 'productmonitor/base_productmonitor.html'
test_context = {
'products' : Product.objects.all(),
}
return render(request, template, test_context)
def product(request, product_name='dualpol'):
if product_name == 'dualpol':
template = 'productmonitor/base_productmonitor_dualpol.html'
if product_name == 'rhi':
template = 'productmonitor/base_productmonitor_rhi.html'
test_context = {
'products' : Product.objects.all(),
}
return render(request, template, test_context)
base_productmonitor.html
{% extends "productmonitor/base.html" %}
{% block content %}
<div class="productSelectMenu">
<ul>
<p>Test</p>
{% for product in products %}
<li><a href="{% url 'productmonitor:product' 'dualpol' %}">{{ product.name }}<a/></li>
{% endfor %}
</ul>
</div>
{% block productcontent %}
<div id="productView" class="productView">
<p>Default productView content</p>
</div>
{% endblock %}
{% endblock %}
base_productmonitor_dualpol.html
{% extends "productmonitor/base_productmonitor.html" %}
{% block productcontent %}
<p>
dualpol
</p>
{% endblock %}
EDIT: FIXED VERSION
urls.py
# -*- coding: utf-8 -*-
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^product/(?P<product_name>[a-z]+)/$', views.product, name='product'),
url(r'^information/$', views.information, name='information'),
url(r'^casedatabase/$', views.casedatabase, name='casedatabase'),
url(r'^contact/$', views.contact, name='contact'),
]
views.py
enter code here
from django.http import HttpResponse
from django.shortcuts import get_object_or_404, render, redirect
from django.views import generic
# Create your views here.
from .models import Product
def index(request, product_name=''):
return redirect('productmonitor:product', product_name='dualpol')
def product(request, product_name):
if product_name == 'dualpol':
template = 'productmonitor/base_productmonitor_dualpol.html'
if product_name == 'rhi':
template = 'productmonitor/base_productmonitor_rhi.html'
test_context = {
'products' : Product.objects.all(),
}
return render(request, template, test_context)
def information(request):
template = 'productmonitor/base_information.html'
context = {}
return render(request, template, context)
def casedatabase(request):
template = 'productmonitor/base_case-database.html'
context = {}
return render(request, template, context)
def contact(request):
template = 'productmonitor/base_contact.html'
context = {}
return render(request, template, context)
base_productmonitor.html
{% extends "productmonitor/base.html" %}
{% block content %}
<div class="productSelectMenu">
<ul>
<li><a href="{% url 'productmonitor:product' 'dualpol' %}">Dual pol<a/></li>
<li><a href="{% url 'productmonitor:product' 'rhi' %}">Rhi<a/></li>
</ul>
</div>
{% block productcontent %}
<div id="productView" class="productView">
<p>Default productView content</p>
</div>
{% endblock %}
{% endblock %}
base_productmonitor_dualpol.html
{% extends "productmonitor/base_productmonitor.html" %}
{% block productcontent %}
<div id="productView" class="productView">
<p>
dualpol
</p>
</div>
{% endblock %}
I think what the error is saying that the render in your product function is not getting the right <product_name> to use. It's showing that the arguments that it has (the <product_name> that it is trying) are none. So what you have to do in your product function is to try and make sure that you are really getting a <product_name>.

Categories