taggit and haystack+whoosh - django

I have a puzzle, my haystack+whoosh works just fine:) I can search through f.e. name of the content. BUT I want to add "taggit" to my core-model and search through tags then I have NO results:// and I don't know why. More precisely I know that content name "X" has a tag "foo" and when I make search through "foo" I have no result:/
Taggit is a simple tag module for django. Here is the part of my search_indexes.py file:
import datetime
from haystack.indexes import *
from haystack import site
from models import Skill
class SkillIndex(SearchIndex):
text = CharField(document = True, use_template = True)
tags = CharField(model_attr='tags')
site.register(Skill, SkillIndex)
Best regards,
nykon
PS My target is to make live-search like google by use of tags. Does someone has a good idea?

You can add the tags to the data template,
For example:
{{ object.name }}
{% for tag in object.tags.all %}{{ tag.name }} {% endfor %}
Not sure that this is the best solution, but it works.

Related

Django - add link with custom admin page href

In my Django project, I have created a custom admin page for an app via the get_urls() method. I'd like to add a link to the app's main model index view that will take users to this custom page - however, I'm having some trouble creating this link element correctly and I don't seem to be able to piece together the right way to do it - I'm just left with a Reverse for 'export' not found. 'export' is not a valid view function or pattern name. error.
I've set up the admin for the app like so:
# my_project/observations/admin.py
from django.template.response import TemplateResponse
from django.urls import path
class ObservationAdmin(SimpleHistoryAdmin, SoftDeletionModelAdmin):
change_list_template = 'export_link.html'
def get_urls(self):
urls = super().get_urls()
custom_urls = [
path('export/', self.admin_site.admin_view(self.export_view), name='export')
]
return custom_urls + urls
def export_view(self, request):
context = dict(
self.admin_site.each_context(request),
)
return TemplateResponse(request, 'export.html', context)
and the two templates that are referenced:
# my_project/observations/templates/export.html
{% extends "admin/base_site.html" %}
{% block content %}
<div>
Some custom content
</div>
{% endblock %}
# my_project/observations/templates/export_link.html
{% extends 'admin/change_list.html' %}
{% block object-tools-items %}
<li>
Export
</li>
{{ block.super }}
{% endblock %}
Navigating directly to http://localhost:8000/admin/observations/observation/export/ works perfectly, I see the custom content page exactly as I want it... so the issue I'm striking is with the link template - I get the Reverse... error when I navigate to the model index page.
Perhaps the argument I'm passing to url is incorrect, or I need to register that URL elsewhere - but I don't quite know. The other examples of link elements like this that I've been able to find don't reference URLs created via the admin class' get_urls() method - so any guidance on this would be greatly appreciated.
Thanks very much, let me know if there's any other info that I can provide to help sort this out.
I think the problems is in missing namespace in your export_link.html template. Instead of:
Export
try:
Export

Make a change to a string in django template?

I have a queryset in Django that contains a string field. This is a filename, something like images/photo.jpg or images/photo.20.19.22.jpg. I need to rewrite them in one particular view so that ".thumbnail" is inserted before the extension. The previous names should become images/photo.thumbnail.jpg and images/photo.20.19.22.thumbnail.jpg.
What is the best way to do this? This is part of a queryset so it will look like:
{% for record in list %}
{{ record.image }}
{% endfor %}
Now of course I would love to do this outside of my template. However, I don't see a way in which I can do that. After all, this needs to be done for every record inside my queryset. To complicate things, this record does not come directly from a modal. This record is coming from a subquery, so I don't see a way for me to change the modal itself. Should I use templatetags for this? Any other recommendations?
FYI the subquery is something like this:
>>> from django.db.models import OuterRef, Subquery
>>> newest = Comment.objects.filter(post=OuterRef('pk')).order_by('-created_at')
>>> Post.objects.annotate(image=Subquery(newest.values('image')[:1]))
A simple custom template filter could do this.
#register.filter
def add_thumbnail(image):
return image.replace('.jpg', 'thumbnail.jpg')
And in the template:
{% for record in list %}
{{ record.image|add_thumbnail }}
{% endfor %}

