Stored Procedure result to Django Model - django

If have a model like:
class Person(models.Model):
id = models.IntegerField()
first_name = models.CharField(max_length=50)
last_name = models.IntegerField()
birthday = models.DateField()
address = models.CharField(max_length=250)
phone = models.TimeField()
To create Person class objects I get data from a stored procedure, like:
cursor = connection.cursor()
cursor.callproc('sp_get_person_by_id', {id:1234})
results = cursor.fetchall()
[Person(*row) for row in results]
But "sp_get_person_by_id" returns more fields than the Person class attributes. Therefore "shit happens", error happens because there is fields that don't have attributes to map.
It's possible to just map this attributes? How can I do that?
Thx in advance.
Cheers.

If you know the order of the attributes you're getting back from the stored procedure you can pass them to the Model like this:
cursor = connection.cursor()
cursor.callproc('sp_get_person_by_id', {id:1234})
results = cursor.fetchall()
result_list = []
from row in results:
p = self.model(id=row[0], fist_name=row[1], last_name=row[2], birthday=row[3])
result_list.append(p)
return result_list

Related

Filtering elements from Django database on two conditions

I want to select elements from my Django database on two conditions - whether the boolean value "used" is true and whether or not the "dateUsed" is within the last 20 days. However, my current filter statement is returning an empty QuerySet, even though there should be elements that meet both conditions. Am I filtering the elements correctly? I've attached the code that filters the elements, the definitions of my models, as well as the block of code that changes the value of "used" once the model elements have been displayed on my site.
Filter:
def pastSongs(request):
window = datetime.now().date() - timedelta(days=20)
songHistory = Song.objects.filter(used = True).filter(dateUsed__gt = window)
ent = {}
ent["ent"] = songHistory
return render(request, 'rollingStone/songs.html',ent)
Models:
class Song(models.Model):
rank = models.IntegerField()
artist = models.CharField(max_length=100)
title = models.CharField(max_length=100)
cover = models.URLField()
writers = models.CharField(max_length=100)
producers = models.CharField(max_length=100)
releaseInfo = models.CharField(max_length=100)
description = models.TextField(max_length=3000)
used = models.BooleanField(default=False)
dateUsed = models.DateField(auto_now=True)
Changing "used" field:
def reload():
# Change status of old song/album to used, and save the date that it was used
if entry["status"] == "filled":
currentSong = Songs.objects.get(entry["songEnt"].name)
currentAlbum = Albums.objects.get(entry["albumEnt"].name)
currentSong.dateUsed = datetime.now().date() - timedelta(days=1)
currentAlbum.dateUsed = datetime.now().date() - timedelta(days=1)
currentSong.used = True
currentAlbum.used = True
currentSong.save()
currentAlbum.save()
Your problem might be that you are doing something weird with the window date...
Other than that you could write a manager for your model:
managers.py:
from django.db.models import QuerySet, Q
SongQuerySet(QuerySet):
def used_and_in_time_window(time_window):
return self.filter(Q(used=True) & Q(dateUsed__gte=time_window))
models.py :
class Song(models.Model):
rank = models.IntegerField()
artist = models.CharField(max_length=100)
title = models.CharField(max_length=100)
cover = models.URLField()
writers = models.CharField(max_length=100)
producers = models.CharField(max_length=100)
releaseInfo = models.CharField(max_length=100)
description = models.TextField(max_length=3000)
used = models.BooleanField(default=False)
dateUsed = models.DateField(auto_now=True)
objects = SongQuerySet.as_manager()
usage:
def pastSongs(request):
time_window = datetime.date(datetime.now()) - timedelta(days=20)
songHistory = Song.objects.used_and_in_time_window(time_window)
ent = {}
ent["ent"] = songHistory
return render(request, 'rollingStone/songs.html',ent)
Also you might wanna pack the time delta value to an environment variable so you don't have to make a commit if you wanna change that in the future.

How to get second last record in a queryset in Django?

I have a model named employees_salary and I need to get second highest salary of employee.
I know that I can filter latest(), first(), last()** and these are working, but how to filter second last? Am I missing something?
Use order_by with a reverse filter (-) and then grab the second object by using [1].
class Salaries(models.Model):
employee_name = models.CharField(max_length=255)
salary = models.IntegerField()
q = Salaries.objects.all().order_by('-salary')
second_highest_paid_name = q[1].employee_name
This way will also work
class EmployeeSalary(models.Model):
employee_name = models.CharField(max_length=255)
salary = models.IntegerField()
#code for view
q = EmployeeSalary.objects.all().order_by('-salary')[1:1]
second_paid_name = q[0].employee_name
second_paid_salary = q[0].salary
This will also work, if you try it like this:
models.py:
class Post(models.Model):
title = models.CharField()
body = models.TextField()
pub_date = models.DateTimeField(auto_now_add=True)
views.py:
def postlist(request):
latest_post = Post.objects.order_by('-pub_date')[0]
secondlast_post = Post.objects.order_by('-pub_date')[1]
context = {
'latest_post' : latest_post, 'secondlast_post' : secondlast_post ,
}
return render(request, 'yourtemplate.html', context)

