Multiple For Loops Django - python

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

Related

Getting unique value on the base of Role

I have model name Movie which have many-to-many Relation with Actor Table. Actor Table is further many-to-many relation with Celebrity-Role.
My question is i need only unique values on the base of roles Like Actors who's role is Director they show in Movie Table field with Director and only directors should be there and so on.
i share my models please have a look.
class CelebrityRole(models.Model):
CELEBRITY_CHOICES = (
('Actor', 'Actor'),
('Producer', 'Producer'),
('Writer', 'Writer'),
('Director', 'Director'),
)
role = models.CharField(max_length=8,
choices=CELEBRITY_CHOICES)
def __str__(self):
return self.role
class Actor(models.Model):
GENDER = (
('Male', 'Male'),
('Female', 'Female'),
)
name = models.CharField(max_length=200)
rank = models.CharField(max_length=5, default=0)
gender = models.CharField(max_length=6, choices=GENDER)
avatar = models.ImageField(upload_to='CelebrityGallery/',
blank=True)
description = models.TextField(blank=True)
birth_place = models.CharField(max_length=200, blank=True)
dob = models.DateField(auto_now=False, auto_now_add=False)
height = models.CharField(max_length=20)
is_married = models.BooleanField(default=False)
movies = models.ManyToManyField(
'movies.Movie', related_name='movies', blank=True)
celebrity_role = models.ManyToManyField(CelebrityRole)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
Here is my Movie Table
class Movie(models.Model):
title = models.CharField(max_length=200)
year = models.CharField(max_length=25, blank=True)
description = models.TextField(blank=True)
released = models.CharField(max_length=25)
runtime = models.CharField(max_length=25)
language = models.CharField(max_length=255)
country = models.CharField(max_length=100)
metascore = models.CharField(max_length=5, blank=True)
imdb_id = models.CharField(max_length=10, blank=False,
unique=True, default='tt3032400')
imdb_rating = models.CharField(max_length=5, blank=True)
imdb_votes = models.CharField(max_length=100, blank=True)
budget = models.CharField(max_length=25)
box_office = models.CharField(max_length=25, blank=True)
imdb_original = models.BooleanField(default=False)
type = models.CharField(max_length=10, blank=True)
season = models.CharField(max_length=2, default=0,
blank=True)
episode = models.CharField(max_length=3, default=0,
blank=True)
poster_url = models.ImageField(upload_to='Posters/',
blank=True)
video_poster_url =
models.ImageField(upload_to='VideoPosters/', blank=True)
video_url = models.TextField(validators=[URLValidator()],
blank=True, max_length=2000)
genre = models.ManyToManyField(Genre,
related_name='genre_movies')
image_gallery = models.ManyToManyField(ImageGallery,
blank=True)
video_gallery = models.ManyToManyField(VideoGallery,
blank=True)
director = models.ManyToManyField(Actor,
related_name='director')
writer = models.ManyToManyField(Actor,
related_name='writer')
actors = models.ManyToManyField(Actor,
related_name='actors')
producer = models.ManyToManyField(Actor,
related_name='producer')
def __str__(self):
return self.title
I'm not sure how you can do it in your models.py. But you can use the filter method in your views.py when making queries to filter actors whose role is director, etc.

Send JsonResponse with related objects

I want to send JsonResponse with related objects. Here's my playground.
I do it as
def get_stocks(qty=9):
return Stock.objects.values()[:9]
# Returning stocks
stocks = api_services.get_stocks()
return JsonResponse(list(stocks), safe=False)
My models are like
class Sector(models.Model):
name = models.CharField(max_length=200, null=True, blank=True)
original_name = models.CharField(max_length=200)
slug = models.CharField(max_length=200)
class Industry(models.Model):
name = models.CharField(max_length=200, null=True, blank=True)
original_name = models.CharField(max_length=200)
slug = models.CharField(max_length=200)
class Stock(models.Model):
name = models.CharField(max_length=200)
ticker = models.CharField(max_length=200, unique=True)
logo = models.CharField(max_length=200, null=True, blank=True)
website = models.CharField(max_length=200, null=True, blank=True)
sector = models.ForeignKey(Sector, on_delete=models.CASCADE, null=True)
industry = models.ForeignKey(Industry, on_delete=models.CASCADE, null=True)
How can I get my json with related objects? Now I get
0 Object { id: 1, name: "Tesla", ticker: "TSLA", … }
id 1
name "Tesla"
ticker "TSLA"
logo null
website "http://www.tesla.com"
sector_id 1
industry_id 1
I need to get sector and industry as well
You'll need to look up the model entry for the given ID in the Stock model. You can do that in your get_stocks method. Another option would be using a Stock serializer.
For example:
def get_stocks(qty=9):
stocks = Stock.objects.all()[:qty]
for stock in stocks:
try:
stock.sector = Sector.objects.get(id=stock.sector)
except Sector.DoesNotExist:
pass
try:
stock.industry = Industry.objects.get(id=stock.industry)
except Industry.DoesNotExist:
pass
return stocks

Save a many to many object inside a django model?

