Django model - how to define foreign key refer to another table? - django

I'm working with a legay database so I have to set managed = False, which means I cannot update the database schema.
What I'm trying to do is select branches based on project id. Ideally in branches table it should have a project_id as foreign key but the previous system design is another table (branches_projects) stores this relationship.
I have been able to get around some problems using https://docs.djangoproject.com/en/1.11/topics/db/sql/#django.db.models.Manager.raw. raw() would return an RawQuerySet, which is not ideal.
I wonder if there's a way for me to define a foreign key in my branches table, which is the project_id, but refer/link that to the branches_projects table?
class Branches(models.Model):
name = models.CharField(max_length=128)
branchpoint_str = models.CharField(max_length=255)
dev_lead_id = models.IntegerField(blank=True, null=True)
source = models.CharField(max_length=255)
state = models.CharField(max_length=255)
kind = models.CharField(max_length=255)
desc = models.TextField(blank=True, null=True)
approved = models.IntegerField()
for_customer = models.IntegerField()
deactivated_at = models.DateTimeField(blank=True, null=True)
created_at = models.DateTimeField(blank=True, null=True)
updated_at = models.DateTimeField(blank=True, null=True)
codb_id = models.IntegerField(blank=True, null=True)
pm_lead_id = models.IntegerField(blank=True, null=True)
version = models.CharField(max_length=20, blank=True, null=True)
path_id = models.IntegerField(blank=True, null=True)
branchpoint_type = models.CharField(max_length=255, blank=True, null=True)
branchpoint_id = models.IntegerField(blank=True, null=True)
class Meta:
managed = False
db_table = 'branches'
verbose_name_plural = 'Branches'
class Projects(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=40, primary_key=True)
status = models.CharField(max_length=255)
platform = models.CharField(max_length=255)
enabled = models.IntegerField()
path = models.CharField(max_length=128, blank=True, null=True)
tag_prefix = models.CharField(max_length=64, blank=True, null=True)
created_at = models.DateTimeField(blank=True, null=True)
updated_at = models.DateTimeField(blank=True, null=True)
codb_id = models.IntegerField(blank=True, null=True)
template = models.CharField(max_length=64, blank=True, null=True)
image_path = models.CharField(max_length=128, blank=True, null=True)
repository_id = models.IntegerField(blank=True, null=True)
number_scheme = models.CharField(max_length=32)
special_dir = models.CharField(max_length=32, blank=True, null=True)
project_family_id = models.IntegerField()
class Meta:
managed = False
db_table = 'projects'
verbose_name_plural = 'projects'
class BranchesProjects(models.Model):
# project_id = models.IntegerField()
# branch_id = models.IntegerField()
project = models.ForeignKey(Projects, on_delete=models.CASCADE)
branch = models.ForeignKey(Branches, on_delete=models.CASCADE)
class Meta:
managed = False
db_table = 'branches_projects'
My current raw query is like this
SELECT br.id, br.name, br.created_at, br.updated_at,
br.branchpoint_str, br.source
FROM branches as br
LEFT JOIN branches_projects as bp
ON br.id = bp.branch_id
WHERE bp.project_id = %s AND source != 'other'
ORDER BY updated_at DESC

I've finally got it working......
In the model, I use the manytomany as following:
class Branches(models.Model):
name = models.CharField(max_length=128)
project = models.ManyToManyField(Projects,
through='BranchesProjects',
related_name='project')
branchpoint_str = models.CharField(max_length=255)
Then to get the same result as my raw sql, i do the following:
def get_sb(project_id):
result = Branches.objects.filter(
project=Projects.objects.get(id=project_id).id,
).exclude(source='other').order_by('-updated_at')
print result.query
return result

Related

having error (1054, "Unknown column 'order_product.id' in 'field list'") in django

