create a particular detail view - django

i need help to formulate a query.
my models are this:
class Rider(models.Model):
id_rider = models.IntegerField(default = 0,blank= True, primary_key=True)
first_name = models.CharField(max_length = 256,blank= True)
[...]
def str(self):
return self.display_name
class Risultato(models.Model):
TYPE_CHOICES = (('SR','sr'),('ITT', 'itt'),('HC', 'hc'),('1C','1c'),('TTT','ttt'))
id_rider = models.ForeignKey(Rider,related_name='rider', on_delete=models.CASCADE)
id_stage = models.ForeignKey(Stage,related_name='team', on_delete=models.CASCADE)
type_ris = models.CharField(choices=TYPE_CHOICES,max_length = 256,blank= True)
rank = models.IntegerField(default = 0,blank= True)
punti = models.IntegerField(default = 0,blank= True)
def __str__(self):
return self.id_raider,self.id_stage,self.rank
i need to create a Detail View to details of riders, somethings like this:
-------------------------------------------
Rider: [display_name]
age : [age]
...
...
--------SCORE HISTORY-----
stage sr/itt ttt hc 1c tot
1 100 null 10 0 110
2 null 20 5 10 35
Thanks in advance!!
UPDATE
i add the view and the template, but i can't see the table
view.py:
class RiderDetails(DetailView):
model = Rider
template_name = 'game/rider_detail.html'
def get_context_data(self, *args, **kwargs):
context_data = super().get_context_data(**kwargs)
context_data['risultato_qs'] = Risultato.objects.filter(id_rider=self.object)
return context_data
rider_detail.html:
{% extends 'game/base.html'%}
{% block content %}
<h1>{{ rider.display_name }}</h1>
<table>
<tbody>
{% for risultato in risultato_qs %}
<tr>
<td>{{ risultato.stage }}</td>
<td>{{ risutato.type_ris }}</td>
<td>{{ risutato.punti }}</td>
... etc ...
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
screen page

A quick example might look like:
class RiderDetails(DetailView):
model = Rider
template_name = 'path_to_rider_template'
def get_context_data(self, *args, **kwargs):
context_data = super().get_context_data(*args, **kwargs)
context_data['risultato_qs'] = Risultato.objects.filter(id_rider=self.object)
return context_data
Then in your template you can, for example:
... Rider details here ...
<table>
<tbody>
{% for risultato in risultato_qs %}
<tr>
<td>{{ risultato.stage }}</td>
<td>{{ risutato.type_ris }}</td>
... etc ...
</tr>
{% endfor %}
</tbody>
</table>

Related

Regrouping in Django Template With Grouping in views

I have a model with different forginekey wish I could like to group it by student. I was successfully done that but in my template, I want to nested the result or regroup it by subject according to students.
model.py
class Result(models.Model):
examtype = models.ForeignKey(ExamType, on_delete=models.CASCADE)
student = models.ForeignKey(Student, on_delete=models.CASCADE)
subject = models.ForeignKey(SubjectAppointment, on_delete=models.CASCADE)
test = models.FloatField()
exam = models.FloatField()
total = models.FloatField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def save(self, *args, **kwargs):
self.total = self.test + self.exam
super().save(*args, **kwargs)
def __str__(self):
return self.student.matricnumber
def get_result_total(self):
return int(float(f'{self.test + self.exam}'))
views.py
def ReportView(request):
template_name = 'teacher/report.html'
score = Result.objects.values('student', 'exam', 'test', 'subject__subject__name').annotate(student_totalscore=Sum('total')).annotate(attending=Count('subject'))
print(score)
context = {
'score': score,
}
return render(request, template_name, context)
report.html
{% for s in score %}
{% regroup score by s.student as student_list %}
{% for a in student_list %}
<!-- {% for b in a.list %} -->
<tr>
<td>{{ b.subject__subject__name }}</td>
<td>{{ b.test }}</td>
<td>{{ b.exam }}</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<!-- {% endfor %} -->
{% endfor %}
{% endfor %}

Django, How to display 2 models on a Listview

