Django-tables2 reverse lookup - django

I have a table that displays a list of "leads" which are rendered fine. There is also a related model which is called "Leadupdate" that is related to "lead" model that is used in the table. There is a many to one relationship from Leadupdate to lead with a foreign key. I want to display all the related updates for the individual "leads" in one of the updates column. There are several examples online for following forward relationship through foreign key but haven't found one for reverse yet. Here is one example of said relationship Accessor forward look up.
EDIT: Look up will be done on a Django-tables2 module instance table. I am not asking reverse look up on a model but doing it in context of Django-tables2.
Models.py:
class lead(models.Model):
slug = models.SlugField(unique=True,blank=True, null=True)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100, blank=True, null=True)
business_name = models.CharField(max_length=100,blank=True, null=True)
email = models.EmailField(max_length=75, blank=True, null=True)
phone_number = models.CharField(max_length=20, blank=True, null=True)
address = models.CharField(max_length=150, blank=True, null=True)
city = models.CharField(max_length=50, blank=True, null=True)
state = models.CharField(max_length=10, blank=True, null=True)
zipcode = models.CharField(max_length=5, blank=True, null=True)
submission_date = models.DateTimeField(auto_now_add=True, blank=True)
assigned_to = models.ManyToManyField(Listing,blank=True, null=True, related_name="leads")
requested_software = models.CharField(max_length=50, blank=True, null=True)
type_of_business = models.CharField(max_length=30, choices=TYPE_OF_BUSINESS, default='Bar', blank=True, null=True)
time_frame = models.CharField(max_length=10, choices=TIME_FRAME, default='1')
comments = models.TextField(blank=True, null=True)
def __unicode__(self):
return self.business_name
#models.permalink
def get_absolute_url(self):
return('listing_detail', (),{'slug' :self.slug,})
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.business_name)
super(lead, self).save(*args, **kwargs)
class Leadupdate(models.Model):
CONFIDENCE_LEVEL = (
('HOT', 'HOT'),
('COLD', 'COLD'),
)
LEAD_VALUE = (
('1K3K', '1K-3K'),
('5K10K', '5K-10K'),
('10K20K', '10K-20K'),
('20K50K', '20K-50K'),
('50KUP', '5OK-UP'),
)
ESTIMATED_CLOSING = (
('1w4w', '1-4 Weeks'),
('1m3m', '1-3 Months'),
('3m6m', '3-6 Months'),
('6m+', '6+ Months'),
)
updatedate = models.DateTimeField(auto_now_add=True)
update = models.TextField(blank=True, null=True)
updatefrom = models.ForeignKey(Listing, related_name="update_from", blank=True, null=True)
lead = models.ForeignKey(lead, related_name="related_update",blank=True, null=True)
lead_confidence_level = models.CharField(max_length=10, choices=CONFIDENCE_LEVEL, default='COLD', blank=True, null=True)
estimated_lead_value = models.CharField(max_length=10, choices=LEAD_VALUE, default='1K3K', blank=True, null=True)
estimated_closing_frame = models.CharField(max_length=10, choices=ESTIMATED_CLOSING, default='1-4 Weeks', blank=True, null=True)
def __unicode__(self):
return u" %s - %s " % (self.update, self.updatedate)
Table:
class LeadTable(tables.Table):
business_name = tables.LinkColumn('lead-detail', args=[A('slug')])
updates = tables.Column(accessor='lead.related_update')
class Meta:
model = lead
fields = ("business_name","first_name", "last_name","number_of_pos","submission_date","updates")
attrs = {"class":"paleblue"}

