The NoReverseMatch error in Django updateView - django

I am writing and Update View for a model that I have created. The model is a Product Backlog Item. The UpdateView is unable to find a reverse match for my view.
The NoReverseMatch error is saying that Django cannot find a matching url pattern.
My code as below:
UpdatePBI View
class updatePBI(LoginRequiredMixin, UpdateView):
pk_url_kwarg = 'pbipk'
kwargs={'pk_url_kwarg': 'pbipk'}
model = PBI
fields = ['priority', 'summary', 'story_points', 'effort_hours']
login_url = '/accounts/login'
redirect_field_name = '/home'
template_name = 'backtrack/PBIdetail.html'
def dispatch(self, request, *args, **kwargs):
print(kwargs)
return super().dispatch(request, *args, **kwargs)
def get_success_url(self):
return "{}?all=0".format(reverse('pb', kwargs={'pk': self.kwargs['pk']}))
def get_object(self, queryset=None):
obj = get_object_or_404(self.model,pk=self.kwargs['pbipk'])
return obj
def form_valid(self, form):
PBIList = getPBIfromProj(self.kwargs['pk'], '0')
remove = []
priorityData = form.cleaned_data['priority']
if int(priorityData) < self.object.priority:
# Remove all PBI with priority higher than post data priority
# and lesser or equal than current PBI priority
for PBIObj in PBIList:
if PBIObj.priority < int(priorityData) or PBIObj.priority >= self.object.priority:
remove.append(PBIObj.priority)
PBIList = [
PBIObj for PBIObj in PBIList if PBIObj.priority not in remove]
# Increase each objects priority by one
for PBIObj in PBIList:
PBIObj.priority += 1
PBIObj.save()
else:
# Remove all PBI with priority higher than post PBI priority
# and lesser than and equal to Post data priority
for PBIObj in PBIList:
if PBIObj.priority <= self.object.priority or PBIObj.priority > int(priorityData):
remove.append(PBIObj.priority)
PBIList = [
PBIObj for PBIObj in PBIList if PBIObj.priority not in remove]
# Decrease each objects priority by one
for PBIObj in PBIList:
PBIObj.priority -= 1
PBIObj.save()
return super().form_valid(form)
model.py
from django.urls import reverse
# Create your models here.
class PBI(models.Model):
status = models.CharField(max_length=1,
choices=[("N", "Not Done"), ("P", "In Progress"), ("D", "Done")], default="N")
story_points = models.FloatField()
effort_hours = models.FloatField()
summary = models.TextField(default = None)
priority = models.IntegerField(default=0)
Project = models.ForeignKey('Project', on_delete=models.CASCADE, related_name='pbi')
def __str__(self):
return self.summary
class Meta:
db_table = "PBI"
verbose_name = 'PBI'
verbose_name_plural = 'PBIs'
class Project(models.Model):
name = models.CharField(max_length=256)
def __str__(self):
return self.name
class Meta:
db_table = "Project"
urls.py
from django.conf.urls import url
from backtrack import views
from django.shortcuts import redirect
urlpatterns = [
path('', lambda x: redirect('1/'),name='home'),
path('<int:pk>/', views.HomeView.as_view(),name = 'home-project'),
path('<int:pk>/pb/', views.ProductBacklogView.as_view(),name='pb'),
path('<int:pk>/pb/add/', views.AddPBI.as_view(),name='add'),
path('<int:pk>/pb/<int:pbipk>/update', views.updatePBI.as_view(),name='detail'),
path('<int:pk>/pb/<int:pbipk>/delete', views.DeletePBI.as_view(),name='delete')
]
Product Backlog Page
{% block content %}
<h1 class="page-header"><i class="fa fa-file"></i> Product BackLog</h1>
<div class="row placeholders"></div>
{% if data|length == 0 %}
<h4>There are no PBIs</h4>
{% endif %}
<h2 class="sub-header">
<div class="dropdown">
<button class="btn btn-light dropdown-toggle pull-left" type="button" data-toggle="dropdown" style="margin-bottom: 10px;">Filter By
<span class="caret"></span></button>
<ul class="dropdown-menu">
<li>Priority</li>
<li>Story Points</li>
<li>Effort Hours</li>
</ul>
<div class="btn-group btn-toggle">
<button class="btn btn-xs btn-primary active toggle">NOT DONE</button>
<button class="btn btn-xs btn-default toggle">ALL</button>
</div>
<button type="button" class="btn btn-light" style="margin-bottom: 10px;"><i class="fa fa-plus" id="A"></i>ADD</button>
<button type="button" class="btn btn-light" style="margin-bottom: 10px;"><i class="fa fa-times" id="A"></i>DELETE</button>
</div>
</h2>
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th> </th>
<th>Priority</th>
<th>Summary</th>
<th>Status</th>
<th>Story Points</th>
<th>Cumulative Story Points</th>
<th>Effort hours</th>
<th>Cumulative Effort hours</th>
</tr>
</thead>
<tbody>
{% for PBI in data %}
<tr>
<td><input type="checkbox"></td>
<td>
{% if PBI.status == "N" %}
{{PBI.priority}}
{% else %}
--
{% endif %}
</td>
<td><a style="text-decoration: none; color: cornflowerblue;" href={% url 'detail' pk=1 pbipk=PBI.id %}>{{PBI.summary}}</a></td>
<td>
{% if PBI.status == "N" %}
Not Done
{% elif PBI.status == "P" %}
In Progress
{% else %}
Done
{% endif %}
</td>
<td>{{PBI.story_points}}</td>
<td>{{PBI.sum_story_points}}</td>
<td>{{PBI.effort_hours}}</td>
<td>{{PBI.sum_effort_hours}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<script>
$.urlParam = function (name) {
var results = new RegExp('[\?&]' + name + '=([^&#]*)')
.exec(window.location.search);
return (results !== null) ? results[1] || 0 : false;
}
$(document).ready(function () {
if($.urlParam('all') == '1'){
$(this).find('.toggle').toggleClass('active');
if ($(this).find('.btn-primary').length>0) {
$(this).find('.toggle').toggleClass('btn-primary');
}
}
var getUrl = window.location;
var baseUrl = getUrl.protocol + "//" + getUrl.host + getUrl.pathname;
$('.btn-toggle').click(function(){
console.log($.urlParam('all') == '0')
if($.urlParam('all') == '0')
window.location.replace(baseUrl + "?all=1");
else
window.location.replace(baseUrl + "?all=0");
})
});
</script>
{% endblock content %}
I am getting this error
NoReverseMatch at /home/1/pb/50/update
Reverse for 'detail' with keyword arguments '{'pk': 1, 'pbipk': ''}' not found. 1 pattern(s) tried: ['home/(?P<pk>[0-9]+)/pb/(?P<pbipk>[0-9]+)/update$']
Update
I have found that the error is because I am setting the form action with the PBI.id but the Update view is not passing a PBI to my template. How do I fix this?

Okay. I found what I was doing wrong. I have to override the get_context_data() function of the template view mixin and pass the PBI in the context after calling super().get_context_data(form).

Related

Django - Calling function in ListView or model to change model bolean status

I want to call a function - from a model or from a Listview that will change Order.isDone status - TRUE or FALSE after clicking the button in template.
Model.py:
class Order(models.Model):
isDone = models.BooleanField(default=False, verbose_name='Zrealizowane')
views.py:
class OrderListView (ListView):
model = Order
template_name = 'orders/orders_list.html'
ordering = ['-orderDate']
urls.py:
urlpatterns = [
path('', views.home, name='page-home'),
path('orders_list/', OrderListView.as_view(), name='page-orders-list'),
path('completed_orders_list/', OrderCompletedListView.as_view(), name='page-completed-orders-list'),
path('orders/order_create/', OrderCreateView.as_view(), name='page-order-create'),
path('orders/<int:pk>/delete/', OrderDeleteView.as_view(), name='page-order-delete'),
]
template:
<tbody>
{% for order in object_list %}
{% if order.isDone == False %}
<tr>
<td>
<button type="button" class="btn btn-secondary" data-toggle="modal" data-target="#exampleModalCenter">Szczegóły</button>
<form action="{% url 'page-orders-list' order.id %}" method="post">
{% csrf_token %}
<button class="btn btn-info btn-sm">Finish order</button>
<form>
<a class="btn btn-danger adminButton" href="{% url 'page-order-delete' order.id %}">Usuń</a>
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
What is the easiest way to do this ?
I suggest using another view for this. You can use the get method in the view to change the status of the order. The in your HTML you would only need to use a link instead of a form.
So something like this:
views.py
class OrderFinishView(RedirectView):
success_url = None # After finishing the order, where do you want to redirect the user?
def get(self, request, *args, **kwargs):
order_id = self.kwargs['pk_order'] # pk_order must be in your URL
order = get_object_or_404(Order, pk=order_id)
order.is_done = True
order.save()
return super().get(request, *args, **kwargs)
urls.py
urlpatterns = [
path('', views.home, name='page-home'),
path('orders_list/', OrderListView.as_view(), name='page-orders-list'),
path('completed_orders_list/', OrderCompletedListView.as_view(), name='page-completed-orders-list'),
path('orders/order_create/', OrderCreateView.as_view(), name='page-order-create'),
path('orders/<int:pk>/delete/', OrderDeleteView.as_view(), name='page-order-delete'),
path('orders/<int:pk_order>/finish', OrderFinishView.as_view(), name='page-order-finish'),
]
template
<tbody>
{% for order in object_list %}
{% if order.isDone == False %}
<tr>
<td>
<a href={% url 'page-order-finish' order.id %}>Finish</a>
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
Another idea is to use an UpdateView to update your order with a PartialOrderForm which would only contain the is_done field.
I used the #vinkomlacic's solution, but i changed the return of get function:
def get(self, request, *args, **kwargs):
order_id = self.kwargs['pk_order'] # pk_order must be in your URL
order = get_object_or_404(Order, pk=order_id)
order.isDone = True
order.save()
return redirect(self.success_url)
Seems to be working properly now after setting success_url in class

Updating model field after input in Django

I am trying to update an account value model field after the user inputs a stock price and quantity from a form. Essentially the user would input a stock price and share quantity and their account balance should reflect the purchase amount. Below are images of my models.py, my forms.py, my views.py and my buy_stock.html page. Any insight as to how I can get the value to save would be very helpful. Thanks in advance. - Total newb
Views.py
from django.shortcuts import render, redirect
from .models import Stock, Bank, BuyStockModel
from .forms import StockForm, BankForm, BuyStock, Registration
from django.contrib import messages
import requests
import json
def main(request):
stocks = BuyStockModel.objects.all().order_by('-created')
form = BuyStock()
account = Bank.objects.only('account')
balance = account
if request.method == 'POST':
price = request.POST.get('price')
quantity = request.POST.get('quantity')
if price is not None:
price = float(price)
if quantity is not None:
quantity = float(quantity)
total = float(price) * float(quantity)
if balance >= total:
balance = balance - total
account.update(account = balance)
#account.save()
ticker = request.POST['ticker']
api_request = requests.get(
"https://cloud.iexapis.com/stable/stock/" +
ticker +
"/quote?token=i_should_get_a_new_one"
)
try:
api = json.loads(api_request.content)
except Exception as e:
api = "Error..."
context = {
'api': api,
'form' : form,
'stocks' : stocks,
"account" : account
}
return render(request, 'buy_stock.html', context)
else:
context = {'form' : form, 'stocks' : stocks}
return render(request, 'buy_stock.html', context)
def buy_stock(request):
print('buy_stock')
if request.method == 'GET':
form = BuyStock()
stocks = BuyStockModel.objects.all().order_by('-created')
output = {'form' : form, 'stocks' : stocks}
return render(request, 'buy_stock.html', output)
elif request.method == 'POST':
form = BuyStock(request.POST or None)
if form.is_valid():
form.save()
name = form.cleaned_data['name']
price = form.cleaned_data['price']
quantity = form.cleaned_data['quantity']
form = BuyStock()
return redirect('buy_stock')
return render(request, 'buy_stock.html', {
'form' : form,
'name' : name,
'price' : price,
'quantity' : quantity
})
Models.py
from django.db import models
class Stock(models.Model):
ticker = models.CharField(max_length = 10)
def __str__(self):
return self.ticker
class Bank(models.Model):
account = models.DecimalField(
max_digits = 15, default = 30000.0, decimal_places = 0,
editable = True
)
def __str__(self):
return self.account
class BuyStockModel(models.Model):
name = models.CharField(max_length = 100)
option = models.CharField(max_length = 10, default = 'buy')
price = models.DecimalField(
max_digits = 15, decimal_places = 2, default = 0
)
quantity = models.DecimalField(
max_digits = 15, decimal_places = 0, default = 0
)
total_value = models.DecimalField(
max_digits = 15, default = 1, decimal_places = 0,
editable = True
)
created = models.DateTimeField(auto_now_add = True)
def __str__(self):
return self.price
def __str__(self):
return self.quantity
def calc_total(self):
amount = (self.price * self.quantity)
return amount
def save_total(self):
self.total_value = self.calc_total()
super(BuyStockModel, self).save()
Forms.py
from django import forms
from .models import Stock, Bank, BuyStockModel
from django.contrib.auth import login, authenticate
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class Registration(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ["username", "email", "password1", "password2"]
class StockForm(forms.ModelForm):
class Meta:
model = Stock
fields = ["ticker"]
class BankForm(forms.ModelForm):
class Meta:
model = Bank
fields = ["account"]
class BuyStock(forms.ModelForm):
class Meta:
model = BuyStockModel
fields = ["name", "price", "quantity"]
widgets = {
'name' : forms.TextInput(attrs = {'class' : 'form-control'}),
'price' : forms.TextInput(attrs = {'class' : 'form-control'}),
'quantity' : forms.TextInput(attrs = {'class' : 'form-control'}),
}
buy_stock.html
{% extends 'base.html' %}
{% block content %}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Project-4 Buy Stock page</title>
</head>
<body>
<div class="container"></div>
<h1>Buy Stock</h1>
<br/>
<div>
<form action = "{%url 'main' %}" class="form-inline my-2 my-lg-0" method = "POST">
{% csrf_token %}
<input class="form-control mr-sm-2" type="search" placeholder="Get Stock Quote" aria-label="Search" name = "ticker">
<button class="btn btn-outline-secondary my-2 my-sm-0" type="submit">Stock Quote</button>
</form>
</div>
<br/>
<br/>
<div>
{% if ticker %}
{{ ticker }}
{% endif %}
{% if api %}
{% if api == "Error..." %}
There was a problem with your ticker symbol,
please try again...
{% else %}
<h2>{{ api.companyName }}</h2>
<br/>
{% load humanize %}
Price: ${{ api.latestPrice|intcomma }}<br/>
Previous Close: ${{ api.previousClose|intcomma }}<br/>
Market Cap: ${{ api.marketCap|intcomma }}<br/>
YTD Change: {{ api.ytdChange }}<br/>
52 Week High: ${{ api.week52High|intcomma }}<br/>
52 Week Low: ${{ api.week52Low|intcomma }}<br/>
<br/>
{% endif %}
{% else %}
{% endif %}
</div>
<br/>
<div>
<h6 class = "bold">Total in Account</h6>
{% for item in account %}
{% load humanize %}
<h1 class = "bold">${{ item.account|intcomma }}</h1>
{% endfor %}
</div>
<div class="container">
<div class="row">
<div class="col-sm">
<div class = "form-group">
<form action = "{%url 'buy_stock' %}" method = "POST">
{% csrf_token %}
{{ form.as_p }}
<div class="dropdown">
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenu2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Trading Options
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenu2">
<button class="dropdown-item" type="sumbit">Buy</button>
<button class="dropdown-item" type="submit">Sell</button>
</div>
</div>
</form>
</div>
</div>
<div class="row">
<div class="col-sm">
<table class="table table-striped table-bordered table-hover">
<thead class="thead-dark">
<tr>
<th scope="col">Date Purchased</th>
<th scope="col">Company Name</th>
<th scope="col">Stock Price</th>
<th scope="col">Shares Purchased</th>
</tr>
</thead>
<tbody>
{% for item in stocks %}
<tr>
{% load humanize %}
<th scope="row">{{ item.created }}</th>
<td>{{ item.name }}</td>
<td>${{ item.price|intcomma }}</td>
<td>{{ item.quantity|intcomma }} Shares</td>
</tr>
{% endfor %}
</tbody>
</table>
<br/>
{% for item in stocks %}
<a class="btn btn-danger" href = "{% url 'sell_stock' item.id %}">Delete {{ item.name }}</a>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
<br/>
<br/>
<br/>
</body>
{% endblock %}
I think you should learn first about model relations. You data model will not work this way and fixing that, the rest will become more clear, hopefully.
An Order (you call it BuyStockModel) is the marriage of a product with a customer. So this order model should have links with the product (Stock) and the Customer (in your case represented by their Bank account). A broker has 2-way orders: both sales and purchase orders, but for the basic data model it's not important.
I'm going to use Order below, because BuyStockModel is not a good name for me :).
So you need two relations:
Order
/ \
Stock Bank
Django uses ForeignKeys for this relation:
class Order(models.Model):
stock = models.ForeignKey(Stock, on_delete=models.PROTECT)
account = models.ForeignKey(Bank, on_delete=models.PROTECT)
option = models.CharField(max_length = 10, default = 'buy')
price = models.DecimalField(
max_digits = 15, decimal_places = 2, default = 0
)
quantity = models.DecimalField(
max_digits = 15, decimal_places = 0, default = 0
)
created = models.DateTimeField(auto_now_add = True)
#property
def total_value(self):
return self.price * self.quantity
def __str__(self):
return (
f"{self.option.upper()}: {self.id} / qt: {self.quantity}"
f" / price: {self.price}"
)
You can now construct a single "OrderForm" using the Order model, that can render the accounts and stock tickers. That should get you on your way.

django 2.1 HTML form submitting to db error

i am trying to post the data from html form to my db, however i get the error that the url does not exist. what am trying to do is later on turn the test form into dynamic add fields using HTML and Jquery rather than using formset for ease UI designing and handle it in dango back end.
also note that am assigning the foreign key which is the startup_name by passing it through the url to test view.
the code is as following:
models.py:
class Startup(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
startup_name = models.CharField('Startup Name', max_length = 32, null = False, blank = False)
class Team (models.Model):
str_team = models.ForeignKey(Startup, on_delete=models.CASCADE)
name = models.CharField('Name',max_length = 32, null = False, blank = False)
position = models.CharField('Title/Position', max_length = 32, null = False, blank = False)
qualification = models.CharField('Degrees/Qualifications', max_length=32,null=False,blank=False)
views.py:
def create_startupform(request):
if request.method == 'POST':
form = startupform(request.POST)
if form.is_valid():
result = form.save(commit=False)
result.author = request.user
result.save()
return redirect('test', startup_id = result.pk)
else:
form = startupform()
return render(request, 'str_name.html', {'form': form})
def test (request, startup_id):
e = Startup.objects.values('startup_name')
if request.method == 'POST':
na = request.POST.get("name")
po = request.POST.get("position")
qu = request.POST.get("qualification")
ref = Team(name = na, position = po, qualification = qu, str_team = e)
ref.save()
return redirect('str_dashboard')
return render(request, 'test.html')
forms.py:
class startupform(forms.ModelForm):
class Meta:
model = Startup
fields = ('startup_name',)
widgets = {
'startup_name': forms.TextInput(attrs = {'class':'form-control'}),
}
def clean(self):
super ( ).clean ( )
startup_name = self.cleaned_data.get ( 'startup_name' )
startup_qs = Startup.objects.filter ( startup_name = startup_name )
if startup_qs.exists ( ):
raise forms.ValidationError ( 'This Startup Already Exist!' )
test.html:
<form id="add-extra" class="form" method="post" action = "{% url 'test' %}">{% csrf_token %}
<div class="form-row profile-row">
<div class="col-md-8 col-lg-12">
<hr />
<h4>Startup Core Team</h4>
<div class="form-row">
<div class="col-sm-12 col-md-6 col-lg-12">
<div class="form-group">
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Position</th>
<th>Qualification</th>
</tr>
</thead>
<tbody>
<tr>
<td><input class="form-control" type="text" name="candidate_name" /></td>
<td><input class="form-control" type="text" name="position"/></td>
<td><input class="form-control" type="text" name="qualification"/></td>
<td><button class="btn btn-primary d-lg-flex align-items-lg-center" type="button" style="margin-top: 4px;margin-left: 15px;background-color: rgb(24,130,7);"><i class="fas fa-plus"></i></button></td>
</tr>
<tr></tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<hr />
<div class="form-row">
<div class="col-md-12 content-right"><button class="btn btn-primary text-center border rounded d-lg-flex justify-content-lg-end align-items-lg-center form-btn" type="post" style="margin-left: 1040px;padding: 6px;">SAVE </button></div>
</div>
</div>
</div>
URLS:
from django.urls import path
from . import views
urlpatterns = [
path ( 'str_dashboard/' , views.str_dashboard , name = 'str_dashboard' ),
path ( 'create_startupform/' , views.create_startupform, name = 'create_startupform' ),
path('test/', views.test, name='test'),
]
Error:
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/test/
Using the URLconf defined in sourcing.urls, Django tried these URL patterns, in this order:
You are trying an url which is not in the urls.py:
urlpatterns = [
...
path('test/<int:startup_id>/', views.test, name='test'),
path('test/', views.test, name='test_base'), # add this
]
The url 'http://127.0.0.1:8000/test/' won't match because it would need to have 'startup_id' attached with your urls.py.
http://127.0.0.1:8000/test/1 would work.
If you do like i wrote above, make sure that your view is taking startup_id as optional. Or use another function for the call without startup_id.

Django 2.0.5 display different queryset result with the CBV listview

Hi: I am trying to build a staff directory where user can filter view by department. I have the department list displayed in a dropdown button but cannot figure out how to properly pass the user selection to the listview in the views.py Please see the code below.
models.py
class Department(models.Model):
department = models.CharField(max_length = 20, unique = True)
def __str__(self):
return self.department
class EmployeeList(models.Model):
department = models.ForeignKey(Department, on_delete = models.SET_NULL, null = True, blank = True)
views.py
class EmployeeOutput(ListView):
model = models.EmployeeList
context_object_name = 'employee_list'
template_name = 'employee_list.html'
def get_context_data(self, **kwargs):
context = super(EmployeeOutput, self).get_context_data(**kwargs)
context['filter_list'] = models.Department.objects.values_list('department', flat = True)
return context
class FilterDepartment(ListView):
model = models.EmployeeList
context_object_name = 'employee_list'
template_name = 'employee_list.html'
def get_context_data(self, **kwargs):
context = super(FilterDepartment, self).get_context_data(**kwargs)
context['filter_list'] = models.Department.objects.values_list('department', flat = True)
context['department_filter'] = models.EmployeeList.objects.filter(department_id = 3)
return context
employee_list.html
<table class = 'table table-striped table-hover' id = 'my_table'>
<thead>
<tr>
<th><button type="button" class = ' btn btn-info' onclick = 'sortTable(0)'>Name</button></th>
<th><button type="button" class = ' btn btn-info' onclick = 'sortTableNumbers(1)'>Phone Ex</button></th>
<th><button type="button" class = ' btn btn-info' onclick = 'sortTable(2)'>Email</button></th>
<th>
<div class="btn-group dropright">
<button class="btn btn-success dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Department
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
<a class="dropdown-item" onclick = 'sortTable(3)'><b>Sort Department</b></a>
<h6 class="dropdown-header">Filter by:</h6>
<div class="dropdown-divider"></div>
{% for running in filter_list%}
<a class="dropdown-item" href="{% url 'employee:department_filter' %}"><b>{{running}}</b></a>
{% endfor %}
</div>
</div>
</th>
<th><button type="button" class = ' btn btn-info' onclick = 'sortTable(4)'>Remote Access</button></th>
<th>Cell Phone</th>
</tr>
</thead>
<tbody>
{% if department_filter %}
{% for EL in department_filter %}
<tr>
<td>{{EL.first_name}} {{EL.last_name}}</td>
<td>{{EL.phone_ex}}</td>
<td> {{EL.email}}</td>
<td>{{EL.department}}</td>
<td>{{EL.remote_access}}</td>
<td>{{EL.cell}}</td>
</tr>
{% endfor %}
{% else %}
{% for EL in employee_list %}
<tr>
<td>{{EL.first_name}} {{EL.last_name}}</td>
<td>{{EL.phone_ex}}</td>
<td> {{EL.email}}</td>
<td>{{EL.department}}</td>
<td>{{EL.remote_access}}</td>
<td>{{EL.cell}}</td>
</tr>
{% endfor %}
{% endif %}
</tbody>
</table>
I can properly display the entire staff with 'employee_list'. I can show a list of current department in the dropdown button with 'filter_list'. When user clicked on any of the selection, it always shows the same result since 'department_list' is hard coded to department_id = 3. What I need to find out is how to pass in the ID with href as
{% url 'employee:department_filter' dept=running.id %}
with url.py
path('filter/<int:dept>', views.FilterDepartment.as_view(), name = 'department_filter'),
I am struggling to find out how to pass 'dept' into the 'FilterDepartment' view. Maybe there is a better way to do this or I am just missing the last piece to make this happen. Any suggestion is welcome. Thank you
suggestion by #dirkgroten
employee_list.html
<a class="dropdown-item" href="{% url 'employee:department_filter' dept=running.id %}"><b>{{running}}</b></a>
{% if object_list %}
{% for EL in object_list %}
<tr>
<td>{{EL.first_name}} {{EL.last_name}}</td>
<td>{{EL.phone_ex}}</td>
<td> {{EL.email}}</td>
<td>{{EL.department}}</td>
<td>{{EL.remote_access}}</td>
<td>{{EL.cell}}</td>
</tr>
{% endfor %}
urls.py
path('filter/<int:dept>/', views.FilterDepartment.as_view(), name = 'department_filter'),
views.py
class FilterDepartment(ListView):
model = models.EmployeeList
context_object_name = 'employee_list'
template_name = 'employee_list.html'
def get_context_data(self, **kwargs):
context = super(FilterDepartment, self).get_context_data(**kwargs)
context['filter_list'] = models.Department.objects.values_list('department', flat = True)
return context
def get_queryset(self, **kwargs):
return super().get_queryset().filter(department_id=self.kwargs['dept'])
working solution:
employee_list.html
{% for running in filter_list%}
<a class="dropdown-item" href="{% url 'employee:department_filter' running %}"><b>{{running}}</b></a>
{% endfor %}
{% if object_list %}
{% for EL in object_list %}
<tr>
<td>{{EL.first_name}} {{EL.last_name}}</td>
<td>{{EL.phone_ex}}</td>
<td> {{EL.email}}</td>
<td>{{EL.department}}</td>
<td>{{EL.remote_access}}</td>
<td>{{EL.cell}}</td>
</tr>
urls.py
path('filter/<department>/', views.FilterDepartment.as_view(), name = 'department_filter'),
views.py
class FilterDepartment(ListView):
model = models.EmployeeList
context_object_name = 'employee_list'
template_name = 'employee_list.html'
#if missing, it is looking for EmployeeList_list.html
#employee_list.pk used in empllyee_list.html
def get_context_data(self, **kwargs):
context = super(FilterDepartment, self).get_context_data(**kwargs)
context['filter_list'] = models.Department.objects.values_list('department', flat = True)
# context['department_filter'] = models.EmployeeList.objects.filter(department_id = self.kwargs['dept'])
return context
def get_queryset(self):
return super(FilterDepartment, self).get_queryset().filter(department__department=self.kwargs['department'])
Use the ListView's get_queryset() method to filter the list of objects you want to display. This will add object_list to the context in the template. Only use get_context_data() to add additional information to the context.
class FilterDepartment(ListView):
# properties like model and template_name
# context_object_name can be used if you want to call the list something else than 'object_list' in your context
def get_queryset(self):
return super().get_queryset().filter(department_id=self.kwargs['dept'])
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) # this will already include object_list
context['filter_list'] = models.Department.objects.values_list('department', flat = True)
return context
The Django documentation on ListView is quite concise and makes it difficult to really understand which methods to override. A better place to understand Django's generic class based views is here.

django x-editable /post URL issue & django model save

I would like to click on the object and change its attribute value and save it by updating object with new attribute value.
I try to achieve it with x-editable however it gives me an issue as per the picture below. I believe it is sth to do with my url defined in main.js script.
Any ideas how can I solve it ? I would like to use django model save function because I use it for other further reasons.
This is when I click on substage value and x-editable jquery works:
but it does not SAVE new value:
Terminal returns:
[08/May/2016 17:06:03]"POST /post HTTP/1.1" 404 2027
Below is part of my templates code:
{% for substage in trsubstage.substages_related %}
{% for zone in zones %}
{% if zone == substage.stage.zone %}
<td style="width:40px" align="center">
<div id="substage">
<a href="#" data-pk="{{ substage.id }}" data-type="text" >
{{ substage.substage_value }}</a>
</div>
</td>
{% endif %}
{% endfor %}
{% endfor %}
here is my main.js code:
$(document).ready(function() {
//toggle `popup` / `inline` mode
$.fn.editable.defaults.mode = 'popup';
$('#substage a').editable({
type: 'text',
name: 'username',
url: '/post',
title: 'Enter username'
});
});
here are my urls:
urlpatterns = [
url(r'^$', views.MainStatusView.as_view(), name='mainstatus'),
]
and here is my model Substage:
class SubStage(models.Model):
tablerow_substage = models.ForeignKey(TRSubStage)
stage = models.ForeignKey(Stage)
substage_value = models.PositiveSmallIntegerField(default=0)
created_date = models.DateField(auto_now_add= True)
created_time = models.TimeField(auto_now_add= True)
def __str__(self):
return '%s.%s.%s' % (self.stage.zone,
self.stage.tablerow_stage.stage_name,
self.tablerow_substage.substage_num)
def __init__(self, *args, **kwargs):
super(SubStage, self).__init__(*args, **kwargs)
self.value_original = self.substage_value
def save(self, **kwargs):
with transaction.atomic():
response = super(SubStage, self).save(**kwargs)
if self.value_original != self.substage_value:
substage_log = SubStageLog()
substage_log.substage = self
substage_log.substage_value = self.value_original
substage_log.save()
return response
class SubStageLog(models.Model):
substage = models.ForeignKey(SubStage)
substage_value = models.PositiveSmallIntegerField(default=0)
update_date = models.DateField(auto_now_add= True)
update_time = models.TimeField(auto_now_add= True)
def __str__(self):
return '%s | %s | %s' % (self.substage, self.update_date, self.update_time)
# to change str(self.id) to self.slug (but I need to add slug attribute to RoomLog)
def get_absolute_url(self):
return '/mods/' + str(self.id) + '/'
You do not have a url called "post" in your urls.py so your js functions but the request has no idea where to send your data.
Ok,
Below is updated code and it works fine now so I can save the value :-)
template:
{% for substage in trsubstage.substages_related %}
{% for zone in zones %}
{% if zone == substage.stage.zone %}
<td style="width:40px" align="center">
<div id="substage">
<a href="#" data-pk="{{ substage.id }}" data-type="text" >
{{ substage.substage_value }}</a>
</div>
</td>
{% endif %}
{% endfor %}
{% endfor %}
</tr>
{% endfor %}
main.js
$(document).ready(function() {
//toggle `popup` / `inline` mode
$.fn.editable.defaults.mode = 'popup';
$('#substage a').editable({
type: 'text',
name: 'username',
url: '/main/dupa/',
title: 'Enter username'
});
});
urls.py
urlpatterns = [
url(r'^$', views.MainStatusView.as_view(), name='main'),
url(r'^dupa/$', views.dupa, name='dupa'),
]
views.py
#csrf_exempt
def dupa(request):
if request.POST:
z = SubStage.objects.get(pk=request.POST.get('pk'))
z.substage_value = int(request.POST.get('value'))
z.save()
return HttpResponseRedirect('/main/')