How to display only some columns of Django model in a HTML template?
And also: how do I perform a function on one of the records? (amount)?
Right now I'm displaying a whole table of model like that:
my models.py
class Tabela(models.Model):
block_id = models.CharField(max_length=64)
timestamp = models.DateTimeField()
type = models.CharField(max_length=32)
link = models.CharField(max_length=64)
link_as_account = models.CharField(max_length=100)
account = models.CharField(max_length=100)
amount = models.CharField(max_length=64)
def __str__(self):
return self.block_id
My views.py
def search_results(request):
model = Tabela
query_addresse = request.GET.get('addressee', None)
query_hash = request.GET.get('hash', None)
if not query_hash and not query_addresse and request.method == 'GET':
return render(request, 'nanosite/index.html', {})
if query_hash and request.method == 'GET':
if query_addresse:
result = Tabela.objects.filter(account=query_addresse, block_id=query_hash)
else:
result = Tabela.objects.filter(block_id=query_hash)
field_names = [f.name for f in model._meta.get_fields()]
data = [[getattr(ins, name) for name in field_names]
for ins in result]
elif query_addresse and request.method == 'GET':
result = Tabela.objects.filter(account=query_addresse)
field_names = [f.name for f in model._meta.get_fields()]
data = [[getattr(ins, name) for name in field_names]
for ins in result]
return render(request, 'nanosite/index.html', {'field_names': field_names, 'data': data})
My index.html
<div id="bottomhalf" class="table-responsive">
<table class="table table-sm table-dark table-hover">
<thead class="thead-light">
{% for head in field_names %}
<th scope="col">{{ head }}</th>
{% endfor %}
</thead>
<tbody>
{% for row in data %}
<tr scope="row">
{% for cell in row %}
<td>{{ cell }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
What I'd like to do is display only block_id, timestamp, account and amount in html. I've tried different approaches like using only the result part of views without field_names and data, but of course it didn't work.
My other question is, how can I modify the field amount and perform an operation on it to be displayed in template like amound divided by certain digit with a $ sign before it (for example if amount=1488 to be divided by 124 and displayed as '$12')?
Pass the queryset qs selecting the objects to display to the template and iterate over it to generate your table:
{% for obj in qs %}
<tr>
<td> {{obj.block_id}} </td>
<!-- etc ... -->
</tr>
{% endfor %}
Now, if you also want to pass a variable specifying the names of the fields of the object to tabulate, and in what order, you find out that the Django template engine is by design (!) incapable of doing that. You can either do what you are doing, and generate a list-of-rows in Python which you pass to the Template, or you need a Django custom template tag such as
#register.filter
def attr( obj, name):
return getattr( obj, name, '')
and then you can run an inner loop in your template
<tr>
{% for name in selected_field_names %}
<td> {{obj|attr:name}} </td>
{% endfor %}
</tr>
The answer to the second question, is to define a property on your model to return the field suitably transmogrified:
class Tabela(models.Model):
...
#property
def funny_amount(self):
val = self.amount/12.0
return f'$ {val:.2f}'
and refer to {{obj.funny_amount}} in your template
Related
I have a simple table with some rows:
My goal is to instantiate the current value of the quantity and eventually save the new data for all the lines.
At the moment I have a simple view:
#login_required
def compilaDocMultiRow(request,pk):
member = get_object_or_404(testaDoc, pk=pk)
family = corpoDoc.objects.filter(doc=pk)
if request.method == "POST":
form = multiCorpoDocForm(request.POST or None)
if form.is_valid():
reg = form.save(commit=False)
reg.doc_id = member.pk
reg.save()
return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
else:
print(form.errors)
else:
form = multiCorpoDocForm()
return render(request, "compilaDocMultiRow.html", {'family':family, 'member':member, 'form':form})
Is there a way to do this using only Django?
EDIT 1
I was able to instantiate the value with widget tweaks. I am left with the problem of passing the pk of the line to the form and saving the value.
This is the html code:
{% for item in family %}
<tr>
<td>{{ item.item}}</td>
<td>{{ item.desc }}</td>
{% with field=form.qt %}
<td width="15%">{% render_field field class="form-control" placeholder=item.qt %}
</td>
{% endwith %}
<td></td>
<td></td>
</tr>
{% endfor %}
I want to upload an excel file containing 4 columns and display each column in different page.
views.py
def upload(request):
if "GET" == request.method:
return render(request, 'myapp/upload.html', {})
else:
excel_file = 'WBSdetails.xlsx'
pd.read_excel(excel_file, sheet_name = 'ItemDetails')
return render(request, 'myapp/structuremaster.html')
def structure(request):
structures=ConVehicleMaster.objects.all()
context={
'structures':structures
}
return render(request, 'myapp/structuremaster.html', context)
models.py
class Excel(models.Model):
structure = models.CharField(("Structure"), max_length=150)
segment = models.CharField(("Segment"), max_length=150)
subsegment = models.CharField(("SubSegment"), max_length=150)
element = models.CharField(("Element"), max_length=150)
structuremaster.html
<tbody>
{% for row in WBSdetails %}
{% for cell in row %}
<tr>
<td>{{ cell.structure }}</td>
</tr>
{% endfor %}
{% endfor %}
</tbody>
I am new to django and have very little idea. Any help will be appreciated.
I am new in Django, I'm making an item-category exercise. each item belongs to a category via a foreign key.I'm not able to understand problem in my code during submission of item detail. I'm getting an error "FOREIGN KEY constraint failed".
I wrote the code for models.py which is working fine in the admin dashboard of Django, but if same thing I'm trying to implement by HTML form page, I'm getting error.
models.py
class ColorCat(models.Model):
name = models.CharField(max_length=20, default="other")
def __str__(self):
return self.name
class ListItems(models.Model):
name = models.CharField(max_length=25, default='item')
item_cat = models.ForeignKey(ColorCat, on_delete=models.CASCADE, default=0, null=True,blank=True)
views.py
def index(request):
list = ListItems.objects.all()
cat = ColorCat.objects.all()
return render(request, 'colorlist.html', {'color': cat, 'item':list })
def colorlist(request):
new_list = ListItems
new_cate = ColorCat
if request.method=="POST":
item = str(request.POST["item"])
cat = str(request.POST["category"])
f_key = ColorCat.objects.filter(name="orange").get()
new_list(name="item").save()
new_list(item_cat=f_key.id).save()
item = ListItems.objects.all()
color = ColorCat.objects.all()
return render(request, 'colorlist.html', {"item": item, "color": color})
def addcat(request):
if request.method=="POST":
newcat = str(request.POST["name"])
ColorCat(name = newcat).save()
item = ListItems.objects.all()
color = ColorCat.objects.all()
return render(request, 'colorlist.html', {"item":item, "color":color})
colorlist.html
{% extends 'base.html'%}
{% block content%}
<h2>Welcome in color cards</h2>
<form action="addcat" method="POST">
{% csrf_token %}
<lable>add new cat<input type="text" name="name"></lable><br>
<label>submit<input type="submit"></label>
</form>
<form action="colorlist" method="post">
{% csrf_token %}
<label>new item<input type="text" name="item"></label><br>
<label>cat<input type="text" name="category"></label><br>
<label>add item<input type="submit"></label>
</form>
<!--see saved result-->
<table>
<tr>
<th>categories</th>
</tr>
{% for cat in color %}
<tr>
<td>{{cat.name}}</td>
</tr>
{% endfor %}
</table>
<table>
<tr>
<th>category item </th>
</tr>
{% for clr in color %}
{% for itm in item %}
<tr>
{% if clr.name == itm.category %}
<td>{{itm.name}}</td>
{%endif%}
</tr>
{% endfor %}
{% endfor %}
</table>
{% endblock %}
Error
IntegrityError at /color/colorlist
FOREIGN KEY constraint failed
I haven't gone allof your code - there's lots of irrelevant stuff - but I've noticed a couple of errors:
definition of ListItems model, it doesn't make sense to define a default value for field item_cat, it'll try to link the instance with a ColorCat instance with id 0 which probably doesn't exist
item_cat = models.ForeignKey(ColorCat, on_delete=models.CASCADE, null=True, blank=True)
saving a new_list - use ColorCat instance instead of its id
new_list(item_cat=f_key).save()
While rendering a table of items, if the value for field X is not defined, it is rendered as a select element.
Django makes a query for each select element and these can add up and cause delays in large tables.
What is the best way to reduce the number of queries?
views.py
from rest_framework import renderers
from rest_framework.response import Response
class ItemViewSet(viewsets.ModelViewSet):
queryset = models.Item.objects.select_related("bought_by")
serializer_class= serializers.ItemSerializer
filterset_fields = ("bought_by")
renderer_classes = [renderers.JSONRenderer, renderers.BrowsableAPIRenderer, renderers.TemplateHTMLRenderer]
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
if request.accepted_renderer.format == "html":
items = list()
for item in queryset:
items.append({"serializer": self.get_serializer(item), "item": item})
return Response(
{
"items_info": items,
"style": {"template_pack": "rest_framework/inline/"},
},
template_name="myapp/items_list.html",
)
else:
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
items_list.html
{% load static %}
{% load rest_framework %}
{% if items_info %}
{% csrf_token %}
<table id="Items_Table" class="table">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Active</th>
<th scope="col">Bought By</th>
</tr>
</thead>
<tbody>
{% for pair in items_info %}
<tr scope="row">
<td>{{ pair.item.name }}</td>
<td>{{ pair.item.active }}</td>
<td>
<form action="{{ item.url }}" method="PATCH">
{% render_field pair.serializer.bought_by style=style %}
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p class="text-center">No items to show.</p>
{% endif %}
If there are three items, one query each will be made to get serializer.bought_by. I thought Django/DRF would just reuse the value, but it's querying for each loop.
Trying to pass "serializer-bought-by": self.get_serializer().bought_by in the response, I get an AttributeError: 'ItemSerializer' object has no attribute'bought_by'
Printing the serializer I can see:
>>>print(self.get_serializer())
ItemSerializer(context={'request': <rest_framework.request.Request object>, 'format': None, 'view': <myapp.views.ItemViewSet object>}):
url = HyperlinkedIdentityField(view_name='myapp:item-detail')
name= CharField(unique=True, max_length=50)
active = BooleanField(required=False)
bought_by = SlugRelatedField(allow_null=True, queryset=<QuerySet [<Buyer: James>, <Buyer: John>, ...]>, required=False, slug_field='name')
Is there a way to pass the bought_by to the template?
Or do I have to use JS; render the form field outside the loop and clone/duplicate somehow?
---Edits---
As per Endre's request: models.py
class Buyer(models.Model):
name = models.CharField(unique=True, max_length = 20)
class Item(models.Model):
name = models.CharField(unique=True, max_length = 50)
active = models.BooleanField(default=True)
bought_by = models.ForeignKey(Buyer, null=True, blank=True, to_field="name",)
You cannot access the value of fields directly in the serializer. You should use serializer.data['bought_by'] instead. Better of, don't pass the serializer to the template, instead pass the serializer.data.
As for the queries in the template, no query is made to the DB to get the bought_by since it's already included in the serializer data. You're just showing one field name from bought_by, which is already preloaded in the serializer data. The select_related you applied also ensures that multiple queries are not made to fetch bought_by during serialization.
I really need help...i ve been asking a lot of times for help and looked on google and i haven't found anything....
I want when the I click on the Table name i want to get the ID and number and obtain the details about the that table.
table_base.html
{% extends 'base.html' %}
{% block content %}
<br>
<div class="container">
<div class="jumbotron">
<h1> {{ table_name }} List</h1>
{% if list_tables %}
<table>
<thead>
<th>Id</th>
<th>Name</th>
<th>Date</th>
</thead>
{% for list in list_tables %}
<tr>
<td><pre>{{ list.id }}</pre></td>
<td><pre><a class="btn-link" href="{% url 'tables:details' list.id %}">{{ list.name }}</a></pre></td>
<td> <pre>{{ list.date }}</pre></td>
</tr>
{% endfor %}
</table>
{% else %}
<p> No Records Found</p>
{% endif %}
</div>
</div>
{% endblock %}
views.py
def table_base(request):
table_name = Crawledtables._meta.db_table
list_tables = Crawledtables.objects.order_by('id')
return render(request, 'tables/table_base.html', {'table_name': table_name,
'list_tables': list_tables})
class AboutDetail(DetailView):
model = Crawledtables
pk_url_kwarg = 'table_id'
template_name = 'tables/table_list.html'
def __init__(self, **kwargs):
super(AboutDetail, self).__init__(**kwargs)
def get_object(self):
if 'table_id' not in self.kwargs:
return Crawledtables.objects.get(id=1)
else:
return Crawledtables.objects.get(id=self.kwargs['table_id'])
class Details(ListView):
model = AllTables
template_name = 'tables/table_list.html'
context_object_name = 'details'
paginate_by = 15
queryset = AllTables.objects.all()
tables/urls.py
urlpatterns = [
url(r'^$', views.table_base, name='tables'),
url(r'^(?P<table_id>\d+)$', views.AboutDetail.as_view(), name='id-details'),
url(r'^(?P<table_id>\d+)/details$', views.Details.as_view(), name='details'),]
Basically i want to get the value of the table_id and make a new function in views where i get the table info based on what table_id i have...
If i have table_id 2 i want to the data of table_name2...
if i have table_id 3 i want to the data of table_name3...and so on.
I want this data to list it on a new template that i will create.
Something like this for the views.py:
I will get the table_id = 2 and then i use table_id to get the table name that has that id. When i get the table name..i will put it in the models.py in db_table to get that specific table details.
def details(request, table_id):
tbl_name = Crawledtables.objects.get(id=table_id)
AllTables._meta.db_table = tbl_name
query = AllTables.objects.order_by('id')
tbl_query = {'t_details': query}
return render(request, 'tables/table_list.html', context=tbl_query)
Thank you in advance
UPDATE:
I almost figure it out...but i still missing 1 more thing.
views.py
class Details(ListView):
AllTables._meta.db_table = 'table_name_1'
# AllTables._meta.db_table = 'table_name_2'
# AllTables._meta.db_table = 'table_name_3'
model = AllTables
template_name = 'tables/table_list.html'
context_object_name = 'details'
paginate_by = 15
queryset = AllTables.objects.all()
I need to switch between those 3 tables based on the table_id that i get from
views.AboutDetail or the table_base.html when the user clicks on the table_name
Something like this:
class Details(ListView):
if AboutDetail.pk_url_kwarg == 1:
AllTables._meta.db_table = 'table_name_1'
if AboutDetail.pk_url_kwarg == 2:
AllTables._meta.db_table = 'table_name_2'
if AboutDetail.pk_url_kwarg == 3:
AllTables._meta.db_table = 'table_name_3'
else:
pass