A late answer, but here is what works for me in Django 1.8.6 with django-tables2 1.1.0 (based on Django-Tables2 Issue 156 and This answer). To access a one to many set of objects via a foreign key relation you need to just use the related_name in the accessor and then create a render method to produce what gets written to column cell. In that method you can then get all the foreign model objects and access their fields in a for loop.
class LeadTable(tables.Table):
business_name = tables.LinkColumn('lead-detail', args=[A('slug')])
updates = tables.Column(accessor='related_update')
def render_updates(self, value, table):
updates = ""
uFirst = True
updatesList = list(value.all())
for u in updatesList:
if not uFirst:
updates += ", "
else:
uFirst = False
updates += u.update
return updates
class Meta:
model = lead
fields = ("business_name","first_name", "last_name","number_of_pos","submission_date","updates")
attrs = {"class":"paleblue"}

according to django docs
in your views you can access them in this way (assuming lead_instance is an instance of lead class):
all_leadtables_for_lead = lead_instance.leadtable_set
a side note: use Capitalized names for classes (class Lead(models.Model):) in order to adhere to python PEP8 guidelines.

Related

Django - how to make frontend-customizable sets / groups in models?

I am trying to create an app, that handles laboratory analyses - something like similar Laboraotory Information System (LIS)
The issue is that i dont know which approach to take.
I am plannin to make it as follows:
"ANALYSES" table - consisting of "name", "ID" of analyses
"PROBES" table - consisiting of "name", "ID", "reference", "VALUE", "measurement".
Also the PROBES will have the field which links it to certain "ANALYSES" instance.
SO it will be like "ANALYSES #1" -> "PROBE1", "PROBE2", "PROBE3"
"ANALYSES #2" -> "PROBE1", "PROBE3"
And so on.
The operator should be capable of adding new analyses and adding probes to this analyses via frontend in one "view" - like "LAB settings" and in another view - to enter values to instances of this analyses (all analyses instances will be linked to some "VISIT" - the service case)
What approach should i take planning the app and models? will it be some Meta classes or just multiple tables linked "manytoone" or "manytomany"?
Will be gratefull for any advice!
Nothing about this seems particularly complex that a ManyToOne relationship can't handle. Your models would look like this:
class Visit(models.Model):
...
class Analysis(models.Model):
visit = models.ForeignKey(Visit, ...
...
class Probe(models.Model):
analysis = models.ForeignKey(Analysis, ...
...
If many probes can attach to different analyses or analyses to visits then use a ManyToManyField instead of ForeignKey, note that processing m2m in Django works differently to m21 relations.
https://docs.djangoproject.com/en/4.0/topics/db/examples/many_to_one/
https://docs.djangoproject.com/en/4.0/topics/db/examples/many_to_many/
Thanks for answer!
Currently i am doing something similar to this, if someone interested.
Maybe there are easier ways, but it suits my needs so far.
import uuid
from django.db import models
# Create your models here.
class Patient(models.Model):
class Gender(models.TextChoices):
male = "Муж"
female = "Жен"
surname = models.CharField("Фамилия", max_length=200)
name = models.CharField("Имя", max_length=200)
fathname = models.CharField("Отчество", max_length=200)
created = models.DateTimeField("Добавлен", auto_now_add=True)
id = models.AutoField("Идентификатор", primary_key=True)
dateofbirth = models.DateField("Дата рождения", null=True, blank=True)
gender = models.CharField("Пол", max_length=3, choices=Gender.choices, default=Gender.male)
snils = models.DecimalField("СНИЛС", max_digits=11, decimal_places=0, null=True, blank=True)
class Meta:
ordering = ['-created']
def returnFIO(self):
return self.surname + " " + self.name + " " + self.fathname
def returnAge(self):
import datetime
return (datetime.date.today() - self.dateofbirth) / 365
def __str__(self):
return self.surname + " " + self.name + " " + self.fathname
class Visit(models.Model):
patient = models.ForeignKey(Patient, on_delete=models.CASCADE, verbose_name="Пациент")
id = models.AutoField("Идентификатор", primary_key=True)
created = models.DateTimeField("Добавлен", auto_now_add=True)
class Meta:
ordering = ['-created']
def returnCreated(self):
return self.created
def __str__(self):
return str(self.id) + " / " + str(self.created)
from django.db import models
import uuid
from patients.models import Visit
# Create your models here.
class Analiz(models.Model):
name = models.CharField(max_length=200, blank=True, null=True)
description = models.CharField(max_length=200, blank=True, null=True)
id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)
def __str__(self):
return str(self.name)
class AnalizInst(models.Model):
analiz = models.ForeignKey(Analiz, on_delete=models.CASCADE, null=True)
id = models.AutoField(primary_key=True)
created = models.DateTimeField(auto_now_add=True)
related_to_visit = models.ForeignKey(Visit, on_delete=models.CASCADE, null=True)
def __str__(self):
return str(self.analiz) + ' / ' + str(self.id)
class Measurement(models.Model):
id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)
name = models.CharField(max_length=200, blank=True, null=True)
def __str__(self):
return self.name
class Probe(models.Model):
name = models.CharField("Название теста", max_length=200, blank=True, null=True)
description = models.CharField("Описание", max_length=200, blank=True, null=True)
id = models.UUIDField("Идентификатор", default=uuid.uuid4, unique=True, primary_key=True, editable=False)
related_to_analiz = models.ForeignKey(Analiz, on_delete=models.CASCADE, null=True, verbose_name="Привязка к анализу")
digits = models.IntegerField("Цифр после запятой", null=True, blank=True)
measurement = models.ForeignKey(Measurement, on_delete=models.SET_NULL, null=True, blank=True, verbose_name="Измерение")
probeIsDigital = models.BooleanField("Числовой", default=True)
referenceText = models.CharField("Референс текст", max_length=50, blank=True, null=True)
referenceMin = models.DecimalField("Референс MIN", max_digits=10, decimal_places=5, null=True, blank=True)
referenceMax = models.DecimalField("Референс MAX", max_digits=10, decimal_places=5, null=True, blank=True)
defaultInUse = models.BooleanField("Включен по умолчанию", default=True)
hl7Name = models.CharField("Имя в анализаторе", max_length=200, blank=True, null=True)
defaultText = models.CharField("Текст значения по умолчанию", max_length=200, blank=True, null=True)
def __str__(self):
return str(self.name)
class ProbeInst(models.Model):
value = models.DecimalField("Значение", max_digits=10, decimal_places=5, null=True, blank=True)
textvalue = models.CharField("Текстовое значение", max_length=200, blank=True, null=True)
probe = models.ForeignKey(Probe, on_delete=models.CASCADE, null=True, verbose_name="Тест")
id = models.AutoField("Идентификатор", primary_key=True)
related_to_analyse = models.ForeignKey(AnalizInst, on_delete=models.CASCADE, null=True, verbose_name="Привязка к анализу")
created = models.DateTimeField("Создан", auto_now_add=True)
inUse = models.BooleanField("В работе", default=True)
def __str__(self):
return str(self.probe)
Further i am planning to build some UI and forms input for manual input and make some integrations with HL7 standard to load data directly from lab analyzers.
Django is the best thing that happened to me so far in programming)