I create the models file with inspectdb, but it gives an error when I want to show it in Admin panel:
(1054, "Unknown column 'order_product.id' in 'field list'")
In my searches, I realized I had to add a primary key to each of the models, but nothing happened when I did that.
Here is my code:
# models.py
class OrderProduct(models.Model):
order = models.ForeignKey('Orders', models.DO_NOTHING)
product = models.ForeignKey('Products', models.DO_NOTHING)
attribute = models.ForeignKey(Attributes, models.DO_NOTHING, blank=True, null=True)
color = models.ForeignKey(Colors, models.DO_NOTHING, blank=True, null=True)
price = models.IntegerField(blank=True, null=True)
attribute_price_differ = models.IntegerField(blank=True, null=True)
attribute_price = models.IntegerField(blank=True, null=True)
number = models.IntegerField(blank=True, null=True)
class Meta:
managed = False
db_table = 'order_product'
class Orders(models.Model):
id = models.BigAutoField(primary_key=True)
user = models.ForeignKey('Users', models.DO_NOTHING)
price = models.IntegerField()
weight = models.IntegerField()
coupon = models.ForeignKey(Coupons, models.DO_NOTHING, blank=True, null=True)
status = models.IntegerField()
process_status = models.IntegerField()
code = models.CharField(max_length=255)
hash = models.CharField(max_length=255)
created_at = models.DateTimeField(blank=True, null=True)
updated_at = models.DateTimeField(blank=True, null=True)
class Meta:
managed = False
db_table = 'orders'
# admin.py
#admin.register(OrderProduct)
class PostAdmin(admin.ModelAdmin):
pass

Django Need to add two serializers data together in one response

I have a two models, Person and Video.
Below viewset allows me all methods like POST, PATCH, DELETE, GET.
class PersonViewSet(viewsets.ModelViewSet):
queryset = apis_models.Person.objects.all()
serializer_class = apis_serializers.PersonSerializer
permission_classes = [HasPermPage]
Video model is associated with person model through Target model which is my main problem. Each person has few videos.
Now what I need is when I do "/person/{id}/" I should get person details along with all videos details it associated with.
Please let me know what change needs to be done to above ViewSet.
Models and Serializer:
class Video(DFModel):
source = models.ForeignKey(Source, models.DO_NOTHING)
creator = models.ForeignKey(
Creator, models.DO_NOTHING, blank=True, null=True)
title = models.CharField(max_length=500)
views = models.IntegerField(blank=True, null=True)
likes = models.IntegerField(blank=True, null=True)
dislikes = models.IntegerField(blank=True, null=True)
tags = models.TextField(blank=True, null=True)
upload_date = models.DateTimeField(blank=True, null=True)
page_url = models.TextField(blank=True, null=True)
video_url = models.TextField(blank=True, null=True)
thumb_url = models.TextField(blank=True, null=True)
sfw = models.BooleanField(blank=True, null=True)
category = models.CharField(max_length=20, blank=True, null=True)
reviewed = models.TextField(blank=True, null=True)
severity = models.CharField(max_length=10, blank=True, null=True)
origin = models.CharField(max_length=20, blank=True, null=True)
organization_id = models.IntegerField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
class Person(models.Model):
name = models.CharField(unique=True, max_length=45)
nationality = models.CharField(max_length=50, blank=True, null=True)
profession = models.CharField(max_length=50, blank=True, null=True)
avatar = models.CharField(max_length=100, blank=True, null=True)
active_scraping = models.BooleanField(blank=True, null=True)
vuln_score = models.FloatField(blank=True, null=True, default=None)
reviewed = models.TextField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
class Target(DFModel):
person = models.ForeignKey(
Person, models.DO_NOTHING, blank=True, null=True)
video = models.ForeignKey(
'Video', models.DO_NOTHING, blank=True, null=True)
reviewed = models.TextField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
class Meta:
db_table = 'target'
class PersonSerializer(CustomSerializer):
class Meta:
model = apis_models.Person
fields = '__all__'
class TargetSerializer(CustomSerializer):
class Meta:
model = apis_models.Target
fields = '__all__'
extra_fields = ['monthly_growth', 'vulnerablility_score']
class VideoSerializer(CustomSerializer):
source = SourceSerializer(read_only=True)
creator = CreatorSerializer(read_only=True)
class Meta:
model = apis_models.Video
fields = '__all__'
It looks like you have a ManyToMany relation between Person and Video, so, I suggest you to change your models to be like:
class Person(models.Model):
name = models.CharField(unique=True, max_length=45)
nationality = models.CharField(max_length=50, blank=True, null=True)
profession = models.CharField(max_length=50, blank=True, null=True)
avatar = models.CharField(max_length=100, blank=True, null=True)
active_scraping = models.BooleanField(blank=True, null=True)
vuln_score = models.FloatField(blank=True, null=True, default=None)
reviewed = models.TextField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
videos = models.ManyToManyField(Video, through='Target', related_name="people") # Field that will have the videos of a Person
Once you have that, I suggest you to change your PersonSerializer object to be:
class PersonSerializer(CustomSerializer):
videos = VideoSerializer(source='videos', many=True)
class Meta:
model = apis_models.Person
fields = '__all__'
If you can't change your models to support ManyToMany fields I suggest you to do the following:
class Person(models.Model):
name = models.CharField(unique=True, max_length=45)
nationality = models.CharField(max_length=50, blank=True, null=True)
profession = models.CharField(max_length=50, blank=True, null=True)
avatar = models.CharField(max_length=100, blank=True, null=True)
active_scraping = models.BooleanField(blank=True, null=True)
vuln_score = models.FloatField(blank=True, null=True, default=None)
reviewed = models.TextField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
def videos(self):
return Video.objects.filter(
id__in=Target.objects.filter(person=self).values('video')
)
And use the same serializer I used in the first part of the answer.

