how to select data between 2 dates using sql queries in django? - python

models.py
My models.py
class Custom_user_model(User):
daily_target = models.IntegerField()
monthly_target = models.IntegerField()
yearly_target = models.IntegerField()
weekly_target = models.IntegerField()
call_target = models.IntegerField()
email_target = models.IntegerField()
meeting_target = models.IntegerField()
added_under = models.IntegerField()
profile_pic = models.TextField()
doj = models.DateTimeField(default='')
location_id = models.IntegerField()
locked = models.BooleanField()
default_currency = models.IntegerField()
date_change_permission = models.BooleanField()
deal_back_log = models.BooleanField()
created_date=models.DateTimeField(auto_now_add=True)
role_id=models.IntegerField()
profile_pic = models.FileField(upload_to='.')
objects = UserManager()
//This custom_user model is the extension of django's default user model.
class Deal(models.Model):
a_choices = ((0,'yes'),(1,'no'))
approved = models.IntegerField(choices=a_choices,default=1)
user_id = models.IntegerField()
company_id = models.IntegerField()
contact_id = models.IntegerField()
deal_title=models.CharField(max_length=200)
deal_value = models.CharField(max_length=20)
currency_id = models.IntegerField()
process_id = models.IntegerField()
expected_close_date = models.DateField(default='')
closed_date = models.DateField()
deal_milestone=models.IntegerField()
created=models.DateTimeField(auto_now_add=True)
last_modified=models.DateTimeField(auto_now_add=True)
s_choices = ((0,'active'),(1,'won'),(2,'junk'),(3,'lost'))
status = models.IntegerField(choices=a_choices,default=0)
type = models.CharField(max_length=50, default='deal')
source = models.CharField(max_length=50,default='O')
class user_Roles(models.Model):
code = models.CharField(max_length=20)
description = models.CharField(max_length=30)
permitted_menus = models.CharField(max_length=200)
created = models.DateTimeField(auto_now_add=True)
Using user_roles model, I have assigned permission for accessing data to the newly created user based on his/her role. I want to get the created deals which are added by the users having role_id = 2 and deals created date between the specified dates .
### views.py
st_date, end_date = week_magic(date.today())
cur = connection.cursor()
cur.execute("select *, CONCAT(au.first_name,' ',au.last_name) as full_name from myapp_custom_user_model mu left join auth_user au on mu.user_ptr_id = au.id INNER JOIN myapp_user_roles ml on ml.id= 2 and ml.id = mu.role_id LEFT JOIN (SELECT user_id,SUM( deal_value ) AS cnt FROM myapp_deal where status = 1 and DATE_FORMAT(closed_date,'%Y-%m-%d') BETWEEN " '%s' " and " '%s' " GROUP BY user_id)d ON mu.user_ptr_id = d.user_id where mu.locked !=1 and mu.role_id = 2 order by COALESCE( d.cnt, 0 ) DESC",(st_date,end_date))
users = dictfetchall(cur)
cur.close()
While executing the query it shows unsupported format error. So I used one more % symbol in the same query as follows:
cur.execute("select *, CONCAT(au.first_name,' ',au.last_name) as full_name from myapp_custom_user_model mu left join auth_user au on mu.user_ptr_id = au.id INNER JOIN myapp_user_roles ml on ml.id= 2 and ml.id = mu.role_id LEFT JOIN (SELECT user_id,SUM( deal_value ) AS cnt FROM myapp_deal where status = 1 and DATE_FORMAT(closed_date,'%%Y-%%m-%%d') BETWEEN " '%s' " and " '%s' " GROUP BY user_id)d ON mu.user_ptr_id = d.user_id where mu.locked !=1 and mu.role_id = 2 order by COALESCE( d.cnt, 0 ) DESC" %(st_date,end_date))
It doesn't give any error but the result is empty even though there is data because of this syntax: DATE_FORMAT(closed_date,'%%Y-%%m-%%d'). How to solve this?

First of all you should use ForeignKey fields for role_id in Custom_user_model and user_id in Deal. The same is probably true for some of the other _id fields in your models.
class Custom_user_model(User):
...
role = models.ForeignKey('Role')
...
class Deal(models.Model):
...
user = models.ForeignKey('Custom_user_model')
...
After that you can do your query like this:
# get deals from users with role_id=2
query = Deal.objects.filter(user__role_id=2)
# add filter for deals created by that user created between
start_date, end_date = week_magic(date.today())
query = query.filter(created__between=(start_date, end_date))

