Поиск в Django, возвращающий все объекты, не указанные в списке
В настоящее время я пытаюсь добиться поиска, который показывает только те объявления, которые содержат текст в title, description или тегах. Вроде бы все должно работать правильно, но поиск возвращает все объекты.(сайт имеет /?search=foo заканчивающийся после нажатия кнопки)
мой вид списка
class AdListView(ListView):
model = Ad
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
favorites = list()
if self.request.user.is_authenticated:
# rows = [{'id': 2}, {'id': 4} ... ] (A list of rows)
rows = self.request.user.favorite_ads.values('id')
# favorites = [2, 4, ...] using list comprehension
favorites = [ row['id'] for row in rows ]
context['favorites'] = favorites
strval = self.request.GET.get("search", False)
if strval:
# Simple title-only search
# __icontains for case-insensitive search
query = Q(title__icontains=strval)
query.add(Q(text__icontains=strval), Q.OR)
query.add(Q(tags__name__in=[strval]), Q.OR)
objects = Ad.objects.filter(query).select_related().distinct().order_by('-updated_at')[:10]
else :
objects = Ad.objects.all().order_by('-updated_at')[:10]
# Augment the post_list
for obj in objects:
obj.natural_updated = naturaltime(obj.updated_at)
context['search'] = strval
return context
часть моего шаблона:
<div style="float:right">
<!-- https://www.w3schools.com/howto/howto_css_search_button.asp -->
<form>
<input type="text" placeholder="Search.." name="search"
{% if search %} value="{{ search }}" {% endif %}
>
<button type="submit"><i class="fa fa-search"></i></button>
<a href="{% url 'ads:all' %}"><i class="fa fa-undo"></i></a>
</form>
</div>
{% if ad_list %}
<ul>
{% for ad in ad_list %}
<li>
<a href="{% url 'ads:ad_detail' ad.id %}">{{ ad.title }}</a>
{% if ad.owner == user %}
(<a href="{% url 'ads:ad_update' ad.id %}">Edit</a> |
<a href="{% url 'ads:ad_delete' ad.id %}">Delete</a>)
{% endif %}
{% if user.is_authenticated %}
<!-- Two hrefs with two stacked icons each - one showing and one hidden -->
<a href="#" onclick=
"favPost('{% url 'ads:ad_unfavorite' ad.id %}', {{ ad.id }} );return false;"
{% if ad.id not in favorites %} style="display: none;" {% endif %}
id="favorite_star_{{ad.id}}">
<span class="fa-stack" style="vertical-align: middle;">
<i class="fa fa-star fa-stack-1x" style="color: orange;"></i>
<i class="fa fa-star-o fa-stack-1x"></i>
</span>
</a>
forms.py:
# Create the form class.
class CreateForm(forms.ModelForm):
max_upload_limit = 2 * 1024 * 1024
max_upload_limit_text = naturalsize(max_upload_limit)
# Call this 'picture' so it gets copied from the form to the in-memory model
# It will not be the "bytes", it will be the "InMemoryUploadedFile"
# because we need to pull out things like content_type
picture = forms.FileField(required=False, label='File to Upload <= '+max_upload_limit_text)
upload_field_name = 'ad'
# Hint: this will need to be changed for use in the ads application :)
class Meta:
model = Ad
fields = ['title', 'text', 'picture','price', 'tags'] # Picture is manual
# Validate the size of the picture
def clean(self):
cleaned_data = super().clean()
pic = cleaned_data.get('picture')
if pic is None:
return
if len(pic) > self.max_upload_limit:
self.add_error('picture', "File must be < "+self.max_upload_limit_text+" bytes")
# Convert uploaded File object to a picture
def save(self, commit=True):
instance = super(CreateForm, self).save(commit=False)
# We only need to adjust picture if it is a freshly uploaded file
f = instance.picture # Make a copy
if isinstance(f, InMemoryUploadedFile): # Extract data from the form to the model
bytearr = f.read()
instance.content_type = f.content_type
instance.picture = bytearr # Overwrite with the actual image data
if commit:
instance.save()
self.save_m2m()
return instance