I am working with my first Django project
**model.py**
class product(models.Model):
product_code = models.CharField(max_length=15, unique=True)
product_name = models.CharField(max_length=100)
class stock_product(models.Model):
product_code = models.CharField(max_length=15)
branch_code = models.CharField(max_length=5)
quantity = models.IntegerField(default=0)
price = models.DecimalField(default=0)
**views.py**
class productList(ListView):
model = product
template_name = 'product/product_list.html'
def get_queryset(self):
queryset = super(productList, self).get_queryset()
self.filterset = productFilter(self.request.GET, queryset=queryset)
return self.filterset.qs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['filter'] = self.filterset
return context
**product_list.html**
{% for alist in product_list %}
<tr>
<td>{{ alist.product_code }}</td>
<td>{{ alist.product_name }}</td>
<td>{{ alist.price }}</td>
<td>{{ alist.quantity }}</td>
</tr>
{% endfor %}
Sample Data in tables
**product**
['11111','paper'
'22222','Wood']
**stock_product**
['11111','BR1',150, 10
'11111','BR2',120, 10
'11111','BR3',100, 15
'22222','BR1',50, 200
'22222','BR2',70, 200
'22222','BR3',40, 250]
I want to get price and quantity from stock_product model, we can change branch_code by user
how can we do Plese help.
Thanks, But I want display only user branch (if user branch 'BR1' display only 'BR1')
**views.py**
class productList(ListView):
model = product
template_name = 'product/product_list.html'
def get_queryset(self):
queryset = super(productList, self).get_queryset()
self.filterset = productFilter(self.request.GET, queryset=queryset)
return self.filterset.qs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
stock = stock_product.objects.all(). # this line added
context['filter'] = self.filterset
context['stock'] = stock # this line added
return context
Now having this you can access the stock from your template:
**product_list.html**
{% for alist in product_list %}
<tr>
<td>{{ alist.product_code }}</td>
<td>{{ alist.product_name }}</td>
<td>{{ alist.price }}</td>
<td>{{ alist.quantity }}</td>
</tr>
{% endfor %}
{% for s in stock %}
<tr>
<td>{{ s.product_code }}</td>
<td>{{ s.product_branch }}</td>
</tr>
{% endfor %}
BUT I have to just do not recommend you do this. Why? well, I suppose you want to make the match of the product_code. Except of that you should use ForeignKey on the models and so you will have a much simple code and logic:
Model:
class stock_product(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE) # this
branch_code = models.CharField(max_length=5)
quantity = models.IntegerField(default=0)
price = models.DecimalField(default=0)
And so now without modifying your view you could do this on the template to access the data:
template:
{% for alist in product_list %}
<tr>
<td>{{ alist.product_code }}</td>
<td>{{ alist.product_name }}</td>
<td>{{ alist.stock_product.branch_code }}</td>
<td>{{ alist.stock_product.quantity }}</td>
<td>{{ alist.stock_product.price }}</td>
</tr>
{% endfor %}
how about change the model with using foreign keys.
and use the django_tables2.
# **model.py**
from django.db import models
class product(models.Model):
product_code = models.CharField(max_length=15, unique=True)
product_name = models.CharField(max_length=100)
class stock_product(models.Model):
# product_code = models.CharField(max_length=15)
product = models.ForeignKey(product, on_delete=models.CASCADE)
branch_code = models.CharField(max_length=5)
quantity = models.IntegerField(default=0)
price = models.DecimalField(default=0)
this is table code for django_tables2.
class DetailedDataTable(tables.Table):
product_code = tables.Column(verbose_name='product_code', accessor='product_id')
product_name = tables.Column(verbose_name='product_name', accessor='product_id')
class Meta:
model = stock_product
template_name = "django_tables2/bootstrap.html"
fields = ('product_code', 'product_name', 'branch_code', 'quantity', 'price')
def render_product_code(self,value, record):
return product.objects.get(id=value).product_code
def render_product_name(self,value, record):
return product.objects.get(id=value).product_name
and this is view
def view(request):
template_name = 'template.html'
query_set = stock_product.objects.all()
table = DetailedDataTable(qs)
context={
'table':table,
}
return render(request, template_name, context)
and this is for template page uses.
{# tutorial/templates/tutorial/people.html #}
{% load render_table from django_tables2 %}
<!doctype html>
<html>
<head>
<title>List</title>
</head>
<body>
{% render_table table %}
</body>
</html>
:)

Django: Two questions on extending ListView with get_context_data

