As I am beginning to work my way through web-sockets using Python (Django Channels in this case), I am beginning to wonder how companies scale chat applications.
Take this specific problem:
User A has a list of "group messages" that they are involved in. User A is capable of receiving notifications from each of the groups. Lets suppose User A has 5 different groups he would like real time notifications for.
Does User A have 5 separate web socket connections? This is easiest, but the bulkiest and surely wont scale (what if we had 20 chats per user). It is quite easy to make a Django Channels "Group" that listens and sends notifications to one specific group of people.
Does User A instead have 1 web socket connection taking all notifications from many different locations? If so, what is User A subscribing to on the backend? In Django Channels, a websocket is made when users subscribe to a "Group". If we wanted one user per "Group', this would seem counter intuitive. In this case, User A is subscribing to their own personal "Group" and other backend services are delivering messages to that specific "Group" based on other logic that is implemented when a message is received from any user using the service.
This is very verbose and text heavy, but it diagrams an interesting problem that has scaled for other companies in the past. I appreciate any information or insight!
(this is a list of the problems that I thought were basically the same (ignoring language and library use))
1. Websocket multiple Channels vs. One Channel + Server Side handling [GroupChat]
first create a profile model:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, verbose_name=_("user"))
channel = models.CharField(unique=True, max_length=255, blank=True, null=True, verbose_name=_("channel")) # channel for notify user
then create a message model:
class Message(models.Model):
to_user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name=_("user"))
from_user = models.ForeignKey(User)
text = models.TextField(blank=True, null=True)
then use Django signals for sending notify:
#receiver(post_save, sender=Message)
def send_notify(instance, created, **kwargs):
if created:
Group('chat-{}'.format(instance.to_user.profile.channel)).send({'text': {'message': 'you have a new message'}})
sorry for my english : ))
Related
I am trying to implement a notification page on my website in Django. But I have a problem that how can I send the same notification to multiple users.
let suppose I have to send it to just one user.
then I can create a model of notification with
noti = models.TextField()
user= models.foreignkey
is_seen = models.bool
so this is just a sample
but the the problem is this how i can send this notification to selected multiple users
one important is that is_seen is compulsory for each user
I hope you will understand
I think it depends how this data will grow in future. Because if all of your notifications go to multiple users, you can have a Notification model with ManyToMany relation with User. Something like following
class Notification(models.Model):
message = models.TextField()
users = models.ManyToMany(User, through='UserNotification')
class UserNotification(model.Model):
user = models.ForeignKey(User)
notification = models.ForeignKey(Notification)
is_seen = models.BooleanField()
But other question is if you want to build something like the one you shared, that is also fine. I don't think so there's an issue of adding same message for multiple users. This is more flexible in my opinion as compared to M2M relation. You can extend this in future easily as your application will grow.
class Notification(model.Model):
message = models.TextField()
user = models.ForeignKey(User)
is_seen = models.BooleanField)
Another case can be if you want to have more relations and if there's need of adding more information related to notification. This gives more room for improvement in future in terms of storing information.
class Notification(model.Model):
message = models.TextField()
class UserNotification(model.Model):
user = models.ForeignKey(User)
notification = models.ForeignKey(Notification)
is_seen = models.BooleanField()
I'm working on a project using Python(3.7) and Django(2.5) in which I'm building an application something like a freelancing site, but I'm stuck at one point while implementing the delivery submission part.
A user will create a service to sell and then a buyer will order his service, after that the seller has to be done the agreed job and need to submit the work to the buyer as a delivery.
The delivery will be in the form of a file, can be a text file, image file, audio, video or a code file, the problem is that I don't know how I can implement this thing in Django, so a user can send a file to another user in a private manner, so only both of these users will be able to access that file.
Here's what I have so far, for order between buyer and seller:
class Order(models.Model):
status_choices = (
('Active', 'Active'),
('Completed', 'Completed'),
('Late', 'Late'),
('Short', 'Short'),
('Canceled', 'Canceled'),
('Submitted', 'Submitted')
)
gig = models.ForeignKey('Gig', on_delete=models.CASCADE)
seller = models.ForeignKey(User, on_delete=models.CASCADE, related_name='selling')
buyer = models.ForeignKey(User, on_delete=models.CASCADE, related_name='buying')
created_at = models.DateTimeField(auto_now=timezone.now())
charge_id = models.CharField(max_length=234)
days = models.IntegerField(blank=False)
status = models.CharField(max_length=255, choices=status_choices)
def __str__(self):
return f'{self.buyer} order from {self.seller}'
Any idea to implement the file sharing as delivery between two authenticated users?
Thanks in advance!
There is a lot of ways you could implement this.
You can simply add a field for users who access to file and let them download the file whenever they asked for download if they are authenticated and they are allowed to download that specific file.
With your model you can do something like this:
Giving gig field is your file you can create a slug or basically any link for a file and when user clicked on it you can get all the orders for that user, then check for the files that the access has been granted with these orders and if the file that users requests to download is one of them, simply let him download it.
You can let a user download a file using X-Sendfile which helps you check if users are allowed to download file or not.
Example here on stackoverflow
A sample code:
def download_file_view(request, file_id):
if not request.user:
# Redirect user or ...
if not request.user.is_authenticated:
# Redirect user or ...
# Check if this user has any orders with that file linked to it:
if Order.objects.filter(buyer=request.user, gig__pk=file_id).exists():
# User has bought this file already and the download should be allowed.
You can check for expiration date and all sorts of things there.
I'm creating a project using Django and I'm wondering how I can make objects distinct. Now I am creating message box part and what I want to do is show up user names who the user have been contacting. My current way is like this
models.py
class Message(models.Model):
''''''
text = models.TextField()
created = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='myself')
someone = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='someone')
views.py
def inbox(request):
'''See messages history'''
messages = Message.objects.filter(user=request.user).distinct('someone')
notification = Message.objects.filter(someone=request.user).distinct('user')
return render(request, 'campus_feed/inbox.html', {'messages': messages})
So what I want to do is list the users who is contacting me or I contacted and I don't want to show up the same name multiple times but I cannot come up with good way to filter them. Anyone who can give me tips?
If you want users, you should request users.
User.objects.filter(Q(myself__someone=request.user) | Q(someone__user=request.user))
This gives you all users who are either the "someone" in a message from the current user, or the "user" in a message to the current user. Since you are querying users directly, the is no possibility of duplicates.
First of all I would like to say that I am extremely new to Django and Python.
I am writing an application using Django 2.0. I have two inheritances to the user: the patient and responsible. A patient needs a user to exist and a responsible needs a patient to exist. A responsible may have several patients but one patient may only have one responsible.
However I am having the following problem: A patient can not be responsible for himself and currently this happens. How can I stop this from happening?
patient model:
class Patient(models.Model):
user = models.OneToOneField(User, related_name='patient',
on_delete=models.CASCADE, unique=True)
(...)
responsible model:
class Responsible(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,
limit_choices_to=Q(patient=None))
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
As you can see I'm using the "limit_choices_to" but it causes all users who are patients are not listed in the time I create a new responsible.
I managed to solve this as follows:
In my responsible model i added the following lines:
def clean(self):
if self.user == self.patient.user:
raise ValidationError(_("A patient can not be responsible for himself"))
So now it is no longer possible for a patient to be responsible for himself.
I'm having a little trouble with Token Authentication in the Django REST Framework. From the docs I know it is a matter of implementing the following:
from rest_framework.authtoken.models import Token
token = Token.objects.create(user=...)
print token.key
Now my question is, what exactly goes in the argument of Token.objects.create(user=...). The answer here helps and it says That will provide a Token model which is foreign-keyed to User. I'm not sure I understand this.
I have my own model of Users defined like so:
class Users(models.Model):
userid = models.IntegerField(primary_key=True)
username = models.CharField(max_length=255L, unique=True, blank=True)
email = models.CharField(max_length=255L, unique=True, blank=True)
password = models.CharField(max_length=64L, blank=True)
registeredip = models.CharField(max_length=255L, blank=True)
dob = models.DateField(null=True, blank=True)
firstname = models.CharField(max_length=255L, blank=True)
lastname = models.CharField(max_length=255L, blank=True)
joindate = models.DateTimeField()
class Meta:
db_table = 'Users'
How would I create a token for users that satisfy certain conditions in this case?
# View Pseudocode
from rest_framework.authtoken.models import Token
def token_request(request):
if user_requested_token() and token_request_is_warranted():
new_token = Token.objects.create(user=request.user) #What goes here?
Any help or leads to any more documentation/examples would really help me out here. Thank you!
to be sure: we are talking about Token authentication that is provided by django rest framework?
If so, this is very simple method, where there is a token (random 40 characters) that is used instead of username and password.
What is DRF delivering is a table (Token) where you need to create entries for your users, Token is referencing your user model (builtin or active custom model).
There are no tokens created initially, you need to create them.
There are several ways to create tokens, most common are:
create token for all users using signal handler (on create)
create tokens in background task (e.g. management tasks, runining from time to time and creates missing tokens)
have a special api endpoint, that will create token on-demand, with other user authentication method to authorize user
Basically that mean, that somewhere in your code you need to create Token instance, referencing your user instance.
Token(user=user).save()
Now, few remarks:
this implementation of tokens is rather rudimentary, e.g. you do not have any options to expire token, the only way is to regenerate token - this may be problematic if you want expiring sessions and/or multiple clients (remember - one token per user, not browser/session/device)
tokens are created using poor random function
tokens are stored in the database as plain text
there are multiple packages that deliver better and more secure token implementations, the most advanced are django-rest-framework-jwt and django-rest-knox (second one is simpler)
p.s.
python class names should be singular (Users->User)