Привет всем У меня проблема с сортировкой наборов запросов в Django
Итак, я изучаю Django и пытаюсь сделать сайт, похожий на AirBNB. У меня есть модель под названием lisitngs, в которой широта и долгота хранятся в CharField. Моя модель выглядит следующим образом:
class Listing(models.Model):
class BathRoomType(models.TextChoices):
ATTACHED = 'Attached Bathroom'
COMMON = 'Shared Bathroom'
class RoomVentType(models.TextChoices):
AC = 'Air Conditioner'
NO_AC = 'No Air Conditioner'
class LisitngType(models.TextChoices):
ROOM = 'Room'
APARTEMENT = 'Apartement'
HOUSE = 'Full House'
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=255)
city = models.ForeignKey(RoomLocation, on_delete=models.CASCADE)
exact_address = models.CharField(max_length=255)
lat = models.CharField(max_length=300, blank=False, null=False, default="0")
lng = models.CharField(max_length=300, blank=False, null=False, default="0")
description = models.TextField()
price = models.IntegerField()
listing_type = models.CharField(max_length=20, choices=LisitngType.choices, default=LisitngType.ROOM)
kitchen_available = models.BooleanField(default=False)
kitchen_description = models.TextField(null=True, blank=True)
bedrooms = models.IntegerField()
max_acomodation = models.IntegerField()
bathroom_type = models.CharField(max_length=20, choices=BathRoomType.choices, default=BathRoomType.ATTACHED)
no_bathrooms = models.IntegerField()
room_type = models.CharField(max_length=30, choices=RoomVentType.choices, default=RoomVentType.AC)
main_photo = models.ImageField(upload_to='room_images', default='default_room.jpg')
photo_1 = models.ImageField(upload_to='room_images', default='default_room.jpg')
photo_2 = models.ImageField(upload_to='room_images', default='default_room.jpg')
photo_3 = models.ImageField(upload_to='room_images', default='default_room.jpg')
is_published = models.BooleanField(default=False)
date_created = models.DateTimeField(default=timezone.now, editable=False)
slug = AutoSlugField(populate_from=['title', 'listing_type', 'bathroom_type', 'room_type'])
rating = models.IntegerField(default=5)
approved = models.BooleanField(default=False)
total_bookings = models.IntegerField(default=0)
def __str__(self):
return self.title
На моей домашней странице я хочу показать объявления, которые находятся рядом со мной. Для этого у меня есть функция near_places. Эта функция near_place берет широту и долготу после запроса через модель Listing и возвращает расстояние между объявлением и текущим пользователем, заходящим на домашнюю страницу:
import geocoder
from haversine import haversine
def near_places(dest_lat, dest_lng):
g = geocoder.ip('me')
origin = tuple(g.latlng)
destination = (dest_lat, dest_lng)
distance = haversine(origin, destination)
return distance
Моя функция домашней страницы в файле views.py выглядит следующим образом:
def home(request):
objects = Listing.objects.filter(is_published=True, approved=True)
for object in objects:
lat, lng = float(object.lat), float(object.lng)
object.distance = near_places(lat, lng)
return render(request, 'listings/home.html')
Как вы можете видеть, я просмотрел набор запросов и для каждых данных вычислил расстояние и добавил в набор запросов как расстояние. Теперь я хотел бы получить только 10 элементов с наименьшим расстоянием. Как я могу это сделать.
Я пытался использовать object = objects.order_by('-distance')[:10], но он выдает ошибку as
FieldError at /
Cannot resolve keyword 'distance' into field. Choices are: The_room_booked, approved, bathroom_type, bedrooms, city, city_id, date_created, description, exact_address, id, is_published, kitchen_available, kitchen_description, lat, listing_type, lng, main_photo, max_acomodation, no_bathrooms, photo_1, photo_2, photo_3, price, rating, reviewsandrating, room_type, slug, title, total_bookings, user, user_id
Есть ли способ решить эту проблему? Также требуется довольно много времени для вычисления текущего расстояния с помощью функции near_places(), как описано выше. Любые предложения будут полезны. Спасибо
Вы не можете этого сделать, потому что в вашей модели нет поля distance и такого столбца в БД тоже нет.
Что вы можете сделать, это либо
добавьте такое поле в вашу модель - я не рекомендую с вашей текущей логикой, так как вы будете перебирать каждый экземпляр и посылать sql запрос для обновления каждой строки.
.Получите ваш queryest, преобразуйте его в список dicts и затем выполните итерацию по списку dicts с помощью вашей функции, добавляющей к нему ключ
distance. Затем вы можете отсортировать список с помощью функции python sort и передать его в шаблон.
Нравится:
objects = Listing.objects.filter(is_published=True, approved=True).values('lat', 'lng') # add fields that you need
for obj in objects:
obj['distance'] = near_places(obj['lat'], obj['lng'])
my_sorted_list = sorted(objects, key=lambda k: k['distance'])
Передайте my_sorted_list в ваш шаблон. Вы можете добавить аргумент reverse=True к функции sorted, если вам нужно другое направление сортировки.