How to order_by related field date with annotation? - django

i have this model :
class Node(MPTTModel):
parent = TreeForeignKey('self', on_delete=models.CASCADE, blank=True, null=True, related_name='children')
name = models.TextField(blank=True, null=True)
which have this related model :
class Views(models.Model):
related_tree = models.ForeignKey(Node, on_delete=models.CASCADE, blank=True, null=True, related_name='related_views')
views_count = models.PositiveIntegerField(null=True, blank=True, default=0)
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, blank=True, null=True)
view_date = models.DateTimeField(default=timezone.now)
What i am trying to do is to order a queryset of the first model by the view date of the second one, this is the view that i have tried :
last_viewed_trees = Node.objects.filter(tree_type='root').order_by('-related_views__view_date')
In that one the result is correct but i have a duplicate view_date of many users.
I have tried also this one without success :
last_viewed_trees = Node.objects.filter(tree_type='root').annotate(time_of_views= Min('related_views__views_count')
).order_by('-time_of_views')
last_viewed_trees = Node.objects.filter(tree_type='root').annotate(time_of_views= Max('related_views__views_count')
).order_by('-time_of_views')
Nothing have worked for me, there is something that i am missing, but i cannot identify it.

Related

Joining more than 2 tables for reports in django and extract all the fields from the joined table

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()

Django reverse nested filtering

I want to make a filter on a nested Model with the Django reverse relation. Below is the sample models I have :
class ProcessVersion(TimeStampedModel):
tag = models.CharField(_('Tag Name'), max_length=48)
status = FSMField(
_('Status'), max_length=12, choices=VERSION_STATUS_CHOICES,
default=VERSION_STATUS_IN_EDITION)
class Step(models.Model):
version = models.ForeignKey(
ProcessVersion, verbose_name=_('Process Version'),
on_delete=models.CASCADE, related_name='steps', blank=True,
null=True)
is_active = models.BooleanField(
_('Is active'), default=False)
title = models.CharField(_('Title'), max_length=32)
class Block(models.Model):
step = models.ForeignKey(
Step, verbose_name=_('Loan Process Step'), on_delete=models.CASCADE,
related_name='blocks', blank=True, null=True)
is_active = models.BooleanField(
_('Is active'), default=False)
title = models.CharField(_('Title'), max_length=128, blank=True)
The first scenario was accessing the Step through it's related name and it worked :
process_version = ProcessVersion.objects.get(id=process_version_id)
steps = process_version.steps.get(id=param_id)
meaning that I passed through ProcessVersion to get the Step.
Now, my question is what if I want to get the Block but passing through ProcessVersion with it's id , how can I query that ?

Search Two Django Tables once within singel query

I am really confusing about Django joins. I want to search a keyword in two tables with a single query. can anyone help me?
the app model structure like this
class Events(models.Model):
event_type = models.CharField(_("Event Type"), max_length=5, choices=event_type_choices)
webinar_title = models.CharField(_("Webinar Title"), max_length=50, blank=True, null=True)
event_name = models.CharField(_("Event Name"), max_length=50, blank=True, null=True)
banner_title = models.CharField(_("Banner Title"), max_length=50, blank=True, null=True)
added_by = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL)
status = models.BooleanField(_("Event Status"), default=True)
class Meta:
verbose_name = _('Event')
db_table = 'events'
app_label = 'events'
class WebinarSpeakers(models.Model):
event = models.ForeignKey(Events, on_delete=models.CASCADE, null=True)
speaker = models.CharField(_("Speaker Name"), max_length=100, null=True, blank=True)
job_title = models.CharField(_("Job Title"), max_length=255)
place_of_work = models.CharField(_("Place of Work"), max_length=100)
credentials = models.TextField(_("Credentials"), null=True, blank=True)
image = models.ImageField(_("Speaker Image"), upload_to=speaker_file_name, null=True, blank=True)
class Meta:
verbose_name = _('Event Webinar Speakers')
db_table = 'webinar_speakers'
app_label = 'events'
Now I want to search a keyword in webinar_title, evetn_name, banner_title, speaker, 'job_title` with a single query. how to do it in Django joins. I read the select_related document. it confusing me.
WebinarSpeakers.objects.filter(event__webinar_title="something", event__event_name="something", event__banner_title="somethng", speaker="something",job_title="something")

Column core_event.hometask does not exist

When I run my Django project on production server, I have this error:
ProgrammingError at /admin/core/event/
column core_event.hometask does not exist
LINE 1: ..._event"."is_approved", "core_event"."event_type", "core_even...
What I should do to fix it? Now I haven't "hometask" field in my model:
class Event(models.Model):
name = models.CharField(max_length=100, null=True)
author = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
description = models.TextField(max_length=1000, blank=True, null=True)
date_start = models.DateTimeField(null=True, blank=True)
date_finish = models.DateTimeField(null=True, blank=True)
image = models.ImageField(
upload_to="event_images/", default='event_images/default.png', blank=True, null=True)
is_approved = models.BooleanField(null=True)
TYPE_CHOICES = (
('Event', "Мероприятие"),
('Lesson', "Урок"),
)
event_type = models.CharField(choices=TYPE_CHOICES, max_length=200, default="Мероприятие")
topics = ArrayField(models.CharField(max_length=200), blank=True, null=True)
materials = ArrayField(models.URLField(), blank=True, null=True)
possible_users = models.ManyToManyField("core.User", blank=True, related_name='possible_users')
actual_users = models.ManyToManyField("core.User", blank=True, related_name='actual_users')
classes = models.ManyToManyField("core.Class", blank=True, related_name='classes')
From what you posted, looks like the field existed in the model before but not anymore. However, your admin.py still has reference to the old field of hometask.
So, go to admin.py, search for hometask, and remove it.

Why django inspectdb doesn't create foreign keys correctly on an existing database? [duplicate]

django=2.2.3
mariadb
This error occurs after importing model from an existing database with 'inspectdb' and changed field properties.
class Post(models.Model):
post_id = models.AutoField(primary_key=True)
post_name = models.CharField(max_length=255, blank=True, null=True)
email = models.CharField(max_length=255, blank=True, null=True)
class Rank(models.Model):
rank_id = models.AutoField(primary_key=True)
rank_type = models.IntegerField(blank=True, null=True)
created_at = models.DateTimeField()
# post_id = models.IntegerField(blank=True, null=True)
post_id = models.ForeignKey(Post, on_delete=models.SET_NULL, blank=True, null=True)
Originally, it was # post_id, but I removed "managed = False", changed it to ForeignKey and then "migrate".
As far as I know that if the "post_id" in the "Post" model is "primary_key True", it replaces the "id" value with "post_id". But "Django" keeps calling up the "post_id_id".
There is no command to refer to post_id_id elsewhere.
If you have a solution or something that I'm missing, please give me some advice.
-------Add more after commented by Daniel Roseman --------
class Post(models.Model):
post_id = models.AutoField(primary_key=True)
post_name = models.CharField(max_length=255, blank=True, null=True)
email = models.CharField(max_length=255, blank=True, null=True)
class Gallery(models.Model):
uid = models.AutoField(prymary_key=True)
gallery_name = models.CharField(...)
class Rank(models.Model):
rank_id = models.AutoField(primary_key=True)
rank_type = models.IntegerField(blank=True, null=True)
created_at = models.DateTimeField()
# post_id = models.IntegerField(blank=True, null=True)
post_id = models.ForeignKey(Post, on_delete=models.SET_NULL, blank=True, null=True)
# uid = models.IntegerField(blank=True, null=True)
uid = models.ForeignKey(Gallery, on_delete=models.SET_NULL, blank=True, null=True)
Don't call your ForeignKey post_id. Call it post. The underlying database field is post_id; Django adds the _id suffix automatically.