Giter Site home page Giter Site logo

django-ratings's Introduction

django-ratings

This project is no longer maintained

A generic ratings module. The field itself appends two additional fields on the model, for optimization reasons. It adds <field>_score, and <field>_votes fields, which are both integer fields.

Installation

You will need to add djangoratings to your INSTALLED_APPS:

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'djangoratings',
)

Finally, run python manage.py syncdb in your application's directory to create the tables.

Setup your models

The way django-ratings is built requires you to attach a RatingField to your models. This field will create two columns, a votes column, and a score column. They will both be prefixed with your field name:

from djangoratings.fields import RatingField

class MyModel(models.Model):
    rating = RatingField(range=5) # 5 possible rating values, 1-5

Alternatively you could do something like:

from djangoratings.fields import AnonymousRatingField

class MyModel(models.Model):
    rating = AnonymousRatingField(range=10)

If you'd like to use the built-in weighting methods, to make it appear more difficult for an object to obtain a higher rating, you can use the weight kwarg:

class MyModel(models.Model):
    rating = RatingField(range=10, weight=10)

RatingField allows the following options:

  • range = 2 - The range in which values are accepted. For example, a range of 2, says there are 2 possible vote scores.
  • can_change_vote = False - Allow the modification of votes that have already been made.
  • allow_delete = False - Allow the deletion of existent votes. Works only if can_change_vote = True
  • allow_anonymous = False - Whether to allow anonymous votes.
  • use_cookies = False - Use COOKIES to authenticate user votes. Works only if allow_anonymous = True.

Using the model API

And adding votes is also simple:

myinstance.rating.add(score=1, user=request.user, ip_address=request.META['REMOTE_ADDR'], request.COOKIES) # last param is optional - only if you use COOKIES-auth

Retrieving votes is just as easy:

myinstance.rating.get_rating_for_user(request.user, request.META['REMOTE_ADDR'], request.COOKIES) # last param is optional - only if you use COOKIES-auth

New You're also able to delete existent votes (if deletion enabled):

myinstance.rating.delete(request.user, request.META['REMOTE_ADDR'], request.COOKIES) # last param is optional - only if you use COOKIES-auth

Accessing information about the rating of an object is also easy:

# these do not hit the database
myinstance.rating.votes
myinstance.rating.score

How you can order by top-rated using an algorithm (example from Nibbits.com source):

# In this example, ``rating`` is the attribute name for your ``RatingField``
qs = qs.extra(select={
    'rating': '((100/%s*rating_score/(rating_votes+%s))+100)/2' % (MyModel.rating.range, MyModel.rating.weight)
})
qs = qs.order_by('-rating')

Get overall rating for your instance on a scale [0-range]:

myinstance.rating.get_rating()

Get recent ratings for your instance:

# This returns ``Vote`` instances.
myinstance.rating.get_ratings()[0:5]

Get the percent of voters approval:

myinstance.rating.get_percent()

Get that same percentage, but excluding your weight:

myinstance.rating.get_real_percent()

Generic Views: Processing Votes

The best way to use the generic views is by extending it, or calling it within your own code:

from djangoratings.views import AddRatingFromModel

urlpatterns = patterns('',
    url(r'rate-my-post/(?P<object_id>\d+)/(?P<score>\d+)/', AddRatingFromModel(), {
        'app_label': 'blogs',
        'model': 'post',
        'field_name': 'rating',
    }),
)

Another example, on Nibbits we use a basic API interface, and we simply call the AddRatingView within our own view:

from djangoratings.views import AddRatingView

# For the sake of this actually looking like documentation:
params = {
    'content_type_id': 23,
    'object_id': 34,
    'field_name': 'ratings', # this should match the field name defined in your model
    'score': 1, # the score value they're sending
}
response = AddRatingView()(request, **params)
if response.status_code == 200:
    if response.content == 'Vote recorded.':
        request.user.add_xp(settings.XP_BONUSES['submit-rating'])
    return {'message': response.content, 'score': params['score']}
return {'error': 9, 'message': response.content}

COOKIE format