Related

How to return sum according to date range in django?

It'd be really nice if someone could help me with this. I've stuck here. I'm able to do this manually but how to do according to user input.
Payment.objects.filter(created_by=42, mode='cash', created_at__range=["2021-11-01", "2021-11-04"]).aggregate(Sum('amount'))
Here created_by and date_range I'm sending in url like this : http://127.0.0.1:8000/api/v1/registration/?created_by=42&start_date=2021-06-06&end_date=2021-11-18 so the id created by and date_range will always change. And according to change the sum will return.
My Model :
class Payment(TimestampedModel):
customer_visit = models.ForeignKey(
CustomerVisit, on_delete=models.CASCADE, null=True, related_name="customer_payments"
)
mode = models.CharField(choices=PAYMENTCHOICES, max_length=25)
amount = models.FloatField()
ref_no = models.TextField(null=True)
bank = models.ForeignKey(
"BankDetails", on_delete=models.CASCADE, null=True, related_name="payment_bank"
)
is_settlement = models.BooleanField(default=False)
created_by = models.ForeignKey("Employee", on_delete=models.DO_NOTHING, null=True,related_name='payment_created_by')
updated_by = models.ForeignKey("Employee", on_delete=models.DO_NOTHING, null=True,related_name='payment_updated_by')
My View :
class UserWiseCollectionView(ListAPIView):
permission_classes = [
IsAuthenticated,
]
pagination_class = CustomPagination
model = CustomerVisit
serializer_class = UserWiseCollectionSerializer
filter_backends = [DjangoFilterBackend]
filterset_fields = ['created_by']
def get_queryset(self):
start_date = self.request.query_params.get("start_date")
end_date = self.request.query_params.get("end_date")
emp_id = self.request.query_params.get("emp_id")
items = self.model.objects.all()
if start_date and end_date:
items = items.filter(
created_at__range=[start_date, end_date]
)
if emp_id is not None:
items = items.filter(phelebotomist_id = emp_id)
return items
If requirement is to get all the rows created by specific employee within the specific date range, below code might work.
Requirement
Payment.objects.filter(created_by=42, mode='cash', created_at__range=["2021-11-01", "2021-11-04"]).aggregate(Sum('amount'))
View code
def get_queryset(self):
start_date = self.request.query_params.get("start_date")
end_date = self.request.query_params.get("end_date")
emp_id = self.request.query_params.get("emp_id")
employee = Employee.objects.get(pk=emp_id)
payment_by_employee = employee.payment_created_by.all()
if start_date and end_date:
payment_by_employee = payment_by_employee.filter(
created_at__range=[start_date, end_date], mode='cash'
)
payment_by_employee.aggregate(Sum('amount'))
return payment_by_employee
If you want all the records related to specific employee within specific range in CustomerVisit table, you can make use of the related name that is provided to the field(foreign_key) pointing to an employee in customerVisit Table.
For example, if CustomerVisit model has "phelebotomist_id" foreign key that points to Employee Model, you can get all customerVisit records related to Employee Model by below queries
CustomerVisit(models.Model):
phelebotomist_id = models.ForeignKey(Employee, related_name="employee_customer_visit")
emp = Employee.objects.get(pk=<emp_id>)
customer_visits_related_to_emp = emp.employee_customer_visit.all()
You can filter out further depending on the date range and any other fields.

Django ORM like select query in Pony ORM