Django - MultipleChoiceField is being displayed as a string instead of a list

I have a MultipleChoiceField forms field (associated with a models CharField) which shows up in the database like this. It seems to have been converted to a string in the database, because when I try to display it with a 'for property in property_type' statement in the HTML, it shows up like this. I want it to be displayed like this
So I have to write some code to fix this issue. My pseudocode will look something like:
for record in property_type:
split record at comma
for i in record:
if record[i] is not a letter or number:
remove record[i]
Now my question is, where do I write this code? Do I write it in the views.py or in the HTML file? I tried doing it in views but I don't know how to select a single database record. I tried doing it in the HTML but I was limited by the template tags.
Here is the shortened version of my code:
models.py:
property_type = models.CharField(max_length=50, help_text="You can select more than 1 option")
forms.py:
property_type = forms.MultipleChoiceField(widget=forms.SelectMultiple, choices=BuyerListing.PROPERTY_TYPE)
HTML:
{% for property in listing.property_type %}
<p>Property type: {{ property }}</p>
{% endfor %}
EDIT:
Got it to work thanks to #ytsejam and #Daniel Roseman. With ytsejam's code, the result will show up like this:
['1' '2']
I added a basic regex to ytsejam's code to remove the brackets and quotes:
def split_properties(self):
a = self.property_type
a = re.sub(r'[\]\[\']', '', a)
a = a.split(',')
return a
Now the list will display like this, which is very easy to manipulate in HTML.
1 2
in your models.py
def split_properties(self):
return self.properties.split(',')
and in your template use
{% for property in className.split_properties %} {{ property }} {% endfor %}

Get data from the database into the main django admin page

i want to put some data from the database into the admin index page, so i am trying to add some code to the index.html, but the commands such as Model_name.object.get() don't seem to work there
<ul>{% trans 'Last Update at ' %}
{% for entryupdate in Updatetime.objects.all %}
{{ entryupdate.updatetime }}
{% endfor %}
</ul>
so what shall i use instead? The problem is that there is no variable associated with the object i need. If that would have been any other page i could have added the variable in the views.py, but that's not the case. Thank you!
Those sorts of functions don't work in any template.
You should use a custom template tag to query the data and return it.
Thank to the tip of Daniel i created that tag:
import datetime
from django import template
from Myapp.models import Updatetime
register = template.Library()
def update_time():
ss = Updatetime.objects.get(pk=1)
str11 = ss.updatetime.strftime("%d-%m-%Y %H:%M:%S")
return str11
register.simple_tag(update_time)

Django: converting Youtube URL to HTML embed code

I defined my custom Django filter youtube_embed_url in templatetags/custom_filters.py. It takes an Youtube url and returns the string which is embed code for the video. The code for templatetags/custom_filters.py is below:
from django import template
from django.conf import settings
register = template.Library()
import re
#register.filter(name='youtube_embed_url')
# converts youtube URL into embed HTML
# value is url
def youtube_embed_url(value):
match = re.search(r'^(http|https)\:\/\/www\.youtube\.com\/watch\?v\=(\w*)(\&(.*))?$', value)
if match:
embed_url = 'http://www.youtube.com/embed/%s' %(match.group(2))
res = "<iframe width=\"560\" height=\"315\" src=\"%s\" frameborder=\"0\" allowfullscreen></iframe>" %(embed_url)
return res
return ''
youtube_embed_url.is_safe = True
Then I use this filter in link_page.html page. Here is the relevant portion of link_page.html:
<div>
{{ link.url|youtube_embed_url }}
</div>
However, when I view the link page in browser I see the HTML code as the string:
Any idea how to make the result of youtube_embed_url method to be interpreted as the HTML code, not a string? Thanks in advance, guys!
Good ol' safe filter.
{{ link.url|youtube_embed_url|safe }}
You can also use django-embed-video.
Usage is quite similar:
{% load embed_video_tags %}
{{ link.url|embed:'560x315' }}