New: For now COOKIE name has fixed format: "vote-{{ content_type.id }}.{{ object.id }}.{{ rating_field.key }}[:6]" and COOKIE value is simple datetime-stamp.

Example: vote-15.56.2c5504=20101213101523456000

And this COOKIE lives in user's browser for 1 year (this period is also fixed for now)

This feature may change in the future

Limit Votes Per IP Address

New in 0.3.5: There is now a setting, RATINGS_VOTES_PER_IP, to limit the number of unique IPs per object/rating-field combination. This is useful if you have issues with users registering multiple accounts to vote on a single object:

RATINGS_VOTES_PER_IP = 3

Template Tags

Right now django-ratings has limited support for template tags, and only for Django. Load a ratings template tag set. `{% load ratings %}`.

rating_by_request

Retrieves the Vote cast by a user on a particular object and stores it in a context variable. If the user has not voted, the context variable will be 0:

{% rating_by_request request on instance.field as vote %}

If you are using Coffin, a better approach might be:

{% with instance.field_name.get_rating_for_user(request.user, request.META['REMOTE_ADDR'], request.COOKIES) as vote %}
        Do some magic with {{ vote }}
{% endwith %}

To use the request context variable you will need to add django.core.context_processors.request to the TEMPLATE_CONTEXT_PROCESSORS setting.

rating_by_user

It is recommended that you use rating_by_request as you will gain full support for anonymous users if they are enabled

Retrieves the Vote cast by a user on a particular object and stores it in a context variable. If the user has not voted, the context variable will be 0:

{% rating_by_user user on instance.field as vote %}

django-ratings's People

Contributors

dcramer avatar divyekapoor avatar elyezer avatar jezdez avatar jpic avatar kottenator avatar kulbir avatar strakh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-ratings's Issues

Ajax integration

Does anyone have a working example of Ajax integration for this, ideally with a JQuery rating system?

Unknown column 'resources_resources.rating_votes' in 'field list'

After installing and syncing db, i added this to my model:

rating = RatingField(range=5)

and got the error:

Unknown column 'resources_resources.rating_votes' in 'field list'

I checked the DB and the tables ratings_score and ratings_vote were created, but no columns were added to the model i added the RatingField to (not sure if it's supposed to add columns to it's DB).

What am i missing? I believe i followed to tutorial correctly. I'm on Django 1.6. If theres any manual solution to get this working it would help too.

Thanks in advance

Vote/Score entries are not deleted after deleting Model instance with RatingField

Hi,

I have a model which is using RatingField for one of its fields. When I delete a model instance (e.g. via django admin), the connected djangoratings.models.Vote and djangoratings.models.Score entries in the database still remain. The object_id and content_type are still the same and if I create a new instance of my model it might use the same object_id. This is messing up votes and scores for this new instance.
At the moment I only see the option to delete "related" Vote and Score instances when deleting my model instance.

Thanks for checking.

Torsten

still active?