Merge 2 models (tables) in Django and show it in my template

I have 2 models one defines all the all the devices that I have, and the other stores the information that the devices are obtaining. The code of they is the following,
class Device(models.Model):
dev_eui = models.CharField(max_length=16, primary_key=True)
producer = models.CharField(max_length=20, blank=True, null=True)
model = models.CharField(max_length=20, blank=True, null=True)
firmware = models.CharField(max_length=10, blank=True, null=True)
dev_name = models.CharField(max_length=20, blank=True, null=True)
description = models.CharField(max_length=40, blank=True, null=True)
fixed = models.BooleanField()
dev_lat = models.FloatField(null=True, blank=True)
dev_lon = models.FloatField(null=True, blank=True)
deco_name = models.CharField(max_length=20)
fleet_id = models.IntegerField(null=True, blank=True)
class DevData(models.Model):
data_uuid = models.UUIDField(primary_key=True, default=uuid.uuid1, editable=False)
data_id = models.IntegerField()
dev_eui = models.CharField(max_length=16)
gateway = models.CharField(max_length=25)
data_timestamp = models.DateTimeField()
rssi = models.IntegerField()
snr = models.IntegerField()
datarate = models.CharField(max_length=15)
frequency = models.IntegerField()
seq = models.IntegerField()
data_1 = models.FloatField()
data_2 = models.FloatField(null=True, blank=True)
data_3 = models.FloatField(null=True, blank=True)
data_4 = models.FloatField(null=True, blank=True)
data_5 = models.FloatField(null=True, blank=True)
data_6 = models.FloatField(null=True, blank=True)
data_7 = models.FloatField(null=True, blank=True)
Actually what I want is show a table in my template, combining all the data from devData and adding the dev_name and fleet_id from devices.
Now what I'm doing is obtaining all the data and in the template filtering it. But I'm sure it's better and easier doing this in the views.py, but I don't know how.
Reading some info, I found the union() function but it's not working and I'm not sure if is the best option,
#login_required(login_url='/user_app/login/')
def user_data(request):
dev_data = DevData.objects.all()
devices = Device.objects.all()
test = DevData.objects.all().values_list(
"dev_eui"
).union(
Device.objects.all().values_list(
"dev_eui"
))
ctx = {'DevData':dev_data,'Devices':devices, 'Test':test}
return render(request, template_name='data.html', context=ctx)
This join shows nothing.
Can somebody help me? Thank very much!
You need a foreign key relating the two models.
class Device(models.Model):
dev_eui = models.CharField(max_length=16, primary_key=True)
class DevData(models.Model):
device = models.ForeignKeyField(Device, related_name='dev_data', on_delete=models.CASCADE)
data_uuid = models.UUIDField(primary_key=True, default=uuid.uuid1, editable=False)
data_id = models.IntegerField()
# This is not needed, it can be accessed via instance.device.dev_eui now
# dev_eui = models.CharField(max_length=16)
Then to get all of the DevData instances for a particular device:
for device in Device.objects.all():
x = device.dev_data.all()
Please read the documentation to better understand relationship fields.