I tried something similar to this. I have three models:
class PartBase(models.Model):
name = models.CharField('Name', max_length=120)
price = models.DecimalField("Price per part", decimal_places=2, max_digits=6)
class Sett(models.Model):
name = models.CharField('Name', max_length=120)
class PartRelation(models.Model):
part = models.ForeignKey(PartBase, on_delete=models.CASCADE)
qty = models.PositiveIntegerField("Quantity")
sett = models.ForeignKey(Sett, related_name='setts', on_delete=models.SET_NULL, null=True)
def get_position_price(self):
return self.qty * self.part.price
now I want to add the price of all the items in a Sett in a row in my HTML.
{% extends 'base.html' %}
{% block title %}
Add Set
{% endblock title %}
{% block content %}
<table class="table">
<tr>
<th>Set Name</th>
<th>Total price</th>
</tr>
{% for set in setts %}
<tr>
<td>{{ set.name }}</td>
<td>{{ set.test }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
I wanted to override the get_context_data method somehow like this:
class SetListView(ListView):
model = Sett
context_object_name = "setts"
def get_context_data(self,**kwargs):
context = super(SetListView, self).get_context_data(**kwargs)
context['test'] = "price"
return context
But I only get an empty field in the template (which I assumed would have the word "price".
I can access the price in the shell via
for s in Sett.objects.all():
pr = PartRelation.objects.filter(sett=s)
price = 0
for p in pr:
price += p.get_position_price()
But how would I put the code from the shell in the get_context_data() function, so that for every row I get the corresponding total price?
This did the trick:
class SetListView(ListView):
model = Sett
context_object_name = "setts"
def get_context_data(self, **kwargs):
context = super(SetListView, self).get_context_data(**kwargs)
for s in context["setts"]:
pr = PartRelation.objects.filter(sett=s)
s.total_price = 0
for p in pr:
s.total_price += p.get_position_price()
return context
I would gladly get feedback if that is a good approach (and why not/how to do better).

Django model cross reference in templatre

Ok So my mind is going to mush...
I have 2 models. One is a card location and the other holds card types. I've got a view and template which display's the cards in a specific chassis. What I can't seem to get to work is the foreign key reference. I want to display the CardType.sName in the template.
I'm certain i've just done something stupid ...
Models.py:
class CardLocation(models.Model):
chassis = models.ForeignKey(Chassis)
slot = models.CharField(max_length=20)
slot_sub = models.CharField(max_length=20)
CardType = models.ForeignKey(CardType)
PartNum = models.CharField(max_length=200)
ProdID = models.CharField(max_length=200)
versID = models.CharField(max_length=200)
serialNum = models.CharField(max_length=200)
cleiCode = models.CharField(max_length=200)
lastSeen = models.DateTimeField()
isActive = models.BooleanField(default=0)
def __unicode__(self):
return self.slot
class CardType(models.Model):
sName = models.CharField(max_length=5)
lName = models.CharField(max_length=200)
description = models.CharField(max_length=200)
def __unicode__(self):
return self.sName
views.py
class DetailView(generic.ListView):
model = CardLocation
template_name = 'chassis/detail.html'
context_object_name = 'cardLoc'
def get_queryset(self):
#chassis_id = get_object_or_404(CardLocation, chassis_id__iexact=self.args[0])
chassis_id = self.args[0]
return CardLocation.objects.filter(chassis_id=chassis_id)
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super(DetailView, self).get_context_data(**kwargs)
# Add in the
context['chassisQ'] = Chassis.objects.get(id=self.args[0])
#context['CardType'] = CardType.objects.order_by()
return context
detail.html
{% load staticfiles %}
<h2>
<table>
<tr><td>Name:</td><td>{{ chassisQ.name }}<td></tr>
<tr><td>Owner:</td><td>{{ chassisQ.owner }}<td></tr>
<tr><td>ip Adress:</td><td>{{ chassisQ.ipAddr }}<td></tr>
<tr><td>Last updated:</td><td>{{ chassisQ.lastSeen }}<td></tr>
</table>
</h2>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
{% if cardLoc %}
<table border=1>
<tr><td>slot</td><td>Type</td><td>Part Number</td><td>Product ID/</td><td>Version ID</td><td>Serial Num</td><td>CLEI code</td></tr>
{% for card in cardLoc %}
<tr>
<td align="right">{{ card.slot }}</td>
<td>Type {{ card.cardtype__set.all.sName }} </td> <!-- DISPLAY sName HERE -->
<td>{{ card.PartNum }}</td>
<td align="right">{{ card.ProdID }}/</td>
<td align="left">{{ card.versID }}</td>
<td>{{ card.serialNum }}</td>
<td>{{ card.cleiCode }}</td>
</tr>
{% endfor %}
</table>
{% else %}
<p>No cards are available...</p>
{% endif %}
A Card has numerous CardTypes (as it's a ForeignKey relationship), not just one. You have:
<td>Type {{ card.cardtype__set.all.sName }} </td>
You need to loop through all the CardTypes related to the Card:
{% for card in cardLoc %}
...
{% for cardtype in card.cardtype__set.all %}
<td>Type {{ cardtype.sName }}</td>
{% endfor %}
...
{% endfor %}

Django Templates - Accessing a M2M attribute and value by name

I am trying to simply access a the values and names of a Many to Many Model in a template by name. Can someone show me what I'm doing wrong.
I have a model called IP. This model can have several attributes. I want to call the "value" of a a particular attribute.
For example:
I have an IP Block named Foo. Foo has an attribute "bar" with a value of "good luck".
How can I refer to the named attribute in a M2M and it's value from a template??
This works but YUCK!!
{% for attr in ip.attributes.all %}
{% ifequal attr.attribute.name 'vendor' %}
<td>{{ attr.value }}</td>
{% endifequal %}
{% endfor %}
Thanks so much!!
I have a models.py which looks similar to this.
models.py
VALID_IP_TYPES = (("hard", "Hard IP"),
("soft", "Soft IP"),
("verif", "Verification IP"))
class AttributeType(models.Model):
name = models.CharField(max_length = 32, primary_key = True)
ip_type = models.CharField(max_length = 16, choices = \
tuple(list(VALID_IP_TYPES) + [("all", "All IP")]))
def __unicode__(self):
return u'%s' % (self.name)
class Attribute(models.Model):
attribute = models.ForeignKey(AttributeType)
value = models.CharField(max_length = 255)
def __unicode__(self):
return u'%s : %s' % (self.attribute, self.value)
class IP(models.Model):
ip_type = models.CharField(max_length = 16, choices = \
tuple(list(VALID_IP_TYPES),
help_text = "Type of IP")
name = models.CharField(max_length = 32, help_text = "Generic Name")
attributes = models.ManyToManyField(Attribute)
def __unicode__(self):
return u'%s' % (self.name)
The relevant views.py
def search(request):
context = RequestContext(request)
if not request.POST:
form = { 'form' : IPSearch() }
return render_to_response('ip_catalog/search.html', form,
context_instance = context)
else:
form = IPSearch(request.POST)
if form.is_valid():
response_dict = {}
cd = form.cleaned_data
ips = ips.filter(**cd)
response_dict.update({'ips':ips})
response_dict.update({'success': True })
return render_to_response('ip_catalog/results.html', response_dict,
context_instance = context)
And finally the template snippet I am struggling with..
{% for ip in ips %}
<tr>
<td>{{ ip.name }}</td>
<td>{{ ip.release_id }}</td>
<td>{{ ip.release_date }}</td>
<!-- THIS WORKS BUT THERE MUST BE A BETTER WAY! -->
{% for attr in ip.attributes.all %}
{% ifequal attr.attribute.name 'vendor' %}
<td>{{ attr.value }}</td>
{% endifequal %}
{% endfor %}
<!-- THIS DOESN'T WORK! -->
<td>{{ ip.attributes.node.value }}</td>
<!-- OR THIS! -->
<td>{{ ip.attribute_id.foundry }}</td>
<!-- OR THIS.. ! -->
<td>{{ ip.attribute.process }}</td>
</tr>
{% endfor %}
Accessing a ManyToManyField in a model results in a manager, which you can use .filter() et alia on. Since most of these require at least one argument, you can't call them in a template. Create a template tag instead.
You can't do this well in templates. This is restricted by the design philosophy of Django.
The only way to do this is writing a custom template tag or helper function in model like get_vendor.
Checkout How do I perform query filtering in django templates