django-haystack 2.0.0beta facet example - not showing facet counts - django

I've been working through the documentation for Haystack 2.0.0beta, and using solr3.6.0 as my backend. I have gotten through the getting started example. Working with the facet example now.
search_indexes.py
import datetime
from haystack import indexes
from bsmain.models import Note
class NoteIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
author = indexes.CharField(model_attr='user', faceted=True)
pub_date = indexes.DateTimeField(model_attr='pub_date')
def get_model(self):
return Note
def index_queryset(self):
"""Used when the entire index for model is updated."""
return self.get_model().objects.filter(pub_date__lte=datetime.datetime.now())
urls.py
from django.conf.urls.defaults import *
from django.conf import settings
from django.conf.urls.defaults import *
from haystack.forms import FacetedSearchForm
from haystack.query import SearchQuerySet
from haystack.views import FacetedSearchView
sqs = SearchQuerySet().facet('author')
urlpatterns = patterns('haystack.views',
url(r'^$', FacetedSearchView(form_class=FacetedSearchForm,searchqueryset=sqs),
name='haystack_search'),
)
I have tested in python shell and get facets and counts, but when I fire the /search url (with the html provided in the example for facets) I get the form but no facets or counts.
Can anyone see anything wrong in the code above or is there somehing else I am missing?
Thanks.

Did you rebuild the index (./manage.py rebuild_index)?
Once done then create the schema.xml (./manage.py build_solr_scema > schema.xml)
Then copy the shcema.xml to your solr conf directory and restart the solr.
That should solve your problem.

Related

Django url path converter not working in production

I'm using path converter in my django app like so:
# urls.py
from . import views
from django.urls import path
urlpatterns = [
path('articles/<str:collection>', views.ArticleView),
]
# views.py
#login_required
def ArticleView(request, collection):
print(collection)
if collection == "None":
articles_query = ArticleModel.objects.all()
...
This works fine in development for a url suck as : http://localhost:8000/articles/My Collection which gets encoded to http://localhost:8000/articles/My%20Collection, and is decoded properly in the ArticleView. However, in development, I have to edit the view like so to get it to work:
# views.py
import urllib.parse
#login_required
def ArticleView(request, collection):
collection = urllib.parse.unquote(collection)
print(collection)
if collection == "None":
articles_query = ArticleModel.objects.all()
...
Otherwise, the print(collection) shows My%20Collection and the whole logic in the rest of the view fails.
requirements.txt
asgiref==3.2.10
Django==3.1.1
django-crispy-forms==1.9.2
django-floppyforms==1.9.0
django-widget-tweaks==1.4.8
lxml==4.5.2
Pillow==7.2.0
python-pptx==0.6.18
pytz==2020.1
sqlparse==0.3.1
XlsxWriter==1.3.3
pymysql
What am I doing wrong here?
Thanks in advance!
The URL is being urlencoded which encodes spaces as %20. There are a number of other encodings. As you've discovered you need to decode that parameter in order to compare it to what you'd expect. As you've likely realized, if you have a value that actually wants The%20News and not The News, you have no recourse. To handle this people will create a slug field. Django has a model field for this in the framework.
This is typically a URL-friendly, unique value for the record.
Assuming you add a slug = models.SlugField() to ArticleModel, your urls and view can change into:
urlpatterns = [
# Define a path without a slug to identify the show all code path and avoid the None sentinel value.
path('articles', views.ArticleView, name='article-list'),
path('articles/<slug:slug>' views.ArticleView, name='article-slug-list'),
]
#login_required
def ArticleView(request, slug=None):
articles_query = ArticleModel.objects.all()
if slug:
articles_query = articles_query.filter(slug=slug)

django how to display a weeks data

