I want to make a request from two tables at once, I registered dependencies in the class. But the request does not work for me. What is wrong with him?
views.py
def payments(request):
paymentsss = Transaction.objects.select_related("currency_id")[:5]
return render(request, "payments.html", {"paymentsss": paymentsss})
models.py
class Transaction(models.Model):
id = models.BigIntegerField(blank=True, null=False, primary_key=True)
currency_id = models.ForeignKey(Currency, null=True, on_delete=models.CASCADE)
deal_id = models.ForeignKey(Deal, null=True, related_name='deal', on_delete=models.CASCADE)
service_instance_id = models.ForeignKey(ServiceInstance, null=True, related_name='service_instance', on_delete=models.CASCADE)
payment_source_id = models.ForeignKey(PayerPaymentSource, null=True, related_name='payment_source', 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) # This field type is a guess.
class Meta:
managed = False
db_table = '"processing"."transaction"'`enter code here`
And Currency for example:
class Currency(models.Model):
id = models.SmallIntegerField(blank=True, null=False, primary_key=True)
name = models.CharField(max_length=128, blank=True, null=True)
iso_name = models.CharField(max_length=3, blank=True, null=True)
minor_unit = models.SmallIntegerField(blank=True, null=True)
class Meta:
managed = False
db_table = '"processing"."currency"'
My Error:
I would be glad if there is an example of how to make a larger request. From 3-4 tables.
Change the db_table
class Meta:
managed = False
db_table = 'processing.transaction'
class Meta:
managed = False
db_table = 'processing.currency'
You need to change the column names for the foreign keys: e.g. currency = ForeignKey(...) and deal = ForeignKey(...).
The field is a reference to the object itself, not to the id of the object. You can see that behind the scenes, Django queries using currency_id_id which doesn't make sense.
If your column name is currency_id (in your database), then your field name should be currency.
Related
I am joining the ClientDetails, AssignmentTable and CallDetails table to get a view as to which telecaller a particular client has been assigned to and get the latest call details as well. However I am unable to accomplish that using django ORM.
ISSUE:
I am trying to access the fields inside the assignment table and call table but I am getting only the ids and not the other fields.
Question:
How do I extract all the columns from the assignment and call details table which has the client id as 1?
This is the SQL Query that I am trying to come up with:
SELECT t1.uid, t1.phone_number, t1.client_name, t1.base, t1.location, t2.assigner, t2.bpo_agent, t2.cro_agent, t3.bpo_status_id, t3.cro_status_id, t3.agent_id_id
FROM public.bpo_app_clientdetails t1
LEFT JOIN public.bpo_app_assignmentdetails t2 ON t1.uid = t2.client_id_id
LEFT JOIN public.bpo_app_calldetails t3 ON t1.uid = t3.client_id_id;
Below is the model file:
class ClientDetails(models.Model):
uid = models.AutoField(primary_key=True)
phone_number = PhoneNumberField(unique=True)
client_name = models.CharField(max_length=50, blank=True, null=True)
base = models.CharField(max_length=50, blank=True, null=True)
location = models.CharField(max_length=50, blank=True, null=True)
class Meta:
verbose_name_plural = "Client Contact Detail Table"
def __str__(self):
return f"{self.phone_number}, {self.client_name}"
class AssignmentDetails(models.Model):
uid = models.AutoField(primary_key=True)
client_id = models.ForeignKey(
ClientDetails,
on_delete=models.PROTECT,
related_name='assignment_details'
)
date_and_time = models.DateTimeField(auto_now_add=True, blank=True)
assigner = models.ForeignKey(
User,on_delete=models.PROTECT,
related_name='AssignerAgent',
db_column='assigner',
)
bpo_agent = models.ForeignKey(
User,on_delete=models.PROTECT,
related_name='bpoAgent',
db_column='bpo_agent',
)
cro_agent = models.ForeignKey(
User,on_delete=models.PROTECT,
related_name='croAgent',
db_column='cro_agent',
)
class Meta:
verbose_name_plural = "Client Assignment Detail Table"
def __str__(self):
return f"{self.uid}"
class CallDetails(models.Model):
uid = models.AutoField(primary_key=True)
date_and_time = models.DateTimeField(auto_now_add=True, blank=True)
client_id = models.ForeignKey(
ClientDetails,
on_delete=models.PROTECT,
related_name='call_details'
)
agent_id = models.ForeignKey(EmployeeDetails_lk,on_delete=models.PROTECT)
bpo_status = models.ForeignKey(BpoStatus_lk,on_delete=models.PROTECT, blank=True, null=True)
cro_status = models.ForeignKey(CroStatus_lk,on_delete=models.PROTECT, blank=True, null=True)
required_loan_amt = models.CharField(max_length=50, blank=True, null=True)
remarks = models.CharField(max_length=500, blank=True, null=True)
loan_program = models.ForeignKey(LoanProgram_lk, on_delete=models.PROTECT, blank=True, null=True)
disbursement_bank = models.ForeignKey(Banks_lk, on_delete=models.PROTECT, limit_choices_to={'loan_disbursement_status': True}, blank=True, null=True)
class Meta:
verbose_name_plural = "Client Call Detail Table"
def __str__(self):
return f"{self.uid}"
>>> qry=ClientDetails.objects.values('assignment_details','call_details').filter(uid=1)
>>> qry
<QuerySet [{'assignment_details': 1, 'call_details': None}]>
>>> print(a.query)
SELECT "bpo_app_assignmentdetails"."uid", "bpo_app_calldetails"."uid" FROM "bpo_app_clientdetails" LEFT OUTER JOIN "bpo_app_assignmentdetails" ON ("bpo_app_clientdetails"."uid" = "bpo_app_assignmentdetails"."client_id_id") LEFT OUTER JOIN "bpo_app_calldetails" ON ("bpo_app_clientdetails"."uid" = "bpo_app_calldetails"."client_id_id") WHERE "bpo_app_clientdetails"."uid" = 1
You can use prefetch_related() to achieve this. I just use some sample models here for better understanding.
class Company(models.Model):
name = models.CharField(null=True, blank=True, max_length=100)
class Project(models.Model):
name = models.CharField(null=True, blank=True, max_length=100)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
class Employee(models.Model):
name = models.CharField(null=True, blank=True, max_length=100)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
In your views.py function write the below lines to get the desired results
companies = Company.objects.filter(id=1).prefetch_related('project_set', 'employee_set')
for company in companies:
print(company.project_set.values()) # This will print this company projects
print(company.employee_set.values()) # This will print this company employees
Note: If you use related_name in your ForeignKey relationship, make sure that you access with that name instead of model_set inside prefetch_related()
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 have a standard model with a foreignkey, in this case from biology: Seed to Taxon. The taxon model includes both Animal and Plant Taxon, and has a category column which is either zoology or botany
When I add a new Seed I get the expected dropdown list, but it supplies the zoology and botany options. How do I filter it so only the botany options are shown? I'm assuming this filter can be applied somewhere in the model? I've tried adding .filter() and .exclude() but they do nothing here.
class Taxon(models.Model):
taxon_id = models.AutoField(primary_key=True)
taxon = models.CharField(max_length=50, blank=True, null=True)
common_name = models.CharField(max_length=50, blank=True, null=True)
taxon = models.CharField(max_length=50, blank=False, null=False)
genus = models.CharField(max_length=50, blank=True, null=True)
category = models.CharField(max_length=50, blank=True, null=True)
# family_name = models.CharField(max_length=50, blank=True, null=True)
def __str__(self):
return str(self.taxon)
class Meta():
managed=False
db_table = 'kap\".\"taxon_manager'
ordering = ["genus","taxon"]
verbose_name_plural = "taxon"
class Seed(models.Model):
seed_id = models.AutoField(primary_key=True)
fraction_id = models.ForeignKey(Fraction, db_column='fraction_id', blank=True, null=True, on_delete = models.PROTECT)
taxon_id = models.ForeignKey(Taxon, db_column='taxon_id', blank=True, null=True, on_delete = models.PROTECT, related_name='seed_taxon')
weight_type = models.CharField(max_length=50)
weight = models.DecimalField(max_digits=10, decimal_places=3)
quantity_type = models.CharField(max_length=50)
quantity = models.IntegerField()
def __str__(self):
return str(self.taxon_id)
class Meta():
managed=False
db_table = 'kap\".\"seed'
ordering = ["taxon_id","fraction_id"]
verbose_name_plural = "seeds"
If the category field in your Taxon model is a choice between "zoology" and "botany", then I would make them choices like so:
class Taxon(models.Model):
ZOOLOGY = 0
BOTANY = 1
CATEGORY_CHOICES = (
(ZOOLOGY, 'Zoology'),
(BOTANY, 'Botany'),
)
<your other fields>
category = models.CharField(max_length=50, choices=CATEGORY_CHOICES, blank=True, null=True)
Then, if you want to filter inside your seed model, you could change your taxon_id field so that it includes limit_choices_to:
taxon_id = models.ForeignKey(
Taxon,
db_column='taxon_id',
limit_choices_to={'category': Taxon.BOTANY},
blank=True,
null=True,
on_delete = models.PROTECT,
related_name='seed_taxon'
)
I haven't explicitly tested this case, but something like the above should work. If you want to filter in other places, then the filter that Juan mentioned in the comment looks good.
Hope this helps.
I have this abstract models.
class Abstract_Detail(models.Model):
""" Abstract models for detail in subassembly """
name = models.CharField(max_length=50, blank=True, null=True)
mark = models.CharField(max_length=50)
weight_end = models.FloatField(blank=True,
null=True, default=0)
class Meta:
abstract = True
unique_together = ('name', 'makr')
And Details model.
class Detail(Abstract_Detail):
""" Detail """
auto_area = models.FloatField(blank=True, null=True, default=0.0)
size_workpiece = models.CharField(max_length=10, blank=True, null=True)
weight = models.FloatField(blank=True, null=True, default=0)
product = models.ManyToManyField(Products, through='Structure_production')
subassembly = models.ManyToManyField(Subassembly, through='Structure_production')
material = models.ForeignKey(Material, on_delete=models.SET_NULL,
null=True, blank=True)
assortament = models.ForeignKey(Sortment, on_delete=models.SET_NULL,
null=True, blank=True)
class Meta():
unique_together = ('name', 'makr')
What is the problem: in some cases, when you change weight_end in admin Detail, when executing the below code, a new record is created with a combination of the name and mark, which is already in the model.
detail, sost = Detail.objects.get_or_create(
name=name, makr=makr,
defaults={'size_workpiece': size,
'material': material,
'assortament': sortament})
Is there an explanation? Read the documentation fully, the answer is not found.
While trying to run my second Django 2.1 /Postgres 10 project I got stuck with the following programming error:
ProgrammingError at /admin/vocs_app/subsubscriber/
column sub_subscriber.sub_prev_sst_uid_id does not exist
LINE 1: ...", "sub_subscriber"."sub_next_recharge_datetime", "sub_subsc...
^
HINT: Perhaps you meant to reference the column "sub_subscriber.sub_prev_sst_uid".
I can open the admin app of my application, i.e., 127.0.0.1:8000/admin/vocs_app.
It lists all imported models from my database; to illustrate my case I believe the following classes are sufficient:
(taken from my_site/vocs_app/models.py:)
from django.db import models
class VneVirtualNetwork(models.Model):
vne_uid = models.BigAutoField(primary_key=True)
vne_nop_uid = models.ForeignKey(NopNetworkOperator, models.DO_NOTHING, db_column='vne_nop_uid')
vne_name = models.CharField(max_length=50)
vne_code = models.CharField(max_length=50)
vne_external_id = models.CharField(max_length=100, blank=True, null=True)
vne_idd_code = models.CharField(max_length=5)
vne_sn_length = models.IntegerField()
createdon = models.DateTimeField()
createdby = models.CharField(max_length=150)
createdfrom = models.CharField(max_length=150)
modifiedon = models.DateTimeField()
modifiedby = models.CharField(max_length=150)
modifiedfrom = models.CharField(max_length=150)
class Meta:
managed = False
db_table = 'vne_virtual_network'
class SstSystemStatus(models.Model):
sst_uid = models.BigAutoField(primary_key=True)
sst_name = models.CharField(max_length=50)
sst_description = models.CharField(max_length=100, blank=True, null=True)
startdate = models.DateField(blank=True, null=True)
enddate = models.DateField(blank=True, null=True)
class Meta:
managed = False
db_table = 'sst_system_status'
class SubSubscriber(models.Model):
sub_uid = models.BigAutoField(primary_key=True)
sub_vne_uid = models.ForeignKey('VneVirtualNetwork', models.DO_NOTHING, db_column='sub_vne_uid')
sub_rpl_uid = models.ForeignKey(RplRatePlan, models.DO_NOTHING, db_column='sub_rpl_uid')
sub_account_user_id = models.CharField(max_length=100, blank=True, null=True)
sub_external_id = models.CharField(max_length=100)
sub_hzn_uid = models.ForeignKey(HznHomezoneName, models.DO_NOTHING, db_column='sub_hzn_uid')
sub_low_balance_trigger = models.BooleanField()
sub_first_call_datetime = models.DateTimeField(blank=True, null=True)
sub_last_enabled_datetime = models.DateTimeField(blank=True, null=True)
sub_last_disabled_datetime = models.DateTimeField(blank=True, null=True)
sub_last_recharge_datetime = models.DateTimeField(blank=True, null=True)
sub_next_recharge_datetime = models.DateTimeField(blank=True, null=True)
sub_prev_sst_uid = models.ForeignKey(SstSystemStatus, related_name='sub_prev_sst_uid',on_delete=models.DO_NOTHING)
sub_sst_uid = models.ForeignKey(SstSystemStatus, related_name='sub_sst_uid',on_delete=models.DO_NOTHING)
startdatetime = models.DateTimeField()
enddatetime = models.DateTimeField()
createdon = models.DateTimeField()
createdby = models.CharField(max_length=150)
createdfrom = models.CharField(max_length=150)
modifiedon = models.DateTimeField()
modifiedby = models.CharField(max_length=150)
modifiedfrom = models.CharField(max_length=150)
class Meta:
managed = False
db_table = 'sub_subscriber'
class SubSubscriber references foreign key sst_uid of table/class SstSystemStatus twice (previous and current status). It seems Django doesn't like it. Other tables such as VneVirtualNetwork (which contain a "single" foreign key references) don't cause any issue. The admin GUI allows me to display and change their data.
The fault message shows that Django tries to complement the name of field sub_prev_sst_uid with '_id'. If I comment the relevant line in file model.py and try to display the subscriber table it will cause the same error, this time with field sub_sst_uid. How can I prevent Django from appending '_id'?
Thanks in advance for any advice.
By default, Django will use the related name and/or the chosen class field name, add a suffix "_id" and try to locate a column of this name in the database. Unless you explicitly define the db_column as follows:
sub_sst_uid = models.ForeignKey('SstSystemStatus', db_column='sub_sst_uid', related_name='sub_sst_uid', on_delete=models.DO_NOTHING)
sub_prev_sst_uid = models.ForeignKey('SstSystemStatus', db_column='sub_prev_sst_uid', related_name='sub_prev_sst_uid', on_delete=models.DO_NOTHING)