How to optimize Django SQL SELECT Query on views.py? - python

These are the models involved in the view :
class Movie(models.Model):
title_original = models.CharField(max_length=300,
db_column='titulooriginal')
title_translated = models.CharField(max_length=300, blank=True,
db_column='titulotraducido')
thumbnail = models.CharField(max_length=300, blank=True,
db_column='imagen')
length = models.CharField(max_length=75, db_column='duracion')
rating = models.CharField(max_length=75, db_column='censura')
genre = models.CharField(max_length=75, db_column='genero')
country_of_origin = models.CharField(max_length=150, db_column='pais')
trailer = models.CharField(max_length=300, blank=True, db_column='trailer')
synopsis = models.CharField(max_length=3600, blank=True,
db_column='sinopsis')
cast = models.CharField(max_length=300, blank=True, db_column='elenco')
director = models.CharField(max_length=150, db_column='director')
slug = models.SlugField(unique=True, blank=True)
tsc = models.DateTimeField(auto_now=False, auto_now_add=True, db_column='tsc', null=True)
tsm = models.DateTimeField(auto_now=True, auto_now_add=True, db_column='tsm', null=True)
class Meta:
db_table = u'peliculas'
def __unicode__(self):
return self.title_original
class ShowTime(models.Model):
LANGUAGE_ESPANOL = 'Espanol'
LANGUAGE_SUBTITLED = 'Subtitulada'
LANGUAGE_CHOICES = (
(LANGUAGE_ESPANOL, LANGUAGE_ESPANOL),
(LANGUAGE_SUBTITLED, LANGUAGE_SUBTITLED))
movie = models.ForeignKey(Movie, db_column='idpelicula')
theater = models.ForeignKey(Theater, db_column='idcine',
null=True)
time = models.TimeField(null=True, db_column='hora')
type_3d = models.NullBooleanField(db_column=u'3d')
type_xd = models.NullBooleanField(null=True, db_column='xd')
type_gtmax = models.NullBooleanField(null=True, db_column='gtmax')
type_vip = models.NullBooleanField(null=True, db_column='vip')
type_imax = models.NullBooleanField(null=True, db_column='imax')
language = models.CharField(max_length=33, blank=True, db_column='idioma',
choices=LANGUAGE_CHOICES,
default=LANGUAGE_ESPANOL)
city = models.ForeignKey(City, db_column='idciudad')
start_date = models.DateField(blank=True, db_column='fecha_inicio')
end_date = models.DateField(blank=True, db_column='fecha_fin')
visible = models.NullBooleanField(null=True, db_column='visible')
tsc = models.DateTimeField(auto_now=False, auto_now_add=True, db_column='tsc', null=True)
tsm = models.DateTimeField(auto_now=True, auto_now_add=True, db_column='tsm', null=True)
class Meta:
db_table = u'funciones'
def __unicode__(self):
return (unicode(self.theater) + " " + unicode(self.movie.title_original) + " " + unicode(self.time))
Additionally this is the view that queries the models:
def list_movies(request, time_period):
city = utils.get_city_from_request(request)
if time_period == 'proximas-dos-horas':
(start_date,
end_date,
hours_start,
hours_end) = utils.get_datetime_filters_from_time_period(time_period)
else:
(start_date,
end_date) = utils.get_datetime_filters_from_time_period(time_period)
if not start_date: # 404 for invalid time periods
raise Http404
movies = Movie.objects.filter(
showtime__city=city.code,
showtime__visible=1,
).order_by('-tsm').distinct()
if time_period == 'proximas-dos-horas':
movies = movies.filter(
showtime__start_date__lte=start_date,
showtime__end_date__gte=end_date,
showtime__time__range=(hours_start, hours_end))
elif time_period == 'proximos-estrenos':
movies = movies.filter(
showtime__start_date=None,
showtime__end_date=None,
)
else:
movies = movies.filter(
showtime__start_date__lte=start_date,
showtime__end_date__gte=end_date)
context = {'movies': movies, 'city': city, 'time_period': time_period}
return render_to_response('list_movies.html', context,
context_instance=RequestContext(request))
Currently this view is consuming a lot of resources in the database and this results in low response time of the web transaction on the browser. I connected the app with New Relic monitoring software to analyze the transactions on app and DB level. This is the trace detail that i got:
I would like to get somo advice on optimizing this view so that the consumption of DB resources drops to the minimum
Thanks a lot!