How do I show only a subset of options in a Django dropdown menu

I have an app that allows users to signup and register for courses (from a 'TrainingInstance' model). These events have names etc and are categorised as Past or Current in the database (in the 'Training' model). When I show the BuildOrderForm in my template, I want only options for Current trainings to be shown in the dropdown menu. How can this be done in Django without javascript or Ajax?
I have the following form in forms.py:
class BuildOrderForm(forms.ModelForm):
class Meta:
model = Order
fields = ['training_registered']
And the following models in models.py:
class Training(models.Model):
""" Model which specifies the training category (name) and whether they are Past or Present"""
YEAR = (
('current', 'current'),
('past', 'past'),
)
name = models.CharField(max_length=200, null=True)
year= models.CharField(max_length=200, null=True, choices=YEAR, default='current')
def __str__(self):
return self.name
class TrainingInstance(models.Model):
""" Creates a model of different instances of each training ( May 2021 etc) """
name = models.CharField(max_length=200, null=True, blank=True)
venue = models.CharField(max_length=200, null=True, blank=True)
training = models.ForeignKey(Training, on_delete= models.CASCADE, null = True)
training_month = models.CharField(max_length=200, null=True, blank=True)
participant_date = models.CharField(max_length=20, null=True, blank=True)
staff_date = models.CharField(max_length=20, null=True, blank=True)
graduation_date = models.CharField(max_length=200, null=True, blank=True)
def __str__(self):
return self.name
class Order(models.Model):
REGSTATUS = (
('registered', 'registered'),
('enrolled', 'enrolled'),
('holding', 'holding'),
('withdrawn', 'withdrawn'),
('waiting', 'waiting'),
)
customer = models.ForeignKey(Customer, on_delete= models.CASCADE, null = True)
training_registered = models.ForeignKey(TrainingInstance, on_delete= models.SET_NULL, blank = True, null = True)
registration_date = models.DateTimeField(null=True,blank=True)
regstatus = models.CharField(max_length=200, null=True, choices=REGSTATUS, default='registered')
def __str__(self):
return self.customer.username
Here is what I have done - which works but I'm also open to feedback about good/bad practice.
class BuildOrderForm(forms.ModelForm):
class Meta:
model = Order
fields = ['training_registered']
def __init__(self,*args,**kwargs):
super (BuildOrderForm,self ).__init__(*args,**kwargs)
self.fields['training_registered'].queryset = TrainingInstance.objects.filter(training__year ="current")

