Django Need to add two serializers data together in one response - django

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.

Related

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.

Restrict choices using two foreignkey relationships in django

I have three models, a household model, a household-member model, and an occupations models as described below. I would like the occupations model to only show members that belong to a particular household (which is related to field sno). How does one do something like this?
Would be grateful for any help.
class Household(models.Model):
village = models.CharField(max_length=150, null=True, blank=True)
household_number = models.IntegerField(blank=True, null=True)
form_number = models.IntegerField(null=True,blank=True)
head_of_household = models.CharField(max_length=150, null=True, blank=True)
class member(models.Model):
sno = models.ForeignKey(Household, on_delete=models.CASCADE)
person_number = models.IntegerField(blank=True, null=True)
name = models.CharField(max_length=150, null=True, blank=True)
sex_choices2 = (
('M','Male'),
('F','Female'),
)
sex = models.CharField(max_length=3,choices=sex_choices2,blank=True, null=True)
age = models.CharField(max_length=30,blank=True, null=True)
class Meta:
unique_together = (("sno", "person_number"),)
def __unicode__(self):
return self.name
def __str__(self):
return self.name
class occupations(models.Model):
sno = models.ForeignKey(Household,on_delete=models.CASCADE)
person_number = models.IntegerField(blank=True, null=True)
name = models.ForeignKey(member, blank=True, on_delete=models.SET_NULL, null=True)
occupation = models.CharField(max_length=100, null=True, blank=True)
class Meta:
unique_together = (("sno", "person_number","occupation"),)

Django models.ForeignKey issue with model with custom foreign key

