I want to display date in table which is foreign key in this case and when I do this as result I see the date with information that it is object of different table. Which I don't want.
I would appreciate help with this.
class Factclaimcases(models.Model):
idfactclaimcase = models.IntegerField(db_column='IdFactClaimCase', primary_key=True) # Field name made lowercase.
idtechnican = models.ForeignKey(Dimtechnican, models.DO_NOTHING, db_column='IdTechnican') # Field name made lowercase.
thedate = models.ForeignKey(Dimdate, models.DO_NOTHING, db_column='TheDate') # Field name made lowercase.
description = models.CharField(db_column='Description', max_length=50) # Field name made lowercase.
manufacturedef = models.TextField(db_column='ManufactureDef', blank=True, null=True) # Field name made lowercase. This field type is a guess.
doc = models.BinaryField(db_column='Doc', blank=True, null=True) # Field name made lowercase.
<div class="container">
<table>
{% for item in query_results %}
<tr>
<td>{{ item.idfactclaimcase }}</td>
<td>{{ item.thedate }}</td>
<td>{{ item.description }}</td>
</tr>
{% endfor %}
</table>
</div>
def index(request):
query_results = Factclaimcases.objects.all()
context = {
'query_results': query_results,
}
return render(request, 'index.html', context)
class Dimdate(models.Model):
thedate = models.DateField(db_column='TheDate', primary_key=True) # Field name made lowercase.
theday = models.IntegerField(db_column='TheDay', blank=True, null=True) # Field name made lowercase.
thedayname = models.CharField(db_column='TheDayName', max_length=30, blank=True, null=True) # Field name made lowercase.
theweek = models.IntegerField(db_column='TheWeek', blank=True, null=True) # Field name made lowercase.
theisoweek = models.IntegerField(db_column='TheISOWeek', blank=True, null=True) # Field name made lowercase.
thedayofweek = models.IntegerField(db_column='TheDayOfWeek', blank=True, null=True) # Field name made lowercase.
themonth = models.IntegerField(db_column='TheMonth', blank=True, null=True) # Field name made lowercase.
themonthname = models.CharField(db_column='TheMonthName', max_length=30, blank=True, null=True) # Field name made lowercase.
thequarter = models.IntegerField(db_column='TheQuarter', blank=True, null=True) # Field name made lowercase.
theyear = models.IntegerField(db_column='TheYear', blank=True, null=True) # Field name made lowercase.
thefirstofmonth = models.DateField(db_column='TheFirstOfMonth', blank=True, null=True) # Field name made lowercase.
thelastofyear = models.DateField(db_column='TheLastOfYear', blank=True, null=True) # Field name made lowercase.
thedayofyear = models.IntegerField(db_column='TheDayOfYear', blank=True, null=True) # Field name made lowercase.
You render it by accessing the field you want to render, so:
<div class="container">
<table>
{% for item in query_results %}
<tr>
<td>{{ item.idfactclaimcase }}</td>
<td>{{ item.thedate.thedate }}</td>
<td>{{ item.description }}</td>
</tr>
{% endfor %}
</table>
</div>
You can use the |date template filter [Django-doc] to specify how to render the date, for example:
<div class="container">
<table>
{% for item in query_results %}
<tr>
<td>{{ item.idfactclaimcase }}</td>
<td>{{ item.thedate.thedate|date:"Y-m-d" }}</td>
<td>{{ item.description }}</td>
</tr>
{% endfor %}
</table>
</div>
In your view, you can select the Dimdate columns in the same query with .select_related(…) [Django-doc]:
def index(request):
query_results = Factclaimcases.objects.select_related('thedate')
context = {
'query_results': query_results,
}
return render(request, 'index.html', context)
Related
We have migrated some database-tables from our productiv environment to the django ORM and auto sync this tables outside of django. → This works well so far, but we have troubles in django to connect this tables (Models) correctly to each other.
models.py
class SsdaSdgadr(models.Model):
sda_sdgid = models.ForeignKey(SsdgSendung, on_delete=models.CASCADE, blank=True, null=True)
sda_satid = models.CharField(max_length=4, blank=True, null=True)
sda_adrid = models.ForeignKey(SadrAdresse, on_delete=models.CASCADE, blank=True, null=True)
sda_ref = models.CharField(max_length=35, blank=True, null=True)
sda_termbis = models.DateField(blank=True, null=True)
sda_termvon = models.DateField(blank=True, null=True)
class Meta:
db_table = 'ssda_sdgadr'
unique_together = (('sda_sdgid', 'sda_satid'),)
class SsdgSendung(models.Model):
sdg_sdgid = models.CharField(primary_key=True, max_length=30)
sdg_konz = models.CharField(max_length=12, blank=True, null=True)
class Meta:
db_table = 'ssdg_sendung'
class SadrAdresse(models.Model):
adr_adrid = models.IntegerField(primary_key=True)
adr_name1 = models.CharField(max_length=35, blank=True, null=True)
adr_name2 = models.CharField(max_length=35, blank=True, null=True)
class Meta:
db_table = 'sadr_adresse'
Sample Data
SsdaSdgadr:
sdg_sdgid
sda_satid
sda_adrid
sda_ref
sda_termvon
sda_termbis
BL-1237781-BL-1
IV
169550
'00123/4539999'
''
''
BL-1237781-BL-1
SU
555555
''
01.12.2021
02.12.2021
BL-1237781-BL-1
CN
999999
'00123'
02.12.2021
13.12.2021
views.py
I used following raw SQL
Sendungen = SsdaSdgadr.objects.raw('''
SELECT
IV.id,
IV.sda_sdgid_id,
IV.sda_ref,
SU.id,
SU.sda_adrid_id as ABS,
SU.sda_termvon,
CN.id,
CN.sda_adrid_id as EMPF,
CN.sda_termbis
FROM
ssda_sdgadr IV
INNER JOIN ssdg_sendung on sdg_sdgid = IV.sda_sdgid_id
INNER JOIN ssda_sdgadr SU on SU.sda_sdgid_id = IV.sda_sdgid_id and SU.sda_satid="SU"
INNER JOIN ssda_sdgadr CN on CN.sda_sdgid_id = IV.sda_sdgid_id and CN.sda_satid="CN"
WHERE IV.sda_satid="IV"
GROUP BY
IV.id,
IV.sda_sdgid_id,
IV.sda_ref,
SU.id,
SU.sda_adrid_id,
SU.sda_termvon,
CN.id,
CN.sda_adrid_id,
CN.sda_termbis
ORDER BY
sdg_datum desc
''')
...
response = render(request, 'cust/home.html', {
'Sendungen': Sendungen,
})
return response
The result on the template works fine for the fields "SU.sda_termvon" & "CN.sda_termbis", but does not work for the field "sda_adrid" (→ Only the the result for IV.sda_adrid_id is displayed).
Template code
{% for la_item in Sendungen %}
<tr>
<td>{{ la_item.sda_sdgid.sdg_sdgid }}</td>
<td>{{ la_item.sda_ref }}</td> <!-- IV.sda_ref OKAY -->
<td>{{ la_item.sda_adrid.adr_adrid }}</td> <!-- is IV.sda_adrid NOT OKAY -->
<td>{{ la_item.sda_adrid.adr_adrid }}</td> <!-- is IV.sda_adrid NOT OKAY -->
<td>{{ la_item.sda_termvon|date }}</td> <!-- SU.sda_termvon OKAY -->
<td>{{ la_item.sda_termbis|date }}</td> <!-- CN.sda_termbis OKAY -->
</tr>
{% endfor %}
How can I access to the results "CN.sda_adrid_id" & "SU.sda_adrid_id" on template?
→ It look like that the ORM interprets the raw-SQL different than the database:
DB-Result & Desired result should look like this:
sda_sdgid_id
IV.sda_ref
SU.sda_adrid_id
CN.sda_adrid
SU.termvon
CN.termbis
BL-1237781-BL-1
1920192/4530210220/0881760357
555555
999999
01.12.2021
13.12.2021
My actual result look like this:
sda_sdgid_id
IV.sda_ref
IV.sda_adrid_id
IV.sda_adrid_id
SU.termvon
CN.termbis
BL-1237781-BL-1
1920192/4530210220/0881760357
169550
169550
01.12.2021
13.12.2021
I used this workaround (model property for "SsdaSdgadr"), which gave me the desired result:
models.py
class SsdaSdgadr(models.Model):
sda_sdgid = models.ForeignKey(SsdgSendung, on_delete=models.CASCADE, blank=True, null=True)
sda_satid = models.CharField(max_length=4, blank=True, null=True)
sda_adrid = models.ForeignKey(SadrAdresse, on_delete=models.CASCADE, blank=True, null=True)
sda_ref = models.CharField(max_length=35, blank=True, null=True)
sda_termbis = models.DateField(blank=True, null=True)
sda_termvon = models.DateField(blank=True, null=True)
class Meta:
db_table = 'ssda_sdgadr'
unique_together = (('sda_sdgid', 'sda_satid'),)
#property
def is_adr_su(self):
return SsdaSdgadr.objects.filter(sda_sdgid = self.sda_sdgid, sda_satid = "SU")
#property
def is_adr_cn(self):
return SsdaSdgadr.objects.filter(sda_sdgid = self.sda_sdgid, sda_satid = "CN")
views.py
Sendungen = SsdaSdgadr.objects.filter(Q(sda_satid__in=["IV"])).order_by('-sda_sdgid__sdg_datum')
...
response = render(request, 'cust/home.html', {
'Sendungen': Sendungen,
})
return response
Template code home.html
{% for la_item in Sendungen %}
<tr>
<td>{{ la_item.sda_sdgid.sdg_sdgid }}</td>
<td>{{ la_item.sda_ref }}</td> <!-- IV.sda_ref OKAY -->
{% for adr in la_item.is_adr_su %}
<td>{{ adr.sda_adrid.adr_adrid }}</td> <!-- SU.sda_adrid OKAY -->
<td>{{ adr.sda_termvon|date }}</td> <!-- SU.sda_termvon OKAY -->
{% endfor %}
{% for adr in la_item.is_adr_cn %}
<td>{{ adr.sda_adrid.adr_adrid }}</td> <!-- CN.sda_adrid OKAY -->
<td>{{ adr.sda_termbis|date }}</td> <!-- CN.sda_termbis OKAY -->
{% endfor %}
</tr>
{% endfor %}
I'm new to Django so please bear with me. I'm trying to create a view which lists JournalEntries which have type=BP. The list needs to include selected values from the LineItems that are related to each JournalEntry. Each JournalEntry with type=BP only ever has two related LineItems.
models.py
class JournalEntry(models.Model):
date = models.DateField(null=True, blank=False)
TYPE = (
('BP', 'Bank Payment'),
('YE', 'Year End'),
)
type = models.CharField(
max_length=2,
choices=TYPE,
blank=True,
default='0'
)
class LineItem(models.Model):
journal_entry = models.ForeignKey(JournalEntry, on_delete=models.PROTECT)
ledger = models.ForeignKey(Ledger, on_delete=models.PROTECT)
description = models.CharField(max_length=255, null=True, blank=True)
cr = models.DecimalField(max_digits=8, decimal_places=2, null=True, blank=True)
dr = models.DecimalField(max_digits=8, decimal_places=2, null=True, blank=True)
class Ledger(models.Model):
name = models.CharField(max_length=255)
views.py
def journalentries_show_all(request):
journal_entries = JournalEntry.objects.filter(type="BP")
context = {
'journal_entries': journal_entries,
}
return render(request, 'journal/journalentries_show_all.html', context)
My template journalentries_show_all.html
<ul>
{% for journal_entry in journal_entries %}
<li>{{ journal_entry.date }}</li>
<li>{{ ledger name from first line item in this journal_entry }}</li>
<li>{{ ledger name from second line item in this journal_entry }}</li>
<li>{{ description from first line item in this journal_entry }}</li>
<li>{{ description from second line item in this journal_entry }}</li>
{% endfor %}
</ul>
In this particular view I'm only interested in displaying JournalEntries which has type=BP, all of which only ever have two line items. Other types of JournalEntries have more LineItems, but those are dealt with in another view.
Basic Python iteration is enough for what your need
results = []
for entry in journal_entries:
results.append(entry.lineitem_set.all()[2]
Just that results list should do it in the context. .all()[2] will send a query with a limit for the first 2 items. You will get the whole items. Select what you need to display in the template, not the views.
To make your life easier, you can also define a related_name attribute on foreign keys and use the name you want there instead of the generated *_set
Why do you want to pass the information as a string? It's an extra step that doesn't add anything. You can pass in entire dictionaries as the context variable so that's what I'd recommend you do. In your view, it is possible to request rows based off of a filter as seen in the docs here. Then you can pass the data from the query into the template as a dictionary.
Also why does your JournalEntry model only have one field? Can we just combine the JournalEntry and LineItem into something like this:
class LineItem(models.Model):
date = models.DateField(null=True, blank=False)
# journal_entry = models.ForeignKey(JournalEntry, on_delete=models.PROTECT)
# this journal_entry fk wouldn't work so you'd have to replace it with something else
ledger = models.ForeignKey(Ledger, on_delete=models.PROTECT)
description = models.CharField(max_length=255, null=True, blank=True)
cr = models.DecimalField(max_digits=8, decimal_places=2, null=True, blank=True)
dr = models.DecimalField(max_digits=8, decimal_places=2, null=True, blank=True)
Then for the view I would write something like this:
views.py
from .models import LineItem
def journalentries_show_all(request):
context = LineItem.objects.filter(arbitrary_criteria = True) # choose your own criteria here
return render(request, 'journal/journalentries_show_all.html', context)
The important part would be choosing the filter. If you want to do the first two by date you can follow the example here.
Maybe I understood you wrong but why don't you just send your JournalEntry querset to your template?
def journalentries_show_all(request):
context['journal_entries'] = JournalEntry.objects.all()
....
Then you can display what you want in your template
{% for entry in journal_entries %}
{{ entry.id }} {{ entry.date }}
{% for item in entry.lineitem_set.all|slice:"2" %}
{{ item.ledger.name }}
{% endfor %}
{% endfor %}
After some digging I found that I can access related variables direct in the template as follows:
<td>{{ journal_entry.date }}</td>
<td>{{ journal_entry.lineitem_set.all.1.ledger }}</td>
<td>{{ journal_entry.lineitem_set.all.0.ledger }}</td>
<td>{{ journal_entry.lineitem_set.all.1.description|truncatechars:15 }}</td>
<td>{{ journal_entry.lineitem_set.all.0.description|truncatechars:15 }}</td>
I have basic models for a section, subsection and clause. 1 section can hold multiple subsections. Each subsection can hold multiple clauses. The models look like:
**models.py**
class Clause(models.Model):
number = models.CharField(max_length=8, unique=True)
requirements = models.TextField(max_length=2000, unique=False, blank=True, null=True)
documentation = models.TextField(max_length=2000, unique=False, blank=True, null=True)
class Subsection(models.Model):
number = models.CharField(max_length=5, unique=True)
name = models.CharField(max_length=150, unique=False)
descriptor = models.TextField(max_length=2000, unique=False, blank=True, null=True)
clause = models.ForeignKey(Clause, on_delete=models.DO_NOTHING, related_name="clause")
class Section(models.Model):
number = models.CharField(max_length=2, unique=True)
name = models.CharField(max_length=150, unique=False)
descriptor = models.TextField(max_length=2000, unique=False, blank=True, null=True)
subsection = models.ForeignKey(Subsection, on_delete=models.DO_NOTHING, related_name="subsection")
basic view function to call the desired section:
**views.py**
def main(request):
form = MainSearchForm()
user = request.user
sections = []
show_results = True
if 'query' in request.GET:
show_results = True
query = request.GET['query'].strip()
if len(query) <= 2:
sections = Section.objects.filter(number__iexact=query)
if sections:
records = sections
tpl = "display_console.html"
context = {'user': user, 'records': records, 'form': form}
return render(request, tpl, context)
else:
tpl = "main.html"
context = {'user': user, 'form': form}
return render(request, tpl, context)
unfortunately, I can't get my template to return my subsection data. The following returns a 'Subsection' object is not iterable error:
**template**
<table class="section_tb">
{% if records %}
{% for record in records %}
<tr>
<td>{{ record.number }}</td><td>{{ record.name }}</td>
</tr>
{% for item in record.subsection %}
<tr>
<td>{{ item.number }}</td><td>{{ item.name }}</td>
</tr>
<tr>
<td colspan=2>{{ item.descriptor }}</td>
</tr>
{% endfor %}
</table>
{% endfor %}
{% else %}
{% endif %}
substituting:
{% for item in record.subsection.all %}
for:
{% for item in record.subsection %}
removes the error message, but doesn't return any data. Is there something obvious I'm doing wrong?
This is because Section can have only one Subsection.
So you can access the subsection with just {{record.subsection}} so no forloop needed here.
As a tip remember when you usea one to many, the one is where the foreign key is defined.
The model that store the foreign key will always store only one foreign key.
If you want to access the many foreign keys from the other side use the model_name_in_lowercase_set or define a related name in models.ForeignKey(..., related_name="something") then you can call something_set
I have a Requisition which may have multiple lines. So to implement this I included a unique_together constraint on two fields on the RequisitionLine model which one of the fields is a FK to Requisition . So naturally to pull all the lines of a requisition I would query the RequisitionLine table where the FK = the id of the Requisition model, then iterate over all the sequences to grab all the lines.
My goal is to display the header number with the lines of that requisition under the header in the template but am struggling to accomplish this. I have tried to iterate over the queryset but the code i am posting below is my most recent attempt trying pass lists to the template which is also not working. Right now each header is showing all the lines. Any help would be appreciated.
Models.py
class Requisition(models.Model):
username = models.ForeignKey(
'users.CustomUser', on_delete=models.CASCADE, related_name='req_user')
signature = models.CharField(max_length=10, blank=True, null=True)
class RequisitionLine(models.Model):
parent_req = models.ForeignKey('Requisition', on_delete=models.CASCADE, related_name='par_req_line' )
sequence = models.PositiveIntegerField()
item_code = models.ForeignKey(
'items.ItemMaster', on_delete=models.CASCADE, related_name='req_item', blank=True, null=True)
description = models.CharField(max_length=50, blank=True)
extra_information = models.TextField(blank=True)
quantity = models.PositiveIntegerField(blank=True, default=0,null=True)
price = models.DecimalField(max_digits=19, decimal_places=2, blank=True, default=0.00,null=True)
purchase_order = models.CharField(max_length=9, blank=True,null=True)
po_line = models.PositiveSmallIntegerField(blank=True,null=True)
req_delivery_date = models.DateField(blank=True,null=True)
act_delivar_date = models.DateField(blank=True, null=True)
status = models.ForeignKey('RequisitionStatus', related_name='req_status', on_delete=models.CASCADE, blank=True, null=True)
assistance = models.ForeignKey('users.UserRoles', related_name='req_assist', blank=True, null=True, on_delete=models.CASCADE, limit_choices_to= ~Q(role='Requestor'))
catagory = models.ForeignKey('items.ItemCatagory', on_delete=models.CASCADE, related_name='line_cat', blank=True, null=True)
notes = models.TextField(blank=True)
class Meta:
unique_together = ('parent_req','sequence')
Views.py
def pending_action(request):
user = CustomUser.objects.get(username=request.user)
user_req_headers = Requisition.objects.filter(username=user)
complete_status = RequisitionStatus.objects.get(status='Completed')
req_line_list = []
for req_header in user_req_headers:
req_lines = RequisitionLine.objects.filter(Q(parent_req = req_header) & ~Q(status=complete_status))
req_line_list.append(req_lines)
return render(request, 'req/pending_action.html', {'user_req_headers':user_req_headers,'req_line_list':req_line_list})
pending_action.html
{% for header in user_req_headers %}
<h3>{{header}}</h3>
{% for req_line in req_line_list %}
{% for req in req_line %}
<table>
{% if forloop.first %}
<tr>
<th>description</th>
<th>catagory</th>
</tr>
{% endif %}
<tr>
<!-- FOR LOOP HERE TO ITERATE OF LIST OF QUERYSETS-->
<td>{{ req }}</td>
</tr>
</table>
{% endfor %}
{% endfor %}
{% endfor %}
I solved this problem by creating a queryset of the header and using a reverse relationship to capture the lines associated with each header
<table class="table">
{% for req_header in req_header_list %}
<tr>
<ul>{{ req_header }}
{% for line in req_header.par_req_line.all %}
<li>{{line}}</li>
{% endfor %}
</ul>
</tr>
{% endfor %}
</table>
I have a template with a table, and there I have all the objects on a query. Each object can have related objects or not. Assuming this, what I need to do is, for each object check if have or not that related object. If not in the table I have a field to put a link to create a related object, but if have show a icon to see this object.
I can do with the one of the "parent" object but I don't know how to do if I have more than one object in the query.
Models to check:
class Accident(models.Model):
employee = models.ForeignKey(Employee)
place = models.IntegerField(choices=ACCIDENT_PLACE, default=1)
detail = models.CharField(max_length=255)
clinic = models.ForeignKey(Clinic)
is_urgency = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
created_by = models.ForeignKey(User,
related_name='accidents_created_by',
editable=False,
blank=True,
null=True
)
modified_by = models.ForeignKey(User,
related_name='accidents_modified_by',
editable=False,
blank=True,
null=True
)
class Meta:
verbose_name = "accidente"
verbose_name_plural = "accidentes"
def __str__(self):
return str(self.id)
class AccidentCertificate(models.Model):
accident = models.ForeignKey(Accident)
diagnostic = models.CharField(max_length=150)
return_day = models.DateField()
notes = models.CharField(max_length=255)
medication = models.CharField(max_length=255)
doctor = models.ForeignKey(Doctor)
presented = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
created_by = models.ForeignKey(User,
related_name='acc_certificates_created_by',
editable=False,
blank=True,
null=True
)
modified_by = models.ForeignKey(User,
related_name='acc_certificates_modified_by',
editable=False,
blank=True,
null=True
)
class Meta:
verbose_name = "certificado de accidente"
verbose_name_plural = "certificados de accidente"
ordering = ["-id"]
def __str__(self):
return str(self.id)
this is my view (to check only one object that i already know that have 1 related object)
class EmployeeDetailView(LoginRequiredMixin, DetailView):
# Chequeamos que el usuario se encuentre logeado
login_url = reverse_lazy('users:login')
model = Employee
template_name = 'employees/detail.html'
pk_url_kwarg = 'employee_id'
def get_context_data(self, **kwargs):
context_object_name = 'employee'
context = super(EmployeeDetailView, self).get_context_data(**kwargs)
employee = context['employee']
context['cuil'] = employee.cuil[:2]+'-'+employee.cuil[2:10]+'-'+employee.cuil[-1:]
# Tomamos los accidentes correspondientes al empleado
# y los pasamos al contexto
employee_accidents = Accident.objects.filter(employee=employee)
context['accidents'] = employee_accidents
# Tomamos el certificado del accidente si existe
accident_certificate = AccidentCertificate.objects.get(accident=employee_accidents)
return context
and in the template
<table class="table table-striped">
<thead>
<tr>
<th>ID Acc.</th>
<th>Fecha</th>
<th>Cant. Días</th>
<th>Locación</th>
<th>Detalle</th>
<th>Clinica</th>
<th>Urgencia</th>
<th>Cargado por</th>
<th>Certificado</th>
<th>Segimiento</th>
</tr>
</thead>
<tbody>
{% for a in accidents %}
<tr>
<td>{{ a.id }}</td>
<td>{{ a.created|date }}</td>
<td>-</td>
<td>{{ a.get_place_display }}</td>
<td>{{ a.detail }}</td>
<td>{{ a.clinic }}</td>
<td>
{% if a.is_urgency %}
Si
{% else %}
No
{% endif %}
</td>
<td>{{ a.created_by }}</td>
<td>{% bootstrap_icon "search" %}</td>
<td>{% bootstrap_icon "search" %}</td>
</tr>
{% empty %}
<p class="text-center">
<strong>NO HAY REGISTROS</strong>
</p>
{% endfor %}
</tbody>
</table>
Well in sintesis I need to take every accidents that correspond to an employee, and for each accident check if this have an AccidentCertificate, if it have put the link in the table to see the certificate, and if not put the link to create the certificate.
You can use a count annotation to add the number of related certificates to each accident, then use that number in an if statement in the template.
from django.db.models import Count
...
employee_accidents = Accident.objects.filter(employee=employee).annotate(certificate_count=Count('accidentcertificate'))
...
{% for a in accidents %}
...
{% if a.certificate_count == 0 %}
Add new certificate
{% endif %}
{% endfor %}