How to use #property in Django models?

I want to add one subquery to my query. And I created a #property in Transaction. Found on the Internet that this is what I need. But I do not fully understand how they work. How to use it?
views.py(Query)
paymentsss = Transaction.objects.all().select_related('currency',
'payment_source__payment_type',
'deal__service__contractor',).
models.py
class PayerPaymentSource(models.Model):
id = models.BigIntegerField(blank=True, null=False, primary_key=True)
payer_id = models.BigIntegerField(blank=True, null=True)
payment_type = models.ForeignKey(PaymentType, max_length=64, blank=True, null=True, on_delete=models.CASCADE)
source_details = models.TextField(blank=True, null=True) # This field type is a guess.
class Meta:
managed = False
db_table = '"processing"."payer_payment_source"'
class Transaction(models.Model):
id = models.BigIntegerField(blank=True, null=False, primary_key=True)
currency = models.ForeignKey(Currency, null=True, on_delete=models.CASCADE)
deal = models.ForeignKey(Deal, null=True, on_delete=models.CASCADE)
# service_instance = models.ForeignKey(ServiceInstance, null=True, on_delete=models.CASCADE)
payment_source = models.ForeignKey(PayerPaymentSource, null=True, on_delete=models.CASCADE)
payment_date = models.DateTimeField(blank=True, null=True)
amount = models.IntegerField(blank=True, null=True)
status = models.CharField(max_length=255, blank=True, null=True)
context = models.TextField(blank=True, null=True)
#property
def bank_card_details(self):
return PayerPaymentSource.objects.filter(self.payment_source.source_details,
payment_type='bank_card_details')
class Meta:
managed = False
db_table = '"processing"."transaction"'
UPD: print(payment.bank_card_details) works, but it creates a lot of similar queries. How to fix it?
The #property decorator is just a convenient way to call the property() function, which is built in to Python. This function returns a special descriptor object which allows direct access to the method's computed value.
For example in your view
obj = Transaction.objects.get(pk=pk)
#now you can get the bank_card_details like this:
print(obj.bank_card_details)

I wanna create model which Before adding it must be accepted

