Here's working version with user_passes_test. But I would like to replace position > 1 with parameter. I found that, it's possible to do with UserPassesTestMixin. But I don't know how. Can anyone help?
models.py
class user_control(models.Model):
user = models.ForeignKey(user, on_delete=CASCADE)
position = models.ForeignKey(position, on_delete=CASCADE)
...
views.py
def position_check(user):
position = 0 if user.is_anonymous else user_control.objects.values(
'position__rank'
).get(
user = user.id
)
return True if position > 1 else False
#user_passes_test(position_check, login_url='loginPage')
def index(request):
pass
#user_passes_test(position_check, login_url='loginPage')
def exportReview(request):
pass
I was try:
class PositionCheckMixin(LoginRequiredMixin, UserPassesTestMixin):
position_value = 2
def test_func(self):
position = 0 if user.is_anonymous else user_control.objects.values(
'position__rank'
).get(
user = self.request.user.id
)
return position > self.position_value
def handle_no_permission(self):
return redirect('loginPage')
class Review(PositionCheckMixin):
position_value = 2
def index(request):
You can make a decorator that takes for example an optional parameter:
def position_check(function=None, position_value=1, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None):
def check(user):
position = 0 if user.is_anonymous else user_control.objects.values(
'position__rank'
).get(
user=user.id
)
return position > position_value
actual_decorator = user_passes_test(
check,
login_url=login_url,
redirect_field_name=redirect_field_name,
)
if function:
return actual_decorator(function)
return actual_decorator
Then you can use the decorator with:
#position_check(position_value=42, login_url='loginPage')
def index(request):
# …
pass
For a class-based view, using the UserPassesTestMixin mixin [Django-doc] is more convenient:
class PositionCheckMixin(UserPassesTestMixin):
position_value = 1
def test_func(self):
position = 0 if self.request.user.is_anonymous else user_control.objects.values(
'position__rank'
).get(
user=self.request.user.id
)
return position > self.position_value
then you can mix this in a class-based view with:
class MyView(PositionCheckMixin, View):
position_value = 42
# …
I want to override the render for RadioSelect in django. (I have done a similar thing for checkboxes and I want both to look the same). The general workflow for this would be to write a custom renderer, and then change the render in the ChoiceInput, BUT when I copy the existing code and run it the html output is not safe and the escaped html string is shown. This is not making any sense as I didn't do any changes to the class yet, other than change the name:
In my widgets.py:
class ButtonRadioFieldRenderer(ChoiceFieldRenderer):
choice_input_class = OtherRadioChoiceInput
class OtherRadioChoiceInput(OtherChoiceInput):
input_type = 'radio'
def __init__(self, *args, **kwargs):
super(OtherRadioChoiceInput, self).__init__(*args, **kwargs)
self.value = force_text(self.value)
#html_safe
#python_2_unicode_compatible
class OtherChoiceInput(SubWidget):
"""
An object used by ChoiceFieldRenderer that represents a single
<input type='$input_type'>.
"""
input_type = None # Subclasses must define this
def __init__(self, name, value, attrs, choice, index):
self.name = name
self.value = value
self.attrs = attrs
self.choice_value = force_text(choice[0])
self.choice_label = force_text(choice[1])
self.index = index
if 'id' in self.attrs:
self.attrs['id'] += "_%d" % self.index
def __str__(self):
return self.render()
def render(self, name=None, value=None, attrs=None, choices=()):
if self.id_for_label:
label_for = format_html(' for="{}"', self.id_for_label)
else:
label_for = ''
attrs = dict(self.attrs, **attrs) if attrs else self.attrs
return format_html(
'<label{}>{} {}</label>', label_for, self.tag(attrs), self.choice_label
)
def is_checked(self):
return self.value == self.choice_value
def tag(self, attrs=None):
attrs = attrs or self.attrs
final_attrs = dict(attrs, type=self.input_type, name=self.name, value=self.choice_value)
if self.is_checked():
final_attrs['checked'] = 'checked'
return format_html('<input{} />', flatatt(final_attrs))
#property
def id_for_label(self):
return self.attrs.get('id', '')
In my forms.py:
DELIMITER_CHOICES = [
('space', ugettext_lazy("space")),
('underscore', "_"),
]
class SingleDelimiterForm(forms.Form):
delimiter = forms.ChoiceField(initial=0, widget=forms.RadioSelect(renderer=ButtonRadioFieldRenderer), choices=DELIMITER_CHOICES)
The only changes I did was to put "Other" and "Button" in front of already existing classes, and the code doesn't run anymore. If I change OtherChoiceInput to ChoiceInput the code is working. (in the end I only want to add a class to the label...)
I needed unicode strings for the code to work, so from __future__ import unicode_literals fixed the issue. I still found this error very confusing.
I'm upgrading things as the title says, and now doing a rebuild_index seems to do nothing.
The output is a simple:
$ ./manage.py rebuild_index --noinput
Removing all documents from your index because you said so.
All documents removed.
Indexing 17019 users
Indexing 76 gears
Indexing 186523 images
and all of my prepare_FOO functions are not run.
These are my settings:
HAYSTACK_DEFAULT_OPERATOR = 'AND'
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 70
HAYSTACK_CONNECTIONS = {
'default': {
'engine': 'haystack.backends.solr_backend.SolrEngine',
'URL': 'http://127.0.0.1:8983/solr',
'EXCLUDED_INDEXES': [
'threaded_messages.search_indexes.Thread',
'threaded_messages.search_indexes.ThreadIndex',
],
},
}
And these are my indexes:
# Python
import string
import re
import datetime
# Django
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.db.models import Q
# Third party apps
from haystack.indexes import *
from hitcount.models import HitCount
from toggleproperties.models import ToggleProperty
# This app
from astrobin.models import Image
from astrobin.models import DeepSky_Acquisition
from astrobin.models import SolarSystem_Acquisition
from astrobin.models import UserProfile
from astrobin.models import Gear, CommercialGear, RetailedGear
from astrobin.utils import unique_items
# Other AstroBin apps
from nested_comments.models import NestedComment
def _get_integration(image):
deep_sky_acquisitions = DeepSky_Acquisition.objects.filter(image=image)
solar_system_acquisition = None
integration = 0
try:
solar_system_acquisition = SolarSystem_Acquisition.objects.get(image=image)
except:
pass
if deep_sky_acquisitions:
for a in deep_sky_acquisitions:
if a.duration and a.number:
integration += (a.duration * a.number)
elif solar_system_acquisition:
return 0
return integration
def _prepare_likes(obj):
return ToggleProperty.objects.toggleproperties_for_object("like", obj).count()
def _prepare_moon_phase(obj):
from moon import MoonPhase
deep_sky_acquisitions = DeepSky_Acquisition.objects.filter(image=obj)
moon_illuminated_list = []
if deep_sky_acquisitions:
for a in deep_sky_acquisitions:
if a.date is not None:
m = MoonPhase(a.date)
moon_illuminated_list.append(m.illuminated * 100.0)
if len(moon_illuminated_list) == 0:
# We must make an assumption between 0 and 100, or this won't
# show up in any searches.
return 0
return sum(moon_illuminated_list) / float(len(moon_illuminated_list))
def _prepare_first_acquisition_date(obj):
deep_sky_acquisitions = DeepSky_Acquisition.objects.filter(image=obj)
solar_system_acquisition = None
try:
solar_system_acquisition = SolarSystem_Acquisition.objects.get(image=obj)
except:
pass
date = None
if deep_sky_acquisitions:
date = deep_sky_acquisitions[0].date
for a in deep_sky_acquisitions:
if a.date is not None and date is not None:
if a.date < date:
date = a.date
elif solar_system_acquisition:
date = solar_system_acquisition.date
return date
def _prepare_last_acquisition_date(obj):
deep_sky_acquisitions = DeepSky_Acquisition.objects.filter(image=obj)
solar_system_acquisition = None
try:
solar_system_acquisition = SolarSystem_Acquisition.objects.get(image=obj)
except:
pass
date = None
if deep_sky_acquisitions:
date = deep_sky_acquisitions[0].date
for a in deep_sky_acquisitions:
if a.date is not None and date is not None:
if a.date > date:
date = a.date
elif solar_system_acquisition:
date = solar_system_acquisition.date
return date if date else datetime.datetime.min
def _prepare_views(obj, content_type):
views = 0
try:
views = HitCount.objects.get(object_pk = obj.pk, content_type__name = content_type).hits
except:
pass
return views
def _prepare_min_aperture(obj):
d = 0
for telescope in obj.imaging_telescopes.all():
if telescope.aperture is not None and (d == 0 or telescope.aperture < d):
d = int(telescope.aperture)
return d
def _prepare_max_aperture(obj):
import sys
d = sys.maxint
for telescope in obj.imaging_telescopes.all():
if telescope.aperture is not None and (d == sys.maxint or telescope.aperture > d):
d = int(telescope.aperture)
return d
def _prepare_min_pixel_size(obj):
s = 0
for camera in obj.imaging_cameras.all():
if camera.pixel_size is not None and (s == 0 or camera.pixel_size < s):
s = int(camera.pixel_size)
return s
def _prepare_max_pixel_size(obj):
import sys
s = sys.maxint
for camera in obj.imaging_cameras.all():
if camera.pixel_size is not None and (s == sys.maxint or camera.pixel_size > s):
s = int(camera.pixel_size)
return s
def _prepare_telescope_types(obj):
return [x.type for x in obj.imaging_telescopes.all()]
def _prepare_camera_types(obj):
return [x.type for x in obj.imaging_cameras.all()]
def _prepare_comments(obj):
ct = ContentType.objects.get(app_label = 'astrobin', model = 'image')
return NestedComment.objects.filter(
content_type = ct,
object_id = obj.id,
deleted = False).count()
class GearIndex(SearchIndex, Indexable):
model_weight = IntegerField()
text = CharField(document=True, use_template=True)
images = IntegerField()
# Total likes of all images taken with this item.
likes = IntegerField()
# Total integration of images taken with this item.
integration = FloatField()
# Total views on images taken with this item.
views = IntegerField()
# Number of bookmarks on images taken with this item.
bookmarks = IntegerField()
# Number of comments on images taken with this item.
comments = IntegerField()
producers = MultiValueField()
retailers = MultiValueField()
def index_queryset(self, using = None):
return self.get_model().objects\
.exclude(commercial = None)\
.filter(commercial__producer__groups__name = 'Paying')
def get_model(self):
return Gear
def get_images(self, obj):
filters = (\
Q(imaging_telescopes = obj) |\
Q(guiding_telescopes = obj) |\
Q(mounts = obj) |\
Q(imaging_cameras = obj) |\
Q(guiding_cameras = obj) |\
Q(focal_reducers = obj) |\
Q(software = obj) |\
Q(filters = obj) |\
Q(accessories = obj)\
)
return Image.objects.filter(filters).distinct()
def prepare_model_weight(self, obj):
# Printing here just because it's the first "prepare" function.
print "%s: %d" % (obj.__class__.__name__, obj.pk)
return 100;
def prepare_images(self, obj):
return len(self.get_images(obj))
def prepare_likes(self, obj):
likes = 0
for i in self.get_images(obj):
likes += ToggleProperty.objects.toggleproperties_for_object("like", i).count()
return likes
def prepare_integration(self, obj):
integration = 0
for i in self.get_images(obj):
integration += _get_integration(i)
return integration / 3600.0
def prepare_views(self, obj):
views = 0
for i in self.get_images(obj):
views += _prepare_views(i, 'image')
return views
def prepare_bookmarks(self, obj):
bookmarks = 0
for i in self.get_images(obj):
bookmarks += ToggleProperty.objects.toggleproperties_for_object("bookmark", i).count()
return bookmarks
def prepare_comments(self, obj):
comments = 0
for i in self.get_images(obj):
comments += _prepare_comments(i)
return comments
def prepare_producers(self, obj):
producers = CommercialGear.objects\
.filter(base_gear = obj)\
.exclude(Q(producer__userprofile__company_name = None) | Q(producer__userprofile__company_name = ""))
return ["%s" % x.producer.userprofile.company_name for x in producers]
def prepare_retailers(self, obj):
retailers = RetailedGear.objects\
.filter(gear = obj)\
.exclude(Q(retailer__userprofile__company_name = None) | Q(retailer__userprofile__company_name = ""))
return ["%s" % x.retailer.userprofile.company_name for x in retailers]
class UserIndex(SearchIndex, Indexable):
model_weight = IntegerField()
text = CharField(document=True, use_template=True)
images = IntegerField()
avg_integration = FloatField()
# Total likes of all user's images.
likes = IntegerField()
# Total likes of all user's images.
average_likes = FloatField()
# Normalized likes (best images only)
normalized_likes = FloatField()
# Number of followers
followers = IntegerField()
# Total user ingegration.
integration = FloatField()
# Average moon phase under which this user has operated.
moon_phase = FloatField()
# First and last acquisition dates, including all images of course.
first_acquisition_date = DateTimeField()
last_acquisition_date = DateTimeField()
# Total views from all images.
views = IntegerField()
# Min and max aperture of all telescopes used in this user's images.
min_aperture = IntegerField()
max_aperture = IntegerField()
# Min and max pixel size of all cameras used in this user's images.
min_pixel_size = IntegerField()
max_pixel_size = IntegerField()
# Number of bookmarks on own images
bookmarks = IntegerField()
# Types of telescopes and cameras with which this user has imaged.
telescope_types = MultiValueField()
camera_types = MultiValueField()
comments = IntegerField()
comments_written = IntegerField()
username = CharField(model_attr = 'username')
def index_queryset(self, using = None):
return self.get_model().objects.all()
def get_model(self):
return User
def prepare_model_weight(self, obj):
# Printing here just because it's the first "prepare" function.
print "%s: %d" % (obj.__class__.__name__, obj.pk)
return 200;
def prepare_images(self, obj):
return Image.objects.filter(user = obj).count()
def prepare_avg_integration(self, obj):
integration = 0
images = 0
for i in Image.objects.filter(user = obj):
image_integration = _get_integration(i)
if image_integration:
images += 1
integration += image_integration
return (integration / 3600.0) / images if images else 0
def prepare_likes(self, obj):
likes = 0
for i in Image.objects.filter(user = obj):
likes += ToggleProperty.objects.toggleproperties_for_object("like", i).count()
return likes
def prepare_average_likes(self, obj):
likes = self.prepare_likes(obj)
images = self.prepare_images(obj)
return likes / float(images) if images > 0 else 0
def prepare_normalized_likes(self, obj):
def average(values):
if len(values):
return sum(values) / float(len(values))
return 0
def index(values):
import math
return average(values) * math.log(len(values)+1, 10)
avg = self.prepare_average_likes(obj)
norm = []
for i in Image.objects.filter(user = obj):
likes = i.likes()
if likes >= avg:
norm.append(likes)
if len(norm) == 0:
return 0
return index(norm)
def prepare_followers(self, obj):
return ToggleProperty.objects.filter(
property_type = "follow",
content_type = ContentType.objects.get_for_model(User),
object_id = obj.pk
).count()
def prepare_integration(self, obj):
integration = 0
for i in Image.objects.filter(user = obj):
integration += _get_integration(i)
return integration / 3600.0
def prepare_moon_phase(self, obj):
l = []
for i in Image.objects.filter(user = obj):
l.append(_prepare_moon_phase(i))
if len(l) == 0:
return 0
return reduce(lambda x, y: x + y, l) / len(l)
def prepare_first_acquisition_date(self, obj):
l = []
for i in Image.objects.filter(user = obj):
l.append(_prepare_first_acquisition_date(obj))
if len(l) == 0:
return None
return min(l)
def prepare_last_acquisition_date(self, obj):
l = []
for i in Image.objects.filter(user = obj):
l.append(_prepare_last_acquisition_date(obj))
if len(l) == 0:
return None
return max(l)
def prepare_views(self, obj):
views = 0
for i in Image.objects.filter(user = obj):
views += _prepare_views(i, 'image')
return views
def prepare_min_aperture(self, obj):
l = []
for i in Image.objects.filter(user = obj):
l.append(_prepare_min_aperture(i))
if len(l) == 0:
return 0
return min(l)
def prepare_max_aperture(self, obj):
l = []
for i in Image.objects.filter(user = obj):
l.append(_prepare_max_aperture(i))
if len(l) == 0:
return 0
return max(l)
def prepare_min_pixel_size(self, obj):
l = []
for i in Image.objects.filter(user = obj):
l.append(_prepare_min_pixel_size(i))
if len(l) == 0:
return 0
return min(l)
def prepare_max_pixel_size(self, obj):
l = []
for i in Image.objects.filter(user = obj):
l.append(_prepare_max_pixel_size(i))
if len(l) == 0:
return 0
return max(l)
def prepare_bookmarks(self, obj):
bookmarks = 0
for i in Image.objects.filter(user = obj):
bookmarks += ToggleProperty.objects.toggleproperties_for_object("bookmark", i).count()
return bookmarks
def prepare_telescope_types(self, obj):
l = []
for i in Image.objects.filter(user = obj):
l += _prepare_telescope_types(i)
return unique_items(l)
def prepare_camera_types(self, obj):
l = []
for i in Image.objects.filter(user = obj):
l += _prepare_camera_types(i)
return unique_items(l)
def prepare_comments(self, obj):
comments = 0
for i in Image.objects.filter(user = obj):
comments += _prepare_comments(i)
return comments
def prepare_comments_written(self, obj):
return NestedComment.objects.filter(author = obj, deleted = False).count()
class ImageIndex(SearchIndex, Indexable):
model_weight = IntegerField()
text = CharField(document=True, use_template=True)
uploaded = DateTimeField(model_attr='uploaded')
likes = IntegerField()
integration = FloatField()
moon_phase = FloatField()
first_acquisition_date = DateTimeField()
last_acquisition_date = DateTimeField()
views = IntegerField()
solar_system_main_subject = IntegerField()
is_deep_sky = BooleanField()
is_clusters = BooleanField()
is_nebulae = BooleanField()
is_galaxies = BooleanField()
is_solar_system = BooleanField()
is_sun = BooleanField()
is_moon = BooleanField()
is_planets = BooleanField()
is_comets = BooleanField()
license = IntegerField(model_attr = 'license')
min_aperture = IntegerField()
max_aperture = IntegerField()
min_pixel_size = IntegerField()
max_pixel_size = IntegerField()
bookmarks = IntegerField()
telescope_types = MultiValueField()
camera_types = MultiValueField()
comments = IntegerField()
is_commercial = BooleanField()
subject_type = IntegerField(model_attr = 'subject_type')
username = CharField(model_attr = 'user__username')
def index_queryset(self, using = None):
return self.get_model().objects.filter(moderator_decision = 1)
def get_model(self):
return Image
def prepare_model_weight(self, obj):
# Printing here just because it's the first "prepare" function.
print "%s: %d" % (obj.__class__.__name__, obj.pk)
return 300;
def prepare_likes(self, obj):
return _prepare_likes(obj)
def prepare_integration(self, obj):
return _get_integration(obj)
def prepare_moon_phase(self, obj):
return _prepare_moon_phase(obj)
def prepare_first_acquisition_date(self, obj):
return _prepare_first_acquisition_date(obj)
def prepare_last_acquisition_date(self, obj):
return _prepare_last_acquisition_date(obj)
def prepare_views(self, obj):
return _prepare_views(obj, 'image')
def prepare_solar_system_main_subject(self, obj):
return obj.solar_system_main_subject
def prepare_is_deep_sky(self, obj):
return DeepSky_Acquisition.objects.filter(image = obj).count() > 0
def prepare_is_solar_system(self, obj):
if obj.solar_system_main_subject:
return True
if SolarSystem_Acquisition.objects.filter(image = obj):
return True
return False
def prepare_is_sun(self, obj):
return obj.solar_system_main_subject == 0
def prepare_is_moon(self, obj):
return obj.solar_system_main_subject == 1
def prepare_is_planets(self, obj):
return obj.solar_system_main_subject in range(2, 8)
def prepare_is_comets(self, obj):
return obj.solar_system_main_subject == 10
def prepare_min_aperture(self, obj):
return _prepare_min_aperture(obj)
def prepare_max_aperture(self, obj):
return _prepare_max_aperture(obj)
def prepare_min_pixel_size(self, obj):
return _prepare_min_pixel_size(obj)
s = 0
for camera in obj.imaging_cameras.all():
if camera.pixel_size is not None and (s == 0 or camera.pixel_size < s):
s = int(camera.pixel_size)
return s
def prepare_max_pixel_size(self, obj):
return _prepare_max_pixel_size(obj)
import sys
s = sys.maxint
for camera in obj.imaging_cameras.all():
if camera.pixel_size is not None and (s == sys.maxint or camera.pixel_size > s):
s = int(camera.pixel_size)
return s
def prepare_bookmarks(self, obj):
return ToggleProperty.objects.toggleproperties_for_object("bookmark", obj).count()
def prepare_telescope_types(self, obj):
return _prepare_telescope_types(obj)
def prepare_camera_types(self, obj):
return _prepare_camera_types(obj)
def prepare_comments(self, obj):
return _prepare_comments(obj)
def prepare_is_commercial(self, obj):
commercial_gear = CommercialGear.objects.filter(image = obj)
return commercial_gear.count() > 0
Any idea what I might be missing? Thanks!
Got it. 'ENGINE' should be all capitals, in the settings.
It it possible ? I want compare two fields and return score to bet_score field.
class Tabela(models.Model):
score1= models.IntegerField(max_length=3)
score2 = models.IntegerField(max_lenght=3)
bet_score= models.IntegerField(defaults=bet_score())
def bet_score(self):
if (self.score1> self.score2 ):
return 1
elif (self.score1== self.score2 ):
return 0
else:
return 2
If you want to store this kind of thing on a model, I think your best option would be to override the save method:
class Tabela(models.Model):
score1= models.IntegerField(max_length=3)
score2 = models.IntegerField(max_lenght=3)
bet_score= models.IntegerField()
def save(self, *args, **kwargs):
if (self.score1 > self.score2 ):
self.bet_score = 1
elif (self.score1 == self.score2 ):
self.bet_score = 0
else:
self.bet_score = 2
super(Tabela, self).save(*args, **kwargs)
Check out the docs for more info.
class CourtColumn(tables.Column):
def render(self, value):
if value == 'Hard':
self.attrs ={"td": {"bgcolor": "DeepSkyBlue"}}
elif value == 'Clay':
self.attrs ={"td": {"bgcolor": "SandyBrown"}}
class TodayTable(tables.Table):
Rank = tables.Column(accessor='tour.rank_t',orderable=True)
Tour = tables.Column(accessor='tour.name_t')
Court = CourtColumn(accessor='tour.id_c_t.name_c',verbose_name= 'Court')
...
def render_Tour(self, record):
if record.tour.rank_t == 0:
self.attrs ={"td": {"bgcolor": "Violet"}}
return u"%s" % (record.tour.name_t)
I get to Court ... td bgcolor="SandyBrown" class="Court">Clay< ... - ОК.How to get to the same Tour, but use the value of another column? def render_Tour not working as required
Subclass tables.Column and take advantage of the record argument:
class TourColumn(tables.Column):
def render(self, value, record):
if record.tour.rank_t == 0:
self.attrs ={"td": {"bgcolor": "Violet"}}
return u"%s" % (record.tour.name_t)
Then use that class in your table:
Tour = TourColumn(accessor='tour.name_t')