I am still learning to use Django and so I am a bit unclear on something.
I have a product model and category model. A product can lie in multiple categories and multiple categories can have the same product.
So, its a many to many relationship. Now, I want to allow the user to select multiple categories from the html and then I want to save the categories and link them to the category object in my product model. I am completely lost about it.
One way would be to use Modelform but I dont want to go that way. Is there any other way I can accomplish this?
models.py:
class Category(models.Model):
name = models.CharField(max_length=50)
slug = models.SlugField(max_length=50, unique=True,
help_text='Unique value for product page URL, created from name.')
description = models.TextField()
is_active = models.BooleanField(default=True)
meta_keywords = models.CharField("Meta Keywords", max_length=255,
help_text='Comma-delimited set of SEO keywords for meta tag')
meta_description = models.CharField("Meta Description", max_length=255,
help_text='Content for description meta tag')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('catalog:categories', kwargs={'category_slug': self.slug})
class Meta:
ordering = ['-created_at']
verbose_name_plural = 'Categories'
class Product(models.Model):
name = models.CharField(max_length=255, unique=True)
slug = models.SlugField(max_length=255, unique=True,
help_text='Unique value for product page URL, created from name.')
brand = models.CharField(max_length=50)
sku = models.CharField(max_length=50)
price = models.DecimalField(max_digits=9, decimal_places=2)
old_price = models.DecimalField(max_digits=9, decimal_places=2, blank=True, default=0.00)
thumbnail = models.FileField(upload_to='static/images/products/thumbnails')
imageurls = models.CharField(max_length=1000)
is_active = models.BooleanField(default=True)
is_bestseller = models.BooleanField(default=False)
is_featured = models.BooleanField(default=False)
quantity = models.IntegerField()
description = models.TextField()
meta_keywords = models.CharField(max_length=255, help_text='Comma-delimited set of SEO keywords for meta tag')
meta_description = models.CharField(max_length=255, help_text='Content for description meta tag')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
categories = models.ManyToManyField(Category)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('catalog:products', kwargs={'product_slug': self.slug})
def sale_price(self):
if self.old_price > self.price:
return self.price
else:
return None
class Meta:
ordering = ['-created_at']
part of views.py:
if request.method =='POST':
print ('entered')
name = request.POST['name']
brand = request.POST['brand']
sku = request.POST['sku']
price = request.POST['price']
quantity = request.POST['quantity']
description = request.POST['description']
imageurls = request.POST['urls']
print('imageurls',imageurls)
categorylist = request.POST['categories']
print('categorylist',categorylist)
categories = re.findall(r"[\w']+", categorylist)
print categories
imageurls = imageurls.split('~')
print('iageurls',imageurls)
for x in categories:
categoryobj = Category.objects.filter(name=x).values()
print ('categoryobj',categoryobj)
# Product.objects.create(name=name,sku=sku,brand=brand,price=price,quantity=quantity,description=description,imageurls=imageurls,categories=categoryobj)
return HttpResponse('success')
Try to save the above way gives me error.
product=Product.objects.create(name=name,sku=sku,brand=brand,price=price,quantity=quantity,description=description,imageurls=imageurls)
category_queryset = []
for x in categories:
category = Category.objects.filter(name=x).first()
category_queryset.append(category)
product.categories.set(category_queryset)

Optimizing queries in Django, prefact_related for objects that are reversely linked

In my django project I have 3 models, simplified for this example: Contact, WorkRelation and Group objects.
Contact
class Contact(BaseModel):
title = models.CharField(max_length=30, blank=True)
initials = models.CharField(max_length=10, blank=True)
first_name = models.CharField(max_length=30, blank=True)
prefix = models.CharField(max_length=20, blank=True)
surname = models.CharField(max_length=30)
def get_workrelations(self):
workrelations = apps.get_model('groups', 'WorkRelation')
return workrelations.objects.filter(contact=self)
def get_organisations(self):
output = ""
strings = []
wr = self.get_workrelations()
for relation in wr:
group = relation.group
name = group.name
strings.append(s)
if len(strings) > 0:
output = ", ".join(strings)
return output
WorkRelation
class WorkRelation(BaseModel):
contact = models.ForeignKey(Contact, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
function = models.CharField(max_length=40, blank=True)
email_address = models.EmailField()
phone_number = models.CharField(max_length=13, blank=True)
description = models.TextField(max_length=400, blank=True)
Group
class Group(BaseModel):
group_type = models.ForeignKey(GroupType, on_delete=models.CASCADE)
name = models.CharField(max_length=60, unique=True)
street_name = models.CharField(max_length=40, blank=True)
house_number = models.CharField(max_length=10, blank=True)
The problem with this setup is that it becomes extremely slow when I want to call get_organisations() on a large contact set. For example: when trying to list all my contacts (600 for my demo set), and call get_organisations(), about 1250 queries are needed.
I found that you can prevent this by using prefetch_data(), but somehow I can't get this working in my setup. I tried to replace my query for
queryset = Contact.objects.prefetch_related('workrelation_set')
But this didn't speed it up (against my presumption). Do you guys know if it is even possible to speed this up?
Change your get_organisations code to this:
def get_organisations(self):
return ', '.join(
workrelation.group.name for workrelation
in self.workrelation_set.all()
)
And use this query for fetching Contact objects:
Contact.objects.prefetch_related('workrelation_set__group')
This will return the result with a single query.

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

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.

Categories