Hi thanks for helping me
I being doing some browsing on google and stack overflow, but documentation django and python I can hardly understand, how the they make code run
I just can't figure out a way to display week data (table & chart) with
two toggle button to toggle different weeks of 53 weeks in a year
I had try using the week in Django template tags; https://docs.djangoproject.com/en/2.1/ref/templates/builtins/#date
but I get empty value instead; here example I did {{ value|date:"W" }}
is there easily way to do this? I do not wish to use the weekarchiveview:
https://docs.djangoproject.com/en/2.1/ref/class-based-views/generic-date-based/#weekarchiveview
As I need to toggle between years,months and weeks on same page.
Below are my codes
this my code for views
from django.shortcuts import render
from django.views.generic import ListView, DetailView ,TemplateView
from zigview.models import tank_system
from django.utils import timezone
from datetime import date, timedelta
class EC(ListView):
model = tank_system
template_name = 'FrounterWeb/extends/EC.html'
ordering = ['-datetime'] # sort dates in descending order
def get_context_data(self, **kwargs):
return {'tank': self.get_queryset()}
This is my apps url codes
from django.urls import path
from . import views #function views
from django.views.generic.base import TemplateView
from django.contrib.auth.decorators import login_required, permission_required
urlpatterns = [
path('',login_required(views.index.as_view()), name='index'), # views to call our index
path(r'', TemplateView.as_view(template_name='index.html'), name = 'myapp'), # tell django the which path to our main page
path(r'liveSterm/', login_required(views.Strem), name='Livesterm'), #call live strem page
path(r'EC-data/', login_required(views.EC.as_view()), name='EC'),
path(r'ph-data/', login_required(views.ph.as_view()), name='ph'),
path(r'Water-Temptures/', login_required(views.WT.as_view()), name='WT'),
path(r'Room-Temptures/', login_required(views.RT.as_view()), name= 'RT'),
path(r'Water-Flow-IN/', login_required(views.WaterFlowIN.as_view()), name= 'WFI'),
path(r'Water-Flow-OUT/', login_required(views.WaterFlowOUT.as_view()), name= 'WFO'),
]
this is my models codes
from django.db import models
from django.utils import timezone
from decimal import Decimal
# having errors KeyError: "'__name__' not in globals"
class tank_system(models.Model):
PH = models.DecimalField(max_digits=3, decimal_places=1)
EC = models.DecimalField(max_digits=3, decimal_places=1)
Winlet = models.DecimalField(max_digits=3, decimal_places=1)
Woutlet = models.DecimalField(max_digits=3, decimal_places=1)
WaterLevel = models.IntegerField(default=500)
TempWater = models.IntegerField(default=25)
TempRoom = models.IntegerField(default=25)
tanks = models.IntegerField(default=1)
datetime = models.DateTimeField(default=timezone.now())
You don't have 'value' in your context. The context is only 'tank'. So to get the datetime you can use {{ tank.datetime|date:"W" }}
To switch after clicking on a button you can write a simple piece of javascript that changes the inner html of a certain part of your DOM to {{ tank.datetime|date:"W" }} , {{ tank.datetime|date:"M" }} etc. after clicking the button

Embedding Video File in Django Site

I have a Django site that I'm creating, and I want some of the pages to have videos embedded in them. These videos aren't part of a model. I just want to be able to use the view to figure out which video file to play, and then pass the file path into the template. All the files are hosted locally (for now, at least).
Is it possible to do with Django? And if so, how do I do it?
There are two ways you can do this -
Method 1: Pass parameter in URL and display video based on that parameter -
If you don't want to use models at any cost, use this, else try method 2.
Assuming you have saved all videos in your media directory and they all have unique names (serving as their ids).
your_app/urls.py -
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^video/(?P<vid>\w+)/$',views.display_video)
# \w will allow alphanumeric characters or string
]
Add this in the project's settings.py -
#Change this as per your liking
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
your_app/views.py -
from django.conf import settings
from django.shortcuts import render
from django.http import HttpResponse
import os
import fnmatch
def display_video(request,vid=None):
if vid is None:
return HttpResponse("No Video")
#Finding the name of video file with extension, use this if you have different extension of the videos
video_name = ""
for fname in os.listdir(settings.MEDIA_ROOT):
if fnmatch.fnmatch(fname, vid+".*"): #using pattern to find the video file with given id and any extension
video_name = fname
break
'''
If you have all the videos of same extension e.g. mp4, then instead of above code, you can just use -
video_name = vid+".mp4"
'''
#getting full url -
video_url = settings.MEDIA_URL+video_name
return render(request, "video_template.html", {"url":video_url})
Then in your template file, video_template.html, display video as -
<video width="400" controls>
<source src="{{url}}" type="video/mp4">
Your browser does not support HTML5 video.
</video>
Note: There can be performance issue, iterating through all the files in the folder using os.listdir(). Instead, if possible, use a common file extension or use the next method (strongly recommended).
Method 2 : Storing video ids and correspondig file names in database -
Use same settings.py, urls.py and video_template.html as in method 1.
your_app/models.py -
from django.db import models
class videos(models.Model):
video_id = models.CharField(blank=False, max_length=32)
file_name = models.CharField(blank=False, max_length=500)
def __str__(self):
return self.id
your_app/views.py -
from django.conf import settings
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse
from .models import videos
def display_video(request,vid=None):
if vid is None:
return HttpResponse("No Video")
try:
video_object = get_object_or_404(videos, pk = vid)
except videos.DoesNotExist:
return HttpResponse("Id doesn't exists.")
file_name = video_object.file_name
#getting full url -
video_url = settings.MEDIA_URL+file_name
return render(request, "video_template.html", {"url":video_url})
So if you want to access any page with video id 97veqne0, just goto - localhost:8000/video/97veqne0

