Я пытаюсь заставить клиентов искать в моей search.html
базе данных поставщиков услуг, которые относятся только к определенной категории услуг.
Это фрагмент шаблона, обрабатывающего поиск:
<form method = "get" action = "{% url 'search' %}">
<select name = "category" id = "category">
<option value = "">Select a category</option>
{% for category_key, category_name in service_categories %}
<option value = "{{ category_key }}">{{ category_name }}</option>
{% endfor %}
</select>
<button type = "submit">Search</button>
</form>
Это текущая логика в шаблоне поиска views.py
.
def search(request):
# Capture search criteria from request parameters
category = request.GET.get('category')
start_time = request.GET.get('start_time')
end_time = request.GET.get('end_time')
# Initialize search results
search_results = None
if category or (start_time and end_time):
# Filter providers based on category and availability
query = ServiceProvider.objects.all()
if category:
query = query.filter(services__category=category)
if start_time and end_time:
try:
start_time = datetime.strptime(start_time, '%Y-%m-%dT%H:%M:%S')
end_time = datetime.strptime(end_time, '%Y-%m-%dT%H:%M:%S')
query = query.filter(
availabilities__start_time__lte=end_time,
availabilities__end_time__gte=start_time
)
except Exception as e:
print(f"Error processing availability: {e}")
search_results = query.distinct()
# Fetch Popular or Featured Providers (modify based on your logic)
popular_providers = ServiceProvider.objects.filter(is_featured=True)[:3]
service_categories = Service.service_categories
context = {
'search_results': search_results,
'popular_providers': popular_providers,
'service_categories': service_categories
}
return render(request, 'search.html', context)
Это связанные модели для ServiceProvider
и Service
:
class ServiceProvider(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='service_provider')
location = models.CharField(max_length=255)
average_rating = models.FloatField(default=0.0, validators=[MinValueValidator(0.0), MaxValueValidator(5.0)])
name = models.CharField(max_length=255, default='Provider name')
image_url = models.URLField(blank=True) # Optional field for service provider image URL
description = models.TextField(blank=True) # Optional field for service provider description
offers = models.TextField(blank=True) # Field to store offered services (comma-separated or JSON format)
pricing = models.TextField(blank=True) # Field to store pricing information (text or JSON format)
availability_description = models.TextField(blank=True) # Text field for general availability info (e.g., "Weekdays 9am-5pm")
is_featured = models.BooleanField(default=False)
def __str__(self):
return self.user.username
class Service(models.Model):
service_categories = [
('Dance', 'Dance'),
('Music', 'Music'),
('MC', 'Master of Ceremonies'),
# Add more categories as needed
]
name = models.CharField(max_length=255)
provider = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='services')
location = models.CharField(max_length=255, default='')
description = models.TextField()
price = models.DecimalField(max_digits=10, decimal_places=2)
category = models.CharField(max_length=50, choices=service_categories)
def __str__(self):
return f"{self.name} by {self.provider.user.username}"
Итак, ошибка возникла именно из этой строки query = query.filter(category__services=category)
в файле views.py
. Я решил опубликовать полный код функции просмотра для контекста.
Я ожидал, что код вернет список поставщиков услуг определенной категории, например «Танцы», но вместо этого выдал следующую ошибку:
Невозможно преобразовать ключевое слово «услуги» в поле. Возможные варианты: наличие, описание_доступности, средний_рейтинг, описание, идентификатор, URL-адрес_изображения, is_featured, местоположение, имя, предложения, цены, пользователь, идентификатор_пользователя.
У меня такое ощущение, что проблема может быть в чем-то незначительном, но лично мне не удалось ее решить.
PS: Извиняюсь, если предоставил много ненужного кода, я впервые публикую здесь вопрос. Кроме того, если потребуется какое-либо объяснение, я могу его предоставить.
вы привязываете Service
к settings.AUTH_USER_MODEL
с помощью внешнего ключа.
вы привязываете ServiceProvider
к settings.AUTH_USER_MODEL
с помощью внешнего ключа.
Прямо в вашем коде запрос должен выглядеть так:
query = ServiceProvider.objects.filter(user__services__category=category)
извините, я сделал ошибку. у вас есть два прикованных иностранца. Многие ко многим не работает. Я удаляю это из ответа.
Первоначальная ошибка (FieldError) возникает снова, когда я меняю ее на то, что вы отредактировали в своем ответе.
вам не предоставлен код доступа: где доступны поля? Я загружаю код вашей модели в новый проект Django, и ServiceProvider.filter(user__services__category=category) работает!
Я не думал, что фильтр доступности повлияет на первоначальный фильтр по категории услуги. Фильтрация по доступности должна была выполняться после получения услуг от поставщиков. Но вот код модели доступности: class Availability(models.Model): provider = models.ForeignKey(ServiceProvider, on_delete=models.CASCADE, related_name='availabilities') start_time = models.DateTimeField() end_time = models.DateTimeField() def __str__(self): return f"Available from {self.start_time} to {self.end_time} for {self.provider.user.username}"
Аллан, еще раз: я копирую ваш код в новый проект Django, я выполнил миграцию, я применяю фильтр, как я уже сказал, и не получаю никаких ошибок в ServiceProvider.filter(user__services__category=category). Если у вас возникла ошибка, это должна быть другая ошибка, иначе вы не примените мой совет.
Извиняюсь, Максим, я добавил пользовательский бит, но не изменил ссылку на фильтр. При применении предложенного вами изменения я получаю следующую ошибку: type object 'ServiceProvider' has no attribute 'filter'
извините за это: ServiceProvider.objects.filter
Да, это сработало, но я нашел более простой способ фильтрации всей категории. Я решил отфильтровать объекты Service, а затем получить соответствующие объекты ServiceProvider, и это сработало.
Спасибо за ответ. Я внес эти изменения, но получаю эту ошибку:harmoniconnect.CustomUser: (fields.E336) Модель используется в качестве промежуточной модели «harmoniconnect.ServiceProvider.services», но у нее нет внешнего ключа для «ServiceProvider». или «Сервис». harmoniconnect.Service.provider:(fields.E302) Обратный метод доступа «ServiceProvider.services» для «harmoniconnect.Service.provider» конфликтует с именем поля «harmoniconnect.ServiceProvider.services». Я попробовал изменить новое имя поля, но думаю, что это не то имя, которое мне следует менять. Не могли бы вы это уточнить?