sorry, but could you clarify if django-ratings is still being actively developed? there are several issues – some of them already solved with other branches (e.g. #12).

wrong issue

Dear DCramer

Sorry for disturbance,
I don't know how to delete wrong issue.

Thanx

Invalid block tag: 'rating_by_user', expected 'endblock'

I am trying to retrieve the vote by user. and I am getting Invalid block tag: 'rating_by_user', expected 'endblock' . I am using like this {% rating_by_user user on movie_detail.rating as vote %}. Am i missing something? thanks

This project needs a maintainer

Hi,

This repository seems to lack maintenance, I propose myself as a new maintainer.

Could you transfer it on my account in github or give me the right to push in your repository ?

Thank you

templatetag rating_by_user (incl. patch)

from django import template
from django.contrib.contenttypes.models import ContentType
from django.db.models import ObjectDoesNotExist

from djangoratings.models import Vote

register = template.Library()

class RatingByUserNode(template.Node):
def init(self, user, obj, context_var):
self.user = user
self.obj = obj
self.context_var = context_var

def render(self, context):
    try:
        user = template.resolve_variable(self.user, context)
        obj = template.resolve_variable(self.obj, context)
    except template.VariableDoesNotExist:
        return ''
    try:
        ctype = ContentType.objects.get_for_model(obj)
        context[self.context_var] = Vote.objects.get(content_type=ctype, object_id=obj._get_pk_val(), user=user)
    except ObjectDoesNotExist:
        context[self.context_var] = 0
    return ''

def do_rating_by_user(parser, token):
"""
Retrieves the Vote cast by a user on a particular object and
stores it in a context variable. If the user has not voted, the
context variable will be 0.

Example usage::

    {% rating_by_user user on widget as vote %}
"""

bits = token.contents.split()
if len(bits) != 6:
    raise template.TemplateSyntaxError("'%s' tag takes exactly five arguments" % bits[0])
if bits[2] != 'on':
    raise template.TemplateSyntaxError("second argument to '%s' tag must be 'on'" % bits[0])
if bits[4] != 'as':
    raise template.TemplateSyntaxError("fourth argument to '%s' tag must be 'as'" % bits[0])
return RatingByUserNode(bits[1], bits[3], bits[5])

register.tag('rating_by_user', do_rating_by_user)

South migration issue

Hy!

I'm new to South, so if this is something of my lack of knowledge, I apologize.

When I'm running ./manage.py migrate, I have the following error popping from your side:

ValueError: Cannot find a UNIQUE constraint on table djangoratings_vote, columns ['key', 'ip_address', 'object_id', 'content_type_id', 'user_id']

If you need the full stack, I can provide it

Thank you

askbot-devel clash

I'm installing askbot-devel as an additional app in a project already containing django-ratings.
Django version is 1.8
When I run runserver, I get this error:

SystemCheckError: SystemCheckError: System check identified some issues:

ERRORS:
askbot.Vote.user: (fields.E304) Reverse accessor for 'Vote.user' clashes with reverse accessor for 'Vote.user'.
    HINT: Add or change a related_name argument to the definition for 'Vote.user' or 'Vote.user'.
askbot.Vote.user: (fields.E305) Reverse query name for 'Vote.user' clashes with reverse query name for 'Vote.user'.
    HINT: Add or change a related_name argument to the definition for 'Vote.user' or 'Vote.user'.
djangoratings.Vote.user: (fields.E304) Reverse accessor for 'Vote.user' clashes with reverse accessor for 'Vote.user'.
    HINT: Add or change a related_name argument to the definition for 'Vote.user' or 'Vote.user'.
djangoratings.Vote.user: (fields.E305) Reverse query name for 'Vote.user' clashes with reverse query name for 'Vote.user'.
    HINT: Add or change a related_name argument to the definition for 'Vote.user' or 'Vote.user'.

Do you know a way to solve it?

Related issue is #559

Test Errors

When run ./manage.py test djangoratings I receive the following 3 times
DatabaseError: no such table: djangoratings_ratingtestmodel

I see that this model is defined in tests.py but can't figure out when it is supposed to be created so that it exists for the tests.

How to revoke the vote?

How do I let users "unvote"? Passing zero score to RatingManager.add() raises error; this class does not have a delete() method; I don't see any other way to delete the vote and correctly recalculate totals. Maybe we should delete the vote when zero score is passed to RatingManager.add()?

Not setting weight causes division by zero when calculating average (Postgres)

When I'm developing locally, I can leave the weight as default (0) and not get any errors when calculating the average rating using qs.extra(). However on a production server with Postgres this causes a 'Division by Zero' database error. I think this only happens when rating_votes+Recipe.rating.range is zero. I worked around this by setting the weight to 1.

Problem if my id key is not integer

My models all extend my custom model class which id is a CharField not a PositiveIntegerField like the Django's default django.db.models.Model . So, when I try to add a vote, the code will fail at:

rating, created = Vote.objects.get(**kwargs), False

in fields.py because of the object_id field being defined like this in models.py:

object_id       = models.PositiveIntegerField()

Any ideas how should I deal with this ?

Thanks in advance

allow updating votes

it currently doesn´t seem possible to vote more than once on an object. sometimes though, a user might wanna change his/her voting (esp. with something like a star-rating, it´s easy to click the wrong star with the first try). shoudn´t it be possible to update a voting?

DepractionWarning on RatingField

DeprecationWarning: A Field class whose get_db_prep_save method hasn't been updated to  take a `connection` argument.
  class RatingField(IntegerField):

using Django development version (1.3)

rating_score and rating_votes return zero after moving database

I have a weird problem when i export my local database to the server (and vice versa)
I still have the votes number and rating.get_ratings() working, but rating_score, rating_votes, rating.get_real_percent etc return all zero! Can you explane this? Is this related with the key field or with the ip?

DatabaseError: no such column

I installed the django-ratings package via pip and followed your installation instructions. I added an anonymous rating field like so:

from djangoratings.fields import AnonymousRatingField

class Foo(models.Model):
    name = models.CharField(max_length=200)
    rating = AnonymousRatingField(range=5)

Then I synced the db:

$ python manage.py syncdb
Creating tables ...
Installing custom SQL ...
Installing indexes ...
Installed 0 object(s) from 0 fixture(s)

However, when trying to open the admin view for my Foo model, I get this error:

Internal Server Error: /admin/foos/foo/
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 115, in get_response
    response = callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py", line 372, in wrapper
    return self.admin_site.admin_view(view)(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py", line 91, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/views/decorators/cache.py", line 89, in _wrapped_view_func
    response = view_func(request, *args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/sites.py", line 202, in inner
    return view(request, *args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py", line 25, in _wrapper
    return bound_func(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py", line 91, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py", line 21, in bound_func
    return func(self, *args2, **kwargs2)
  File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py", line 1285, in changelist_view
    'selection_note': _('0 of %(cnt)s selected') % {'cnt': len(cl.result_list)},
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 90, in __len__
    self._result_cache = list(self.iterator())
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 301, in iterator
    for row in compiler.results_iter():
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/compiler.py", line 775, in results_iter
    for rows in self.execute_sql(MULTI):
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/compiler.py", line 840, in execute_sql
    cursor.execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/django/db/backends/util.py", line 41, in execute
    return self.cursor.execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/django/db/backends/sqlite3/base.py", line 366, in execute
    six.reraise(utils.DatabaseError, utils.DatabaseError(*tuple(e.args)), sys.exc_info()[2])
  File "/usr/local/lib/python2.7/dist-packages/django/db/backends/sqlite3/base.py", line 362, in execute
    return Database.Cursor.execute(self, query, params)
DatabaseError: no such column: foos_foo.rating_votes

What have I done wrong?

__init__'s lazy_object __import__ call doesn't work with python2.4

In init.py:
imp = import(parts[0], globals(), locals(), [parts[1]], -1)

Fails on python2.4 with the error
"import() takes at most 4 arguments (5 given)"

I'd recommend a try/except here.
try:
imp = import(parts[0], globals(), locals(), [parts[1]], -1)
except:
imp = import(parts[0], globals(), locals(), [parts[1]])

explaining weight

this is not an issue - I´m just not sure about the implementation of "weight" (I probably just don´t understand it). with IMDB (for example), the weight refers to the total votes for an object. with django-rating, the weight is a static value. do you have any additional information about this? thanks in advance.

Loading templatetags

Reading the django docs on custom tags i figured I should do {% load ratings %} however this doesn't work. How are the tags loaded? The name to load should really be added to the README file.

Template Tags

I am not sure if this is an Issue or it's just something I misunderstood.

When I try to use the template tags I got a "TemplateSyntaxError": "Invalid block tag: 'rating_by_request' ". I tried to load the module but then I got the next error "not a valid tag library".

Is there any error or as I assume is just some error I have done ?

Thanks
Albert

ProgrammingError: relation "django_content_type" does not exist

Hi,
I just migrated to django 1.8

My operations are:

  1. scratch whole db
  2. remove all migartions from my apps
  3. manage.py makemigrations
  4. manage.py migrate

However I get this error after "manage.py migrate" command:

django.db.utils.ProgrammingError: relation "django_content_type" does not exist

The sql command causing the error is:

u'ALTER TABLE "djangoratings_vote" ADD CONSTRAINT "djan_content_type_id_34170de97babd8e2_fk_django_content_type_id" FOREIGN KEY ("content_type_id") REFERENCES "django_content_type" ("id") DEFERRABLE INITIALLY DEFERRED'

If a comment out djangoratings from INSTALLED_APPS, the migrations finishes without problems.

If I issue a "./manage.py showmigrations" I get empty migrations for django ratings.

contenttypes
 [ ] 0001_initial
 [ ] 0002_remove_content_type_name
djangoratings
 (no migrations)                     <------------ strange this
guardian
 [ ] 0001_initial

The exception is raised when running deferred SQL.

Creating tables...
    Creating table thumbnail_kvstore
    Creating table djangoratings_vote
    Creating table djangoratings_score
    Creating table djangoratings_similaruser
    Creating table djangoratings_ignoredobject
    Running deferred SQL...
Traceback (most recent call last):
  File "./manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
    ........

I will continue investigating but maybe you know/have a solution.

Thank you.

rating with ajax, in django1.4

how can I use rating with ajax, in django1.4
I want POST a request by ajax, but django report 403 status code, I need request with csrf_token code, how can I disable this in django-rating

Multiple Rating in One Object

Hi Guys,

How can I add multiple rating in one object. This is the example.

The Object is 'BORACAY BEACH, then I want to rate it by 'location', 'cleanliness', 'price'.

Thanks,
Ralph

Error in documentation

myinstance.rating.add(score=1, user=request.user, ip_address=request.META['REMOTE_ADDR'], request.COOKIES) # last param is optional - only if you use COOKIES-auth
-- non keyword arg.

can_delete_vote is an unexpected keyword argument

 from djangoratings.fields import RatingField

 class MyModel(models.Model):
     rating = RatingField(range=1, can_change_vote=True, can_delete_vote=True)

 TypeError: __init__() got an unexpected keyword argument 'can_delete_vote'

I get this error when trying to enable can_delete_vote

EDIT: turns out it is allow_delete and not can_delete_vote. The readme appears to be incorrect.

Ebay like rating system

How can i implement ebay like rating system using django-ratings. Should i create multiple rating fields? How can i aggregate all of them to make a single average rating? Thanks in advance.

CSRF vulnerability

The view accepts vote updates as a GET request (actually any kind of request). As such it is trivial to use this to exploit the rating system from any third party site.

Example: site A uses django-ratings to rate some items. On site B add

<img src="http://A/rate-my-post/100/10" width="1" height="1" />

Any user visiting site B will rate the thing on site A.

The effects of this vulneraibility depend mostly on can_change_vote and allow_anonymous.

Field class doesn't take connection and prepared arguments

Fields in new versions of django can receive a connection and prepared argument. I believe this is for multi-db. Until django-ratings accepts these variables, django will throw a DeprecationWarning using djangoratings.fields.RatingField:

DeprecationWarning: A Field class whose get_db_prep_lookup method hasn't been updated to take `connection` and `prepared` arguments.

Cannot deploy to Heroku

I followed closely your tutorial and my app works just fine on localhost on sqlite or postgres, but I've tried to deploy on Heroku and I'm getting the following error:

relation "subtitrari_subtitle" does not exist
LINE 1: ...votes", "subtitrari_subtitle"."rating_score" FROM "subtitrar...

Thanks.

Update for new Django (1.9.x)

Hi guys!

I work with 'django-ratings' a couple year and before this battery work perfectly for me. But now, i want migrate to Django 1.9.8 and comes with a few trouble:

  1. "...put your South migrations in the 'south_migrations' directory and your Django migrations in the 'migrations' directory." ( link to Docs: http://bit.ly/29YMN5F )
  2. "The django.contrib.contenttypes.generic module is removed." Now 'GenericForeignKey' in 'django.contrib.contenttypes.fields' ( link to Docs: http://bit.ly/2aee5pG )
  3. 'IPAddressField' now as 'GenericIPAddressField' ( link to Docs: http://bit.ly/2aF7ovF )

I hope what you update current version for users a new Django
Best regard

TemplateTag Not Working

Hello, after doing all the necessary settings. When I put the below template tag in my template, I can't see any rating objects that user can click on to rate. Not even the number of ratings.

   {% load ratings %}
   {% rating_by_user user on instance.field as vote %}

How can I fix this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.