Making table report from non-related GeoDjango models

I have this 2 models:
class BuildingStructure(models.Model):
bldg_name = models.CharField(max_length=100)
height = models.FloatField()
code = models.CharField(max_length=25)
block_name = models.CharField(max_length=75)
bldg_type = models.CharField(max_length=50)
brgy_locat = models.CharField(max_length=50)
geom = models.MultiPointField(srid=32651, null=True, blank=True)
objects = models.GeoManager()
def __unicode__(self):
return self.bldg_name
class FloodHazard(models.Model):
gridcode = models.IntegerField()
hazard = models.CharField(max_length=6)
date_field = models.CharField(max_length=50)
geom = models.MultiPolygonField(srid=32651, null=True, blank=True)
objects = models.GeoManager()
def __unicode__(self):
return self.hazard
hazard field in the model has the following values: 'High', 'Medium', 'Low'.
I wanted to create a report in a table format(HTML) like this:
I tried this so far:
getgeom = FloodHazard.objects.get(id=512).geom
getgeom_medium = FloodHazard.objects.get(id=620).geom
getgeom_low = FloodHazard.objects.get(id=638).geom
response_data = {}
response_data["medium"] = list(BuildingStructure.objects.filter(geom__intersects=getgeom_medium).values( 'brgy_locat').annotate(countmedium=Count('brgy_locat')))
response_data["high"] = list(BuildingStructure.objects.filter(geom__intersects=getgeom).values('brgy_locat').annotate( counthigh=Count('brgy_locat')))
response_data["low"] = list(BuildingStructure.objects.filter(geom__intersects=getgeom_low).values('brgy_locat').annotate( countlow=Count('brgy_locat')))
result = {}
for category in response_data.values():
for element in category:
key = element.pop('brgy_locat')
if key not in result:
result[key] = {"loc":key}
result[key].update(element)
json_result = result.values()
return HttpResponse(list(json.dumps(json_result)), content_type='application/json')
The above code works fine as I am able to get my intended output. But as you examine it, I tried one id in each hazard type. So my problem now is to use filter to get all the ids and used it as reference in my GeoQuerySet. Any help will be appreciated. I'm trying to pass the data as JSON in my template because I'm using datatables.
This is how I get all the ids for e.g. hazard type "high"
reference = FloodHazard.objects.filter(hazard='High')
ids = reference.values_list('id', flat=True)
for id in ids:
#something has to be done here...

Django how to order_by temporary field, dynamic create field

think about these:
here is a function,
def calculate(model):
model.tempfield = 1
and this function will save a temp field in this model
and you can use model.tempfield in everywhere
but if it's a queryset,after an order_by these temp filed will lost
how to order_by these temp field in queryset?
i have 2 model:
Class A(models.Model):
name = models.CharField(maxlength=100)
Class Log_Of_A(models.Model):
clicks = models.IntegerField()
a = models.ForeignKey(A)
date = models.DateField(db_index=True)
and calculate the Log of A by date
def createlog(request):
start = request.GET.get("start")
end = request.GET.get("end")
all_A = A.objects.all()
for a in all_A:
logs=Log_Of_A.objects.filter(a=a,date__gt=start,date__lt=end)
statistics = logs.aggregate(Sum("clicks"))
a.clicks = statistics["clicks__sum"]
all_A.order_by("clicks")
return all_A
how to order_by temporary field
Try this:
import operator
def createlog(request):
start = request.GET.get("start")
end = request.GET.get("end")
all_A = A.objects.all()
for a in all_A:
logs=Log_Of_A.objects.filter(a=a,date__gt=start,date__lt=end)
statistics = logs.aggregate(Sum("clicks"))
a.clicks = statistics["clicks__sum"]
sorted = sorted(all_A, key=operator.attrgetter('clicks'), reverse=True)
return sorted

Filtering query with a foreign key

I have the following Models:
class Categories(models.Model):
name = models.CharField(max_length=200, unique=True)
class Funnies(models.Model):
title = models.CharField(max_length=200)
category = models.ForeignKey(Categories)
In a case where I have a variable holding a category name (myVar), instead of getting all rows in Funnies that hold a reference to the category the long way:
category_id = Categories.objects.get(name = myVar)
funnies_list = Funnies.objects.filter(category = category_id)
Is there a shorter, more "django" way of getting funnies_list ?
Meir
well if you have myVar already then
funnies_list = Funnies.objects.filter(category__name=myVar)
would work.