Connecting my django app to the redis installation - python

I have a django app. The app is a normal application. Everything is running fine for me.
I want to implement a leaderboard as of now. Read couple of places that redis helps in doing it. And is really awesome. So I installed and configured redis on the server.
A minimal representation of the user profile for me is:
class UserProfile(models.Model):
user = models.OneToOneField(User)
invited_friends = models.BooleanField(default=False)
filled_wishlist = models.BooleanField(default=False)
upvote = models.IntegerField()
downvote = models.IntegerField()
#property
def reputation(self):
return int(confidence_fixed(self.upvote, self.downvote)*100)
Based on this reputation property, I get a value. All this is happening at the PostgreSQL db backend.
Now what I want to do is, take these scores, put them in redis key value store, and generate a leaderboard. There is a superawesome redis library for implementing leaderboard: https://github.com/agoragames/leaderboard-python
So my question is, given my redis server is running say at XXX.XXX.XX.XX:6342
How do I connect my python/django app to the redis server, and update the KV store, and once there are some numbers, how do I fetch in a view and display?

I think you're on the right track with the leaderboard-python library.
First you would need to write a onetime script to move the data from your model to redis using leaderboard-python.
# Create a new leaderboard
reputation_lb = Leaderboard('reputation')
for profile in UserProfile.objects.all():
reputation.rank_member('user_%i' % profile.user.pk, profile.reputation)
You would also need to create another property on the UserProfile model that retrieves the reputation from leaderboard-python.
Then you would most likely want to update the score, either you duplicate the information in the database and continue to use your reputation property to update the leaderboard, or you simply increment/decrement the score stored in redis.
The readme of the leaderboard-python library is quite good and should contain all of the examples you need to build this.

For future googlers, the way to tell Leaderboard how to connect to your redis server is by specifying a few more arguments in the Leaderboard constructor:
reputation_lb = Leaderboard('reputation', host="xyz.com", port="1234")
More details about what options are supported can be found in constructor code for Leaderboard here: http://pydoc.net/Python/leaderboard/2.8.0/leaderboard/

Related

How can I make unique user "sessions" for my Django web application running on heroku?