Django admin upload and image to s3 and then resize the image and save a thumb problem

I am having error after error trying to upload and resize images to s3 with pil and botos3 and the django default_storage. I am trying to do this on save in the admin.
here is the code:
from django.db import models
from django.forms import CheckboxSelectMultiple
import tempfile
from django.conf import settings
from django.core.files.base import ContentFile
from django.core.files.storage import default_storage as s3_storage
from django.core.cache import cache
from datetime import datetime
import Image, os
import PIL.Image as PIL
import re, os, sys, urlparse
class screenshot(models.Model):
title = models.CharField(max_length=200)
slug = models.SlugField(max_length=200)
image = models.ImageField(upload_to='screenshots')
thumbnail = models.ImageField(upload_to='screenshots-thumbs', blank=True, null=True, editable=False)
def save(self):
super(screenshot, self).save() # Call the "real" save() method
if self.image:
thumb = Image.open(self.image.path)
thumb.thumbnail(100, 100)
filename = str(self.slug)
temp_image = open(os.path.join('tmp',filename), 'w')
thumb.save(temp_image, 'JPEG')
from django.core.files import File
thumb_data = open(os.path.join('/tmp',filename), 'r')
thumb_file = File(thumb_data)
new_file.thumb.save(str(self.slug) + '.jpg', thumb_file)
def __str__(self):
return self.title
This is just one of the many ways I have tried to get it working, and I either get (2, 'No such file or directory') or some other error.
Please can someone help me to get it working. I want it to use the django backend to get the image uploaded to be resized and saved as the thumbnail and then saved. Let me know if you need to know any information. I would be happy to use the django snippet - http://djangosnippets.org/snippets/224/ but I don't know what data to feed it. I get the same IOErrors and 'no such path/filename' even though the main image is uploading to s3 fine. I have also tried things like:
myimage = open(settings.MEDIA_URL + str(self.image))
myimage_io = StringIO.StringIO()
imageresize = myimage.resize((100,100), Image.ANTIALIAS)
imageresize.save('resize_100_100_aa.jpg', 'JPEG', quality=75)
It's been 3 days of looking now so I am starting to go spare! Thanks
I had a similar problem, but in my case using sorl-thumbnail was not an option. I found that I can open an Image directly from S3BotoStorage by passing in a file descriptor instead of a path.
So instead of
thumb = Image.open(self.image.path)
use
thumb = Image.open(s3_storage.open(self.image.name))
Then you can process and save the new file locally as you were doing before.
Why don't you try sorl-thumbnail. It has the exact same interface as the default ImageField django provides and it seems like it would be a lot nicer to work with than the roll-your-own support.
Storage support
Pluggable Engine support (PIL, pgmagick)
Pluggable Key Value Store support (redis, cached db)
Pluggable Backend support
Admin integration with possibility to delete
Dummy generation
Flexible, simple syntax, generates no html
ImageField for model that deletes thumbnails
CSS style cropping options
Margin calculation for vertical positioning

Overriding _get_url() from ImageField

I'm looking to the best way to overriding the _get_url method from ImageField, I need to customize the url since I don't want the default returned url (I distribute this image trhough a view to manage ACL on it so the url based on the MEDIA_ROOT is wrong).
Should I have to create my own ImageField ? or is there a solution using less code ?
Thanks in advance
Fabien
The url returned be _get_url is actually generated by the used Storage class; it would probably make more sense to create your own Storage and use it when creating the ImageField!
See: http://docs.djangoproject.com/en/dev/topics/files/#file-storage, http://docs.djangoproject.com/en/dev/howto/custom-file-storage/
You will neet to override the Storage.url method for that!
Thanks to lazerscience, here my final solution :
from django.core.files.storage import FileSystemStorage
from django.db.models import get_model
from django.core.urlresolvers import reverse
from django.db import models
from django.conf import settings
class PhotographerStorage(FileSystemStorage):
def __init__(self, location=None):
super(PhotographerStorage, self).__init__(location)
def url(self, name):
photo_model = get_model('photographer', 'photo')
photo = photo_model.objects.get(original_image=name)
url = super(PhotographerStorage, self).url(name)
return '%s?size=%d' % (reverse('photographer_photo_display',
args=[photo.slug]), 300)
fs = PhotographerStorage(location=settings.PHOTOGRAPHER_LOCATION)
class Photo(models.Model):
...
original_image = models.ImageField(storage=fs)
...
It works like a charm :)