I'm now to Pony ORM
and I have created my DB models like this:
class RSSSource(db.Entity):
title = Required(str, max_len=100)
link = Required(str, max_len=800)
key = Required(str, max_len=200)
description = Required(str, max_len=800)
is_deleted = Optional(bool, sql_default=False)
rss_content = Set('RSS', reverse='source')
subscriptions = Set("Subscription", reverse='source')
def __str__(self):
return self.title
class RSS(db.Entity):
title = Optional(str, max_len=300)
link = Optional(str, max_len=500)
description = Required(str, max_len=500)
source = Optional("RSSSource", reverse="rss_content")
pub_date = Optional(datetime)
is_deleted = Optional(datetime, sql_default=False)
likes = Set("Like", reverse="rss")
def __str__(self):
return self.title
class User(db.Entity):
first_name = Optional(str, max_len=100)
last_name = Optional(str, max_len=100)
username = Required(str, max_len=200, unique=True)
password = Required(str, max_len=500)
is_deleted = Optional(bool, sql_default=False)
subscriptions = Set("Subscription", reverse="user")
likes = Set("Like", reverse="user")
def __str__(self):
return self.username
class Subscription(db.Entity):
source = Optional("RSSSource", reverse="subscriptions")
user = Optional("User", reverse="subscriptions")
is_deleted = Optional(bool, sql_default=False)
now I want to perform a Django ORM-like select query. something like this:
select user.id
from Subscription where source.key = $key and (is_deleted is null or is_deleted = FALSE)
I couldn't find a way to do this. can anyone help, please?
I finally came up with something like this and it worked.
select user
from Subscription as s
left join RSSSource as rs on rs.id = s.source
where rs.key = $key and (s.is_deleted is null or s.is_deleted = FALSE)

How do I link models together using foreign key with Django?

I am trying to update three models in django with a task function and link them together using a foreign key. Event, Market & Runner
I would like to be able to query the data in my views and display the data.
A single event has multiple markets and in each market there's multiple runners.
I'm getting an error when I try to use foreign keys to link the three models together.
django.db.utils.ProgrammingError: relation "apimb_event" does not exist
STATEMENT: SELECT "apimb_event"."event_id", "apimb_event"."event_name", "apimb_event"."start_time", "apimb_event"."status" FROM "apimb_event" ORDER BY "apimb_event"."event_id" DESC LIMIT 21
Update:
After nuking the db and starting over I have a similar error.
apimb.models.DoesNotExist: Market matching query does not exist.
psycopg2.errors.NotNullViolation: null value in column "event_id"
violates not-null constraint DETAIL: Failing row contains
(1271204194200017, null, null, null, null).
I don't think I'm using foreign key's correctly. Each model has a id as a primary key.
I can update and create this data fine without using foreign keys but,
How can I update the model and then query the data to show as below?
Event Market Runner
event_name_1 market_name_1 runner_name_1
runner_name_2
runner_name_3
event_name_1 market_name_2 runner_name_1
runner_name_2
runner_name_3
runner_name_4
task_function
#shared_task(bind=True)
def get_events(self):
api = get_client()
events = api.market_data.get_events(sport_ids=[9],states=MarketStates.All,
per_page=200, offset=0,
include_event_participants=Boolean.T,
category_ids=None, price_depth=3,
side=Side.All, session=None)
for event in events:
event_name = event["name"]
event_id = event['id']
start_time = event['start']
status = event["status"]
ev, created = Event.objects.update_or_create(event_id=event_id)
ev.event_name = event_name
ev.start_time = start_time
ev.status = status
ev.save()
markets = event["markets"]
for market in markets:
event_id = market['event-id']
market_id = market['id']
market_name = market['name']
status = market['status']
volume = market['volume']
ma, created = Market.objects.update_or_create(market_id=market_id)
ma.market_name = market_name
ma.status = status
ma.volume = volume
ma.save()
runners = market["runners"]
for runner in runners:
runner_name = runner['name']
runner_id = runner['id']
event_id = runner['event-id']
runner, created = Runner.objects.update_or_create(runner_id=runner_id)
runner.event_id = event_id
runner.runner_name = runner_name
runner.save()
models.py
class Event(models.Model):
event_id = models.BigIntegerField(primary_key=True)
event_name = models.CharField(max_length=200, null=True)
start_time = models.DateTimeField(null=True)
status = models.CharField(null=True, max_length=13)
class Market(models.Model):
event = models.ForeignKey(Event, on_delete=models.CASCADE)
market_id = models.BigIntegerField(primary_key=True)
market_name = models.CharField(null=True, max_length=35)
status = models.CharField(null=True, max_length=10)
volume = models.FloatField(null=True, max_length=15)
class Runner(models.Model):
market = models.ForeignKey(Market, null=True, on_delete=models.SET_NULL)
runner_id = models.BigIntegerField(primary_key=True)
event_id = models.BigIntegerField(null=True)
runner_name = models.CharField(max_length=100)