I made a web application using Django, that stores information in python arrays that are accessed by the user via the front-end. My problem now is that since I have deployed it via heroku, you can't use the website on more than one device, or else options selected from one device affects the website data for all devices.
How would I be able to make it so that user experiences are different / unrelated? How can I alter the views.py (or other components) so that the web application has a "session" for each user?
This is for a django web application running on heroku. The application is for my school, and it's akin to a battle-royal type site. Users can select people displayed on the site, which in turn removes them from a python dictionary that's stored in memory and puts them in another dictionary for later. The problem is, if more than one person is using the site at one time, they access the same dictionary. I haven't a clue what to try to solve this.
"processor.py"
names, accepted = list(), list()
# names contains many names of people, accepted is empty
def accept_person(person):
if person in names:
accepted.append(person)
names.remove(person)
else:
a = difflib.get_close_matches(person, names)
if len(a) > 1:
accepted.append(a[0])
names.remove(a[0])
else:
pass
"views.py"
def view_home(request):
if request.method == 'POST':
if(request.POST.get("yes")):
processor.accept_person(request.POST.get("yes", False))
Accepting a person on one device accepts that person for everyone accessing the site. I want to be able to have one "session" per user, so that one person changing this python dictionary doesn't affect everyone's experience.
What you are looking for here is a way to authenticate users, Django is brilliant for this and handles basically all of it for you.
But if you really want a full solution with minimal effort I would take a look at a package called django-allauth.
The official docs (https://django-allauth.readthedocs.io/en/latest/installation.html) can be a bit daunting so here is a good tutorial I followed the first time I integrated authentication into Django.
https://wsvincent.com/django-allauth-tutorial/

Django: Random ManyToMany relation is added on User connect

Strangest bug I ever encountered
User model is the regular one from conrtib.auth.User
Let's say I have the following model:
class Region(model.Model):
name = models.CharField(max_length=256)
rakazim = models.ManyToManyField(settings.AUTH_USER_MODEL)
goal = models.IntegerField(default=0)
and someplace else I have:
user_model = get_user_model()
rakaz = user_model.objects.create_user(username, email, password)
Then Immediately after the user creation method is called the "rakaz" instance has a random region connected
rakaz.region_set.all() = [<random_region>]
It also sometimes connects to another model that has a similar ManyToManyField to AUTH_USER_MODEL
I debugged with pdb into the user creation method (in auth contrib) and immediately after calling save inside this happens.
AFAIK it happens only on the staging server, but until I find the reason I'm afraid to deploy to prod..
Django version 1.84. server using mariabdb on RDS
I don't use signals in my code (and at all :) ) and can't find relevant third party code doing this, (And if so it would happen on my machine also)
Any Ideas?
The issue turned out to be:
I seeded the staging server with data from prod for "region" the dumpdata command dumps the region with foreign keys for rakazim . But since the users where actually missing (I didn't copy the users from my prod environment) Instead of shouting at me, and not allowing me to loaddata with non existing foreign keys, mariadb chose to give me :+1 and add random foreign keys each time I created a user (Perhaps not random, but according to the imported mapping, not sure).
Lesson learned: use a proper DBMS and not a mysql varient.

How to create a user to user message system using Django?

I am trying to create a private messaging system using Django. It doesn't have to be like a live chat, just have an inbox and be able to respond, simple thing like that. So far, from research I have found two things: django.contrib.messages which doesn't seem to be for private messages, but rather messages from the system to a user. Then I also found django-postman which seems to be what I'm looking for, but there seems to be little documentation on how to use it. So has anybody used anything else to accomplish this? Or am I wrong about django.contrib.messaging? Or is there good documentation on django-postman that I'm missing?
You can create your own custom message app.
Models for Message like app :
Class Message():
Class Message(models.Model):
sender = models.ForeignKey(User, related_name="sender")
reciever = # almost same as above field, just change the related-name
msg_content = # text field
created_at = # time field
Create a form for this model, use model form .
filter "Inbox" queries in views.py by
Message.objects.filter(reciever=request.user)
filter "Sent Box" queries in views.py by
Message.objects.filter(sender = request.user)
There is good documentation on django-postman that you're missing:
https://bitbucket.org/psam/django-postman/wiki/browse/
or
http://django-postman.readthedocs.org/en/latest/
For queries like these, I usually head to Django Packages (https://djangopackages.org/) which lists popular Django packages with comparisons, categorised by the functionality needed.
It has a grid for messaging and based on this grid, django-messages, django-private-chat and django-postman seem to be the top ones.

How to add many to one relationship with model from external application in django

My django project uses django-helpdesk app.
This app has Ticket model.
My app got a Client model, which should have one to many relationship with ticket- so I could for example list all tickets concerning specific client.
Normally I would add models.ForeignKey(Client) to Ticket
But it's an external app and I don't want to modify it (future update problems etc.).
I wold have no problem with ManyToMany or OneToOne but don't know how to do it with ManyToOne (many tickets from external app to one Client from my app)
Even more hacky solution: You can do the following in the module level code after you Client class:
class Client(models.Model):
...
client = models.ForeignKey(Client, related_name='tickets')
client.contribute_to_class(Ticket, name='client')
I haven't fully tested it (I didn't do any actual database migrations), but the correct descriptors (ReverseSingleRelatedObjectDescriptor for Ticket and ForeignRelatedObjectsDescriptor for Client) get added to the class, and South recognizes the new fields. So far it seems to work just like a regular ForeignKey.
EDIT: Actually not even that hacky. This is exactly how Django sets up foreign keys across classes. It just reverses the process by adding the field when the reverse related class is built. It won't raise an error if any of the original fields on either model is shadowed. Just make sure you don't do that, as it could potentially break your code. Other than that, I don't think there should be any issues.
There are (at least) two ways to accomplish it:
More elegant solution: Use a TicketProfile class which has a one-to-one relation to Ticket, and put the Client foreign key into it.
Hacky solution: Use a many-to-many relation, and manually edit the automatically created table and make ticket_id unique.

Django-registration combine databases

I've installed the django-registration app succesfully and it works great.
But now I want that when people are logged in, they have to fill in more data about theirself.
Do I need to create an new django-app, so with a new database, or is it possible to save the data in the djano-registration app database (the database with username, password and e-mail)?
And how should I link these two databases, so everybody have his own, unique "index"-page with correct 'place'/link in/to the database?
Thanks a lot!
Look at the User-Profiles section of the auth application. It explains how to create a Profile object (basically a new table, not database), that is connected to the User object, and has whatever data you add to it. It can be retrieved with get_profile().
Just to highlight something in the docs - get_profile() does not automatically create a Profile for you, you need to manually create one each time a User is created. This Answer gives sample code for using Signals to create a profile - after a User is created, it sends a signal to any registered process. You would need to code, and register a profile-creation function with the signal.
The author of django-registration has also done a nice profile app. Wrapping around the User-Profiles.
Check it out at:
https://bitbucket.org/ubernostrum/django-profiles/

Categories