I don't know the context of your problem, but my 2 advises are:
First, consider some changes in your data model. The ShowTime class have a foreign key to City and a foreign key to Theater and it seems a bit redundant. Personally, I prefer de-normalize addresses, for example:
class Theater(models.Model):
name = models.CharField(max_length=48)
# Location fields.
geo_country = models.CharField(max_length=48)
geo_country_code = models.CharField(max_length=2)
geo_locality = models.CharField(max_length=48)
geo_street = models.CharField(max_length=48, blank=True, default="")
geo_address = models.CharField(max_length=120, blank=True, default="")
class ShowTime(models.Model):
theater = models.ForeignKey(Theater)
This way, you can save a JOIN to the City table and it can be erased from your data model.
Second, read the select_related feature of the Django ORM.
Wish you fun.

Related

Multiple For Loops Django

I have the following two models ASPBoookings and Athlete. The Athlete model is linked to the ASPBookings model by the foreign key named athlete.
I am trying to create a loop that will cycle through all of the bookings in the ASPBooking table and find out which is the most recent booking by each athlete (the table can contain multiple bookings each to the same or different athletes (athlete_id).
Once I have this information (booking_date and athlete_id), I then want to be able to automatically update the "Lastest ASP Session Field" in the Athlete Model.
This is what I have tried so far. I can cycle through the bookings in the ASPBookings table and retrieve and update the "Latest ASP Session Field" using the booking_date and athlete_id, but I cannot do this for multiple different athletes that are within the table. Currently the view just identifies the latest booking and the assigned athlete_id and then updates the field.
Thanks in advance for any help.
Below is the code:
ASPBookings Model
class ASPBookings(models.Model):
asp_booking_ref = models.CharField(max_length=10, default=1)
program_type = models.CharField(max_length=120, default='asp')
booking_date = models.DateField()
booking_time = models.CharField(max_length=10, choices=booking_times)
duration = models.CharField(max_length=10, choices=durations, default='0.5')
street = models.CharField(max_length=120)
suburb = models.CharField(max_length=120)
region = models.CharField(max_length=120, choices=regions, default='Metro')
post_code = models.CharField(max_length=40)
organisation_type = models.CharField(max_length=120,choices=organisation_types, default='Government School')
audience_number = models.CharField(max_length=10)
presentation_form = models.CharField(max_length=120, choices=presentation_form_options, default='Face to Face')
contact_name = models.CharField(max_length=80)
email = models.EmailField()
phone_number = models.CharField(max_length=120)
comments = models.TextField()
status = models.CharField(max_length=80, choices=statuses, default='TBC')
email_sent = models.BooleanField(default=False)
athlete = models.ForeignKey(Athlete, default= '1', on_delete=models.CASCADE)
def __str__(self):
return self.contact_name
# return URL after the POST has been submitted.
def get_absolute_url(self):
return reverse('vistours:success')
Athlete Model
class Athlete(models.Model):
athlete_ref = models.CharField(max_length=10, default=1)
athlete_name = models.CharField(max_length=80)
email = models.EmailField()
phone_number = models.CharField(max_length=120)
home = models.CharField(max_length=120)
education = models.CharField(max_length=120)
sport = models.CharField(max_length=120, choices=sports, default='1500m Runner')
notes = models.TextField(default='None')
gender = models.CharField(max_length=120, choices=genders, default='Not Specified')
para_athlete = models.BooleanField(blank=True)
working_with_children = models.BooleanField(blank=True)
expiry_date = models.DateField(blank=True, null=True)
available = models.BooleanField(blank=True)
available_from = models.DateField(blank=True, null=True)
bfbw = models.BooleanField(blank=True)
latest_bfbw_session = models.DateField(blank=True, null=True)
number_bfbw_sessions = models.CharField(blank=True, null=True, max_length=10)
asp = models.BooleanField(blank=True)
latest_asp_session = models.DateField(blank=True, null=True)
number_asp_sessions = models.CharField(blank=True, null=True, max_length=10)
tours = models.BooleanField(blank=True)
latest_tours_session = models.DateField(blank=True, null=True)
number_tours_sessions = models.CharField(blank=True, null=True, max_length=10)
def __str__(self):
return self.athlete_name
# return URL after the POST has been submitted.
def get_absolute_url(self):
return reverse('home')
View
# Complete first loop for inital values.
for date in asp_data:
if date.booking_date != None:
first_loop = date.booking_date
athl_id = date.athlete_id
break
# If next value is greater than inital value, replace current values.
for date in asp_data:
if date.booking_date != None:
if date.booking_date > first_loop:
first_loop = date.booking_date
athl_id = date.athlete_id
print(first_loop)
print(athl_id)
update_date = Athlete.objects.get(id=athl_id)
update_date.latest_asp_session = first_loop
update_date.save()
No need for loops. You can do this for all athletes in just one go using subqueries to leave all the heavy-lifting to your database:
from django.db.models import F, OuterRef, Subquery
bookings = ASPBookings.objects.filter(
athlete=OuterRef('pk')
).order_by('-booking_date')
Athlete.objects.annotate(
latest_asp_booking_date=Subquery(
bookings.values('booking_date')[:1]
)
).update(
latest_asp_session=F('latest_asp_booking_date')
)

django - Runpython function to turn charfield into foreignkey

I've been strugglin to relate a csv imported data model with a spatial data model based on a CharField.
I've created both models and now im trying to transfer the data from one field to a new one to be the ForeignKey field. I made a Runpython funtion to apply on the migration but it goives the an error:
ValueError: Cannot assign "'921-5'":
"D2015ccccccc.rol_fk" must be a "D_Base_Roles" instance.
Here are the models:
class D_Base_Roles(models.Model):
predio = models.CharField(max_length=254)
dest = models.CharField(max_length=254)
dir = models.CharField(max_length=254)
rol = models.CharField(primary_key=True, max_length=254)
vlr_tot = models.FloatField()
ub_x2 = models.FloatField()
ub_y2 = models.FloatField()
instrum = models.CharField(max_length=254)
codzona = models.CharField(max_length=254)
nomzona = models.CharField(max_length=254)
geom = models.MultiPointField(srid=32719)
def __str__(self):
return str(self.rol)
class Meta():
verbose_name_plural = "Roles"
class D2015ccccccc(models.Model):
id = models.CharField(primary_key=True, max_length=80)
nombre_archivo = models.CharField(max_length=180, blank=True, null=True)
derechos = models.CharField(max_length=120, blank=True, null=True)
dir_calle = models.CharField(max_length=120, blank=True, null=True)
dir_numero = models.CharField(max_length=120, blank=True, null=True)
fecha_certificado = models.CharField(max_length=50, blank=True, null=True)
numero_certificado = models.CharField(max_length=50, blank=True, null=True)
numero_solicitud = models.CharField(max_length=50, blank=True, null=True)
rol_sii = models.CharField(max_length=50, blank=True, null=True)
zona_prc = models.CharField(max_length=120, blank=True, null=True)
##NEW EMPTY FOREIGNKEY FIELD
rol_fk = models.ForeignKey(D_Base_Roles, on_delete=models.CASCADE, blank=True, null=True)
def __str__(self):
return str(self.numero_certificado)
class Meta:
managed = True
#db_table = 'domperm2015cip'
verbose_name_plural = "2015 Certificados Informaciones Previas"
ordering = ['numero_certificado']
The Runpython function:
def pop_rol(apps, schema_editor):
roles = apps.get_model('b_dom_edificacion', 'D2015ccccccc')
for r in roles.objects.all():
rol = roles
r.rol_fk = r.rol_sii
r.save()
D_Base_Roles.rol values are all unique, and 921-5 is one of those values.
What am I missing?
You probably need to assign an object, not a string. Change the line
r.rol_fk = r.rol_sii
to
r.rol_fk = D_Base_Roles.objects.get(rol=r.rol_sii)
Maybe adjust to whatever the correct field for looking up D_Base_Roles instances is.
Note: this will make a database query for every iteration of the for-loop

Django: How to correct created date/time

I've a model Order, that has a field created. It's intention is to show when the order took place (date and time speaking).
I'm using this line to create the field in the model:
current_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
However, the reviewing it from admin panel, it shows It was created in the future: 10:52 pm of 27/12. When the time right now is: 6:11 pm. You can see these details in this screenshot:
How can I make sure the correct time gets recorded in productio env? It'll be hosted using Google Cloud Products.
Right know I'm in development env.
View that creates the Order:
#csrf_exempt
def cart_charge(request):
culqipy.public_key = settings.CULQI_PUBLISHABLE_KEY
culqipy.secret_key = settings.CULQI_SECRET_KEY
amount = request.POST.get('amount')
currency_code = request.POST.get('currency_code')
email = request.POST.get('email')
source_id = request.POST.get('source_id')
last_four = request.POST.get('last_four')
dir_charge = {"amount": int(amount), "currency_code": currency_code,
"email": email,
"source_id": source_id}
print(dir_charge)
charge = culqipy.Charge.create(dir_charge)
transaction_amount = int(charge['amount'])/100 #Necesario dividir entre 100 para obtener el monto real,
#Esto debido a cómo Culqi recibe los datos de los pagos
current_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
shipping_address1 = request.user.profile.shipping_address1
shipping_address2 = request.user.profile.shipping_address2
shipping_department = request.user.profile.shipping_department
shipping_province = request.user.profile.shipping_province
shipping_district = request.user.profile.shipping_district
order = Order.objects.create(
token = charge['id'],
total =transaction_amount,
email= email, #Using email entered in Culqi module, NOT user.email. Could be diff.
last_four = last_four,
created = current_time,
shipping_address1 = shipping_address1,
shipping_address2 = shipping_address2,
shipping_department = shipping_department,
shipping_province = shipping_province,
shipping_district = shipping_district
)
order.save()
return HttpResponse("Hi")
Oder model:
class Order(models.Model):
token = models.CharField(max_length=100, blank=True, null=True)
total = models.DecimalField(max_digits=10, decimal_places=2)
email = models.EmailField(max_length=250, blank = True, verbose_name= 'Correo electrónico')
last_four = models.CharField(max_length=100, blank=True, null=True)
created = models.DateTimeField(auto_now_add=True)
shipping_address1 = models.CharField(max_length=100, blank=True, null=True)
shipping_address2 = models.CharField(max_length=100, blank=True, null=True)
shipping_department = models.CharField(max_length=100, blank=True, null=True)
shipping_province = models.CharField(max_length=100, blank=True, null=True)
shipping_district = models.CharField(max_length=100, blank=True, null=True)
reason = models.CharField(max_length=400, blank=True, null=True, default='')
class Meta:
db_table = 'Order'
ordering = ['-created']
def __str__(self):
return "Order by: " + str(self.id) + " for " + str(self.total)
You don't need to provide current date when creating model object, because you already set option 'auto_now_add=True', which will set date automatically when you create a model object, for example:
order = Order.objects.create(
token = charge['id'],
total =transaction_amount,
email= email, #Using email entered in Culqi module, NOT user.email. Could be diff.
last_four = last_four,
shipping_address1 = shipping_address1,
shipping_address2 = shipping_address2,
shipping_department = shipping_department,
shipping_province = shipping_province,
shipping_district = shipping_district
)
order.save()
print(order.created) # return current time on in server's timezone

Django ForeignKeys not saving

Currently have a problem where I will assign a both Client foreignkey to a Signin and its not saving either reference. Heres the Signin Model
#Sign-ins require just a user
class Signin(models.Model):
employee = models.ForeignKey(Employee)
sign_in_time = models.DateTimeField(null=True)
sign_out_time = models.DateTimeField(null=True)
sign_in_number = models.CharField(max_length=15, default="00000000000")
sign_out_number = models.CharField(max_length=15, default="00000000000")
client_in_obj = models.ForeignKey(Clients, related_name="client_in", null=True)
client_out_obj = models.ForeignKey(Clients, related_name="client_out", null=True)
client_in = models.CharField(max_length=100, default="Unkown")
client_out = models.CharField(max_length=100, null=True)
# Start of Sign in Function
def save(self, *args, **kwargs):
self.client_out_obj.save()
self.client_in_obj.save()
super(Signin, self).save(*args, **kwargs)
def __str__(self):
return self.employee.first_name + " " + self.employee.last_name + " : " + str(self.sign_in_time)+ " to " + str(self.sign_out_time)
Now the employee field IS saving, but the two client_in_obj,and client_out_obj are NOT saving. I will assign them and then when refreshing the page they are not set.
Here is the client Model
class Clients(models.Model):
name = models.CharField(max_length=40, blank=True, null=True)
alt_name = models.CharField(max_length=25, blank=True, null=True)
address1 = models.CharField(max_length=35, blank=True, primary_key=True)
address2 = models.CharField(max_length=35, blank=True, null=True)
rate = models.FloatField(blank=True, null=True)
contact_email = models.CharField(max_length=40, blank=True, null=True)
contact_name = models.CharField(max_length=30, blank=True, null=True)
phone = models.CharField(max_length=40, blank=True, null=True)
billing_name = models.CharField(max_length=30, blank=True, null=True)
billing_email_field = models.CharField(db_column='billing_email_', max_length=12, blank=True, null=True) # Field renamed because it ended with '_'.
def __str__(self):
return self.name + ", " + self.address1
class Meta:
managed = False
db_table = 'clients'
They client_in and client_out fields were my hackey way of trying to get by it for now.
My relations I would like to keep are as followed - An employee will have Many Sign ins, and each Sign in only needs an employee at first, each other field will be filled in over the course of a day.
I found the answer!
So the problem was followed. Im dealing with a legacy database in mySQL, the problem was that when django was assigning the client id it was thinking the primary key was an integer field, so when it tried assigning the key (which was a varchar) it ran into an integer field, so it didn't like it and didn't save. Hopefully that helps anyone who runs into this problem later!

Filtering two models

I have a problem with following thing: using models described below, I need to search for a car, that has more than x km of mileage and latest visit has date of more than year ago. Of course one car can have more than one visit.
class Car(models.Model):
...
id = models.CharField(max_length=10, primary_key=True, db_index=True)
mileage = models.PositiveIntegerField(db_index=True)
class Visit(models.Model):
...
id = models.ForeignKey(Car, db_column='id', db_index=False)
date = models.DateField(db_index=True)
In views.py I have code like this
def search_car(request):
time_threshold = datetime.now() - timedelta(days=365)
cars = Car.objects.filter(mileage__gte=500000,
id=Visit.objects.filter(data__lt=time_threshold.date()))
return render(request, 'myapp/search_car.html', {'cars': cars})
Unfortunately, it doesn't work. Any ideas?
EDIT Exact code:
models.py
class Samochod(models.Model):
marka = models.CharField(max_length=30)
model = models.CharField(max_length=30)
nr_rejestracyjny = models.CharField(max_length=10, primary_key=True, db_index=True)
nr_VIN = models.CharField(max_length=17, unique=True, validators=[validators.MinLengthValidator(17)])
przebieg = models.PositiveIntegerField(db_index=True)
id_uzytkownika = models.ForeignKey(User, db_column='id_uzytkownika', db_index=True)
class Wizyta(models.Model):
id_wizyty = models.IntegerField(primary_key=True, db_index=True)
data = models.DateField(db_index=True)
status = models.CharField(max_length=6, choices=STAN_CHOICE, db_index=True)
id_uzytkownika = models.ForeignKey(User, db_column='id_uzytkownika', db_index=True)
nr_rejestracyjny = models.ForeignKey(Samochod, db_column='nr_rejestracyjny', db_index=False)
przebieg_w_momencie_wizyty = models.PositiveIntegerField()
opis = models.CharField(max_length=200)
id_czesci = models.ForeignKey(Czesci, db_column='id_czesci')
cena = models.PositiveIntegerField()
czas_pracownikow = models.PositiveIntegerField(validators=[validators.MaxValueValidator(1000)])
id_sprzetu = models.ForeignKey(Sprzet, db_column='id_sprzetu', db_index=True)
views.py
def search_car(request):
time_threshold = datetime.now() - timedelta(days=365)
samochody = Samochod.objects.distinct().filter(przebieg__gte=500000).exclude(wizyta__date__gte=time_threshold)
return render(request, 'warsztat_app/search_car.html', {'samochody': samochody})
cars = Car.objects.distinct().filter(mileage__gte=500000) \
.exclude(visit__date__gte=time_threshold)
For your real models code should look like this:
samochody = Samochod.objects.distinct().filter(przebieg__gte=500000) \
.exclude(wizyta__data__gte=time_threshold)

Categories