How to select specific tables from related tables(Django)?

I have a query that links five tables. In some of them I need one (name from contractor) field. Therefore, I want to optimize this and select only one field), and not the entire table. How can I edit this code?
paymentsss = Transaction.objects.all().select_related('currency',
'payment_source__payment_type', 'deal__service','deal__service__contractor')
Turns into
SELECT "processing"."transaction"."id",
"processing"."transaction"."currency_id",
"processing"."transaction"."deal_id",
"processing"."transaction"."service_instance_id",
"processing"."transaction"."payment_source_id",
"processing"."transaction"."payment_date",
"processing"."transaction"."amount",
"processing"."transaction"."status",
"processing"."transaction"."context",
"processing"."currency"."id",
"processing"."currency"."name",
"processing"."currency"."iso_name",
"processing"."currency"."minor_unit",
"processing"."deal"."id",
"processing"."deal"."service_id",
"processing"."deal"."currency_id",
"processing"."deal"."adapter_account_id",
"processing"."deal"."amounts_rule",
"processing"."deal"."comission_rule",
"processing"."deal"."weight_rule",
"processing"."deal"."active",
"processing"."deal"."provider_enabled",
"processing"."deal"."min_amount",
"processing"."deal"."max_amount",
"processing"."deal"."payment_types",
"processing"."deal"."params",
"processing"."deal"."contractor_params",
"processing"."deal"."tags",
"processing"."service"."id",
"processing"."service"."flow_id",
"processing"."service"."currency_id",
"processing"."service"."contractor_id",
"processing"."service"."amount",
"processing"."service"."callback_url",
"processing"."service"."definition",
"processing"."service"."name",
"processing"."service"."description",
"processing"."service"."charge_strategy",
"processing"."service"."routine",
"processing"."service"."tags",
"processing"."contractor"."id",
"processing"."contractor"."name",
"processing"."contractor"."inn",
"processing"."contractor"."kpp",
"processing"."contractor"."bank_reg_id",
"processing"."contractor"."bank_reg_date",
"processing"."contractor"."slug",
"processing"."contractor"."uuid",
"processing"."contractor"."is_nds_payer",
"processing"."contractor"."tag",
"processing"."payer_payment_source"."id",
"processing"."payer_payment_source"."payer_id",
"processing"."payer_payment_source"."payment_type_id",
"processing"."payer_payment_source"."source_details",
"processing"."payment_type"."id",
"processing"."payment_type"."name",
"processing"."payment_type"."group_name"
FROM "processing"."transaction"
LEFT OUTER JOIN "processing"."currency"
ON ("processing"."transaction"."currency_id" = "processing"."currency"."id")
LEFT OUTER JOIN "processing"."deal"
ON ("processing"."transaction"."deal_id" = "processing"."deal"."id")
LEFT OUTER JOIN "processing"."service"
ON ("processing"."deal"."service_id" = "processing"."service"."id")
LEFT OUTER JOIN "processing"."contractor"
ON ("processing"."service"."contractor_id" = "processing"."contractor"."id")
LEFT OUTER JOIN "processing"."payer_payment_source"
ON ("processing"."transaction"."payment_source_id" = "processing"."payer_payment_source"."id")
LEFT OUTER JOIN "processing"."payment_type"
ON ("processing"."payer_payment_source"."payment_type_id" = "processing"."payment_type"."id")
ORDER BY "processing"."transaction"."id" DESC
What i want to delete
I highlighted in red those columns that I wanted to delete.
Some of models from models.py
class Contractors(models.Model):
id = models.IntegerField(blank=True, null=False, primary_key=True)
name = models.CharField(max_length=255, blank=True, null=True)
inn = models.CharField(max_length=14, blank=True, null=True)
kpp = models.CharField(max_length=14, blank=True, null=True)
bank_reg_id = models.CharField(max_length=255, blank=True, null=True)
bank_reg_date = models.DateField(blank=True, null=True)
slug = models.CharField(max_length=255, blank=True, null=True)
uuid = models.CharField(max_length=36, blank=True, null=True)
is_nds_payer = models.BooleanField(blank=True, null=True)
tag = models.TextField(blank=True, null=True) # This field type is a guess.
class Meta:
managed = False
db_table = '"processing"."contractor"'
class PaymentType(models.Model):
id = models.CharField(max_length=75, blank=True, null=False, primary_key=True)
name = models.CharField(max_length=128, blank=True, null=True)
group_name = models.CharField(max_length=64, blank=True, null=True)
class Meta:
managed = False
db_table = '"processing"."payment_type"'
class Service(models.Model):
id = models.IntegerField(db_index=True, blank=True, null=False, primary_key=True)
flow_id = models.IntegerField(blank=True, null=True)
currency_id = models.SmallIntegerField(blank=True, null=True)
contractor = models.ForeignKey(Contractors, blank=True, null=True, on_delete=models.CASCADE)
amount = models.IntegerField(blank=True, null=True)
callback_url = models.CharField(max_length=128, blank=True, null=True)
definition = models.TextField(blank=True, null=True) # This field type is a guess.
name = models.CharField(max_length=255, blank=True, null=True)
description = models.TextField(blank=True, null=True)
charge_strategy = models.CharField(max_length=64, blank=True, null=True)
routine = models.TextField(blank=True, null=True) # This field type is a guess.
tags = models.TextField(blank=True, null=True) # This field type is a guess.
class Meta:
managed = False
db_table = '"processing"."service"'
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)
class Meta:
managed = False
db_table = '"processing"."transaction"'
You can use defer to not load up the fields from related models:
https://docs.djangoproject.com/en/2.2/ref/models/querysets/#defer
So a (not complete) modification of your query to remove currency name:
paymentsss = Transaction.objects.all().select_related('currency', 'payment_source__payment_type', 'deal__service','deal__service__contractor').defer('currency__name')
I decided this by simply deleting the fields I did not need from the model.