I use Django 1.11, Python 3.6 and PostgreSQL 9.6.
I define two models as described in the documentation.
class CircDetect(models.Model):
oid = models.AutoField(primary_key=True)
...
class Meta:
db_table = 'circdetect'
class PatientMed(models.Model):
...
circdetect = models.ForeignKey(CircDetect, on_delete=models.CASCADE, to_field='oid')
...
But when I try to get an access to the list of PatientMed objects on the admin site I get an exception:
ProgrammingError at /canreg/editor/patientmed/
column patient_med.circdetect_id does not exist
LINE 1: ... "patient_info"."id") INNER JOIN "circdetect" ON ("patient_m...
HINT: Perhaps you meant to reference the column "patient_med.circdetect".
It looks like Django tries to get id filed of circdetect, which is actually has name oid.
What can I do to fix this issue?
EDITED on 21 jul
As Ahmad took note below, I have an another model, that I didn't mention. I'm not sure it affects on the error in this case but this is that model:
class PatientInfo(models.Model):
...
class Meta:
db_table = 'patient_info'
And PatientMed is connected with PatientInfo this way:
class PatientMed(models.Model):
info = models.OneToOneField(PatientInfo, on_delete=models.CASCADE, primary_key=True)
...
But it works without any problems.
I should say, that circdetect is a legacy table, that I already had in my database when I started work.
EDITED
I use this code to show PatientMed objects in the admin site:
class PatientMedAdmin(admin.ModelAdmin):
list_display = (
'info',
...
'circdetect',
...
)
list_per_page = 25
admin.site.register(models.PatientMed, PatientMedAdmin)
EDITED
As Alasdair ask below I put here full models. There is no secret in them, but they are big
class CircDetect(models.Model):
oid = models.AutoField(primary_key=True)
code = models.SmallIntegerField(blank=True, null=True)
txt = models.CharField(max_length=50, blank=True, null=True)
class Meta:
db_table = 'circdetect'
ordering = ['code']
class PatientInfo(models.Model):
objects = models.Manager()
first_name = models.CharField(max_length=50, blank=True, null=True)
last_name = models.CharField(max_length=50, blank=True, null=True)
patronymic = models.CharField(max_length=50, blank=True, null=True)
birth_date = models.DateField(blank=True, null=True)
zip_code = models.CharField(max_length=6, blank=True, null=True)
address = models.TextField(blank=True, null=True)
home_phone = models.CharField(max_length=11, blank=True, null=True)
cell_phone = models.CharField(max_length=11, blank=True, null=True)
e_mail = models.EmailField(null=True)
def __str__(self):
return u'%s %s %s %s' % (to_str(self.last_name), to_str(self.first_name),
to_str(self.patronymic), to_str(self.birth_date))
class Meta:
db_table = 'patient_info'
class PatientMed(models.Model):
objects = models.Manager()
info = models.OneToOneField(PatientInfo, on_delete=models.CASCADE, primary_key=True)
center = models.SmallIntegerField(blank=True, null=True)
sex = models.SmallIntegerField(blank=True, null=True)
fddate = models.DateField(blank=True, null=True)
tsdate = models.DateField(blank=True, null=True)
tdate = models.DateField(blank=True, null=True)
edate = models.DateField(blank=True, null=True)
otcode = models.SmallIntegerField(blank=True)
ddate = models.DateField(blank=True, null=True)
death_icd = models.CharField(max_length=7, blank=True, null=True)
ecode = models.SmallIntegerField(blank=True, null=True)
esource = models.SmallIntegerField(blank=True, null=True)
dcause = models.SmallIntegerField(blank=True, null=True)
dsource = models.SmallIntegerField(blank=True, null=True)
numtumor = models.SmallIntegerField(blank=True, null=True)
iccc = models.CharField(max_length=3, blank=True, null=True)
icd_10 = models.CharField(max_length=7, blank=True, null=True)
icd_o = models.CharField(max_length=5, blank=True, null=True)
fds = models.TextField(blank=True, null=True)
circdetect = models.ForeignKey(to=CircDetect, on_delete=models.CASCADE, to_field='oid')
hyst = models.CharField(max_length=5, blank=True, null=True)
cyto = models.CharField(max_length=5, blank=True, null=True)
exp_oper = models.CharField(max_length=5, blank=True, null=True)
immun = models.CharField(max_length=5, blank=True, null=True)
cytogen = models.CharField(max_length=5, blank=True, null=True)
lab_instr = models.CharField(max_length=5, blank=True, null=True)
incentr = models.CharField(max_length=5, blank=True, null=True)
lasttest = models.DateField(blank=True, null=True)
lastsource = models.SmallIntegerField(blank=True, null=True)
lfudate = models.DateField(blank=True, null=True)
lfucode = models.SmallIntegerField(blank=True, null=True)
otregion = models.CharField(max_length=5, blank=True, null=True)
date_actend = models.DateField(blank=True, null=True)
concord = models.SmallIntegerField(blank=True, null=True)
protocol = models.CharField(max_length=10, blank=True, null=True)
autopsie = models.CharField(max_length=5, blank=True, null=True)
tabort = models.SmallIntegerField(blank=True, null=True)
stage = models.SmallIntegerField(blank=True, null=True)
stage_sym = models.CharField(max_length=4, blank=True, null=True)
chirurg = models.CharField(max_length=5, blank=True, null=True)
radiolog = models.CharField(max_length=5, blank=True, null=True)
chimio = models.CharField(max_length=5, blank=True, null=True)
rdate = models.DateField(blank=True, null=True)
rem = models.TextField(blank=True, null=True)
t_tnm = models.SmallIntegerField(blank=True, null=True)
n_tnm = models.SmallIntegerField(blank=True, null=True)
m_tnm = models.SmallIntegerField(blank=True, null=True)
g_tnm = models.SmallIntegerField(blank=True, null=True)
encr_bas = models.SmallIntegerField(blank=True, null=True)
ct_tnm = models.SmallIntegerField(blank=True, null=True)
cn_tnm = models.SmallIntegerField(blank=True, null=True)
cm_tnm = models.SmallIntegerField(blank=True, null=True)
land = models.IntegerField(blank=True, null=True)
lum = models.CharField(max_length=5, blank=True, null=True)
oss = models.CharField(max_length=5, blank=True, null=True)
hepar = models.CharField(max_length=5, blank=True, null=True)
lung = models.CharField(max_length=5, blank=True, null=True)
brain = models.CharField(max_length=5, blank=True, null=True)
skin = models.CharField(max_length=5, blank=True, null=True)
nephro = models.CharField(max_length=5, blank=True, null=True)
herm = models.CharField(max_length=5, blank=True, null=True)
periton = models.CharField(max_length=5, blank=True, null=True)
kmark = models.CharField(max_length=5, blank=True, null=True)
unknown = models.CharField(max_length=5, blank=True, null=True)
other = models.CharField(max_length=5, blank=True, null=True)
acc = models.IntegerField()
class Meta:
db_table = 'patient_med'
It sounds like you have to specify db_column, to let Django know the name of the column in the PatientMed column.
class PatientMed(models.Model):
circdetect = models.ForeignKey(CircDetect, on_delete=models.CASCADE, db_column='circdetect', to_field='oid')
You haven't written the instruction that makes the error. But it seems that you have another table named PatientInfo that the error is related to.
I'm not sure what was the cause of the problem. I solved it by dropping my database and recreating it and my entities.
Thank you everyone.

Make a query to django models

How is "translation" for following query to django queryset?
SELECT guid FROM feedme_feeditem
WHERE feed_id IN
(SELECT id FROM feedme_feed WHERE country_id IN
(SELECT id FROM feedme_country WHERE name='NL'))
models.py
class Country(models.Model):
name = models.CharField(max_length=250, blank=True)
class Category(models.Model):
name = models.CharField(max_length=250, blank=True)
slug = models.SlugField(blank=True, null=True, editable=False)
user = models.ForeignKey(User, blank=True, null=True)
country = models.ForeignKey(Country, blank=True, null=True)
class Feed(models.Model):
link = models.CharField(blank=True, max_length=450)
url = models.CharField(blank=True, max_length=450)
title = models.CharField(blank=True, null=True, max_length=250)
category = models.ForeignKey(Category, blank=True, null=True)
user = models.ForeignKey(User, blank=True, null=True)
last_update = models.DateField(blank=True, null=True, editable=False)
country = models.ForeignKey(Country, blank=True, null=True)
class FeedItem(models.Model):
title = models.CharField(max_length=350, blank=True)
link = models.URLField(blank=True)
content = models.TextField(blank=True)
feed = models.ForeignKey(Feed, blank=True, null=True)
read = models.BooleanField(default=False)
guid = models.CharField(max_length=255)
pub_date = models.DateTimeField()
To make more simple I already tried add country = models.ForeignKey(Country, blank=True, null=True) to FeedItem class but does't work how i expected.
guids = FeedItem.objects.filter(feed__country__name = 'NL')

function in models is unrecognizable

I trying extend existed models so I added 'thumbnails' in to it. Unfortunately function related to this is not recognized and django console gives me:
thumbnail = models.ImageField(upload_to=_get_upload_image, blank=True, null=True)
NameError: name '_get_upload_image' is not defined
Could someone help me with this issue?
Django 1.6.5 models.py (short version)
class Feed(models.Model):
link = models.CharField(blank=True, max_length=450)
url = models.CharField(blank=True, max_length=450)
title = models.CharField(blank=True, null=True, max_length=250)
category = models.ForeignKey(Category, blank=True, null=True)
user = models.ForeignKey(User, blank=True, null=True)
last_update = models.DateField(blank=True, null=True, editable=False)
country = models.ForeignKey(Country, blank=True, null=True)
thumbnail = models.ImageField(upload_to=_get_upload_image, blank=True, null=True)
class Meta:
unique_together = (
("url", "user"),
)
def _get_upload_image(instance, filename):
return "images/%s_%S" % (str(time()).replace('.','_'), filename)
I solved this through placing function on top of class
class Feed(models.Model):
def _get_upload_image(instance, filename):
return "images/%s_%S" % (str(time()).replace('.','_'), filename)
link = models.CharField(blank=True, max_length=450)
url = models.CharField(blank=True, max_length=450)
title = models.CharField(blank=True, null=True, max_length=250)
category = models.ForeignKey(Category, blank=True, null=True)
user = models.ForeignKey(User, blank=True, null=True)
last_update = models.DateField(blank=True, null=True, editable=False)
country = models.ForeignKey(Country, blank=True, null=True)
thumbnail = models.ImageField(upload_to=_get_upload_image, blank=True, null=True)