I would like to create a model which must be accepted by the moderator before adding, after which every change in eg the title in this model must also be accepted
class MangaRequest(models.Model):
title = models.CharField(max_length=191)
type = models.CharField(max_length=30,choices=TYPE, blank=True, default='', null=True)
status= models.CharField(max_length=30, choices=STATUS, blank=True, default='', null=True)
date_start = models.DateField(blank=True, null=True)
data_end = models.DateField(blank=True, null=True)
age_restrictions = models.ForeignKey(OgraniczenieWiekowe, null=True, default='', blank=True)
volumes = models.SmallIntegerField(null=True, blank=True, default=0)
chapter = models.SmallIntegerField(null=True, blank=True, default=0)
is_accept = models.BooleanField(default=False)
delete = models.BooleanField(default=False)
This is my model and I have done it
def save(self, *args, **kwargs):
if self.is_accept == True:
manga = MangaAccept.objects.create(...)
super(MangaRequest, self).delete()
return manga
else:
super(MangaRequest, self).save()
And the same way is about deletes
My question is how can ACCEPT or REJECT for model and everyone field in this model ? Any sugestion ?

Update existing M2M relationship in Django

I'm trying to save an existing instance of a customer record. Its model has a M2M to the vehicle model (since a customer can multiple vehicles). After reading several questions/answer here, I still do not know how to solve this.
Customer model:
class Customer(models.Model):
vehicle_id = models.ManyToManyField(VehicleSale)
name = models.CharField(max_length=40, blank=True, db_index=True, null=True,
verbose_name='name')
lic = models.CharField(max_length=20, blank=True, db_index=True, null=True,
verbose_name='license')
addr = models.CharField(max_length=40, blank=True, null=True, verbose_name='address')
city = models.CharField(max_length=15, blank=True, null=True, verbose_name='city')
state = models.CharField(max_length=2, blank=True, null=True, verbose_name='state')
zip = models.CharField(max_length=10, blank=True, null=True, verbose_name='zipcode')
email = models.EmailField(blank=True, null=True, verbose_name='email')
tel1 = models.CharField(max_length=15, blank=True, verbose_name='Tel. 1', null=True)
tel2 = models.CharField(max_length=15, blank=True, verbose_name='Tel. 2', null=True)
ssn = models.CharField(max_length=12, blank=True, db_index=True, null=True,verbose_name='SSN')
class Meta:
db_table = 'customer'
def __unicode__(self):
return self.name
def save(self, *args, **kwargs):
self.name = self.name.upper()
self.addr = self.addr.upper()
self.city = self.city.upper()
self.state = self.state.upper()
return super(Customer, self).save(*args, **kwargs)
In the view, after defining customer as
customer = current_vehicle.customer_set.all()
I tried the following:
if 'customer' in request.POST:
if customer:
customer_form = CustomerForm(request.POST, instance=customer[0])
if customer_form.is_valid():
customer_form.save()
Also tried adding before customer_form is defined:
customer.vehicle_id = current_vehicle.id
And then this after the form:
customer_form.vehicle_id = current_vehicle.id
Form is not valid so it's not saved. Upon checking {{ form.errors}}, it always reports vehicle_id is required.
Finally, after the answer in this, I adjusted it to my scenario by adding:
obj = customer_form.save(commit=False)
and hoping to assign vehicle_id, but it fails immediately.
What am I missing?
Thanks.
1st EDIT:
The section on the view now looks as:
customer_form = CustomerForm(request.POST, instance=customer[0])
customer_form.save()
customer_form.vehicle_id.add(current_vehicle)
You are misunderstanding what a ManyToMany field is here:
customer_form.vehicle_id = current_vehicle.id
vehicle_id is defined as a ManyToMany field on your Customer model, therefore you can't just assign a single id to it. You have to add an instance of VehicleSale model, eg:
customer_form.vehicle_id.add(current_vehicle)
See docs here:
https://docs.djangoproject.com/en/dev/topics/db/examples/many_to_many/
See also this answer for why you can't save until you populate the vehicle_id relation:
https://stackoverflow.com/a/2529875/202168