One table filter is working fine for me but ,here i need to filter two tables filter in django which is not working

models.py:
class Department(models.Model):
department_id = models.AutoField(primary_key=True)
department_n_key = models.CharField(max_length=30,blank=True,unique=True)
hospital_short_name = models.CharField(max_length=20)
department_name = models.CharField(max_length=50)
class EmployeesMaster(models.Model):
employee_id = models.AutoField(primary_key=True)
employee_n_key = models.CharField(max_length=30,blank=True,unique=True)
first_name = models.CharField(max_length=30)
middle_name = models.CharField(max_length=30, blank=True, null=True)
last_name = models.CharField(max_length=30, blank=True, null=True)
gender = models.CharField(max_length=12, blank=True, null=True)
class PatientMaster(models.Model):
patient_id = models.AutoField(primary_key=True)
patient_n_key = models.CharField(max_length=30,blank=True,unique=True)
first_name = models.CharField(max_length=30)
middle_name = models.CharField(max_length=30, blank=True, null=True)
last_name = models.CharField(max_length=30, blank=True, null=True)
age = models.IntegerField(blank=True, null=True)
views.py
i need to apply this in django:
SELECT * FROM appointment_master WHERE patient_type='something' andappointment_master.department_n_key IN (SELECT department.department_n_key FROM department WHERE department.department_name='something')
help somebody to apply this in django
It's not optimal but you can do it in two Queries
departments_list= Department.objects.filter(departmen_name='foo').values_list('department_n_key', flat=True)
apointment_master = YourModel.objects.filter(patient_type='bar', department_n_key__in=departments_list)