Django, subset of foreign key

I need a way to select a subset of a foreign key, but only limit it to a subset. This is the raw query that was used in the old PHP database;
SELECT a.name FROM character_trait b
LEFT JOIN trait a ON b.id_trait = a.id
WHERE b.id_character = 1
AND a.id_traittype = 10
All the tables, character, trait, traittype and character_trait are available, but I can't figure out how to do it in Djando. My idea was this;
traits = CharacterTrait.objects.filter( id_character = character, id_trait.id_traittype = 10 )
But that just gives an error "keyword can't be an expression". I can do it in a very ugly way and just iterate through the resulting 'traits' using a for loop like this;
traits = CharacterTrait.objects.filter( id_character = character )
for t in traits:
print t.id_trait.id_traittype.id
if t.id_trait.id_traittype.id == 10:
print "Got One"
Edit, the module definitions;
class Trait(models.Model):
id = models.IntegerField(primary_key=True) # AutoField?
id_traittype = models.ForeignKey(Traittype, null=True, db_column = 'id_traittype')
name = models.CharField(max_length=32)
class Meta:
managed = False
db_table = 'trait'
def __unicode__(self):
return self.name
class Traittype(models.Model):
id = models.IntegerField(primary_key=True) # AutoField?
name = models.CharField(max_length=64)
class Meta:
managed = False
db_table = 'traittype'
def __unicode__(self):
return self.name
class Trait(models.Model):
id = models.IntegerField(primary_key=True) # AutoField?
id_traittype = models.ForeignKey(Traittype, null=True, db_column = 'id_traittype')
name = models.CharField(max_length=32)
class Meta:
managed = False
db_table = 'trait'
def __unicode__(self):
return self.name
class CharacterTrait(models.Model):
id = models.IntegerField(primary_key=True) # AutoField?
##id_character = models.IntegerField()
## id_trait = models.IntegerField()
id_character = models.ForeignKey(Werewolfcharacter, null=True, db_column = 'id_character')
id_trait = models.ForeignKey(Trait, null=True, db_column = 'id_trait')
class Meta:
managed = False
db_table = 'character_trait'
def __unicode__(self):
return self.id_trait.name
I was going to suggest you needed to chain the filters, like
traits = CharacterTrait.objects.filter( id_character = character).filter(id_trait__id_traittype = 10 )
But looking back at some code,
traits = CharacterTrait.objects.filter( id_character = character, id_trait__id_traittype = 10 )
Should be sufficient, where the key thing is replacing the . with __ as suggested by dm03514
One simple possibilty, since you (presumably) already have the correct SQL in your PHP code, is simply to use raw SQL queries in Django.
You should read the docs on lookups that span relationships. You need to use the double-underscore syntax:
CharacterTrait.objects.filter(id_character=character, id_trait__id_traittype=10)

Group by in Django?

I have the next structure in my django app:
class Telefono(models.Model):
tipo = models.CharField(max_length=200)
lada = models.IntegerField()
numero = models.CharField(max_length=12)
def __unicode__(self):
return (self.tipo +" - (" +str(self.lada)+")"+str(self.numero))
class Persona(models.Model):
nombre = models.CharField(max_length=200)
apellidoPaterno = models.CharField(max_length=200)
apellidoMaterno = models.CharField(max_length=200)
rfc = models.CharField(max_length=10)
ubicacion = models.OneToOneField(Ubicacion)
telefonos = models.ManyToManyField(Telefono)
The problem is: I need a single "telefono" to show in my datagrid.. so I built the next query in MYSQL:
select p.nombre,tf.numero from persona as p join persona_telefonos AS t ON t.persona_id=p.id join telefono As tf ON t.telefono_id=tf.id group by p.id
And actually gives this result:
"nombre" "numero"
"MiKchorro123213" "5345234523"
But in django I have this query:
Cliente.objects.filter().values("id","nombre","telefonos__numero", "ubicacion__direccion")
And I get two results.. one for each ("telefono") object in the many to many relationship..
How can I do a group by function in django?
Please refer documentation : Raw Query, Filterings, Group_by
example:
query = Cliente.objects.all().query
query.group_by = ['field_name']
results = QuerySet(query=query, model=Model_name)

Categories