Django: send notifications at user based on database change - python

I have 3 database tables:
users (stores info about users e.g. email, name)
metadata (stores data)
activity (stores changes made to users/metadata tables)
I want to achieve the following:
to store any change into the activity table (e.g. new user is created, a user updates the metadata table)
to send notifications to users whenever a change into the users/metadata tables happens.
What are the libraries/method that I could use in order to achieve the desired functionalities? Thank you!

in addition to django signals which wes already recommended, you can also check out django channels + django activity stream

Assuming you are making use of the Django Models, I would use the Django Signals for saving the data to a second model: "MetaData" according to your question.
Specifically the post_save signal:
https://docs.djangoproject.com/en/4.0/ref/signals/#django.db.models.signals.post_save
#receiver(post_save, sender=User)
def post_save_user(sender, instance, created, **kwargs):
# Save Stuff To Metadata Model.
meta = MetaData(user=instance)
meta.save()
You need to import those signals inside your models.py placed at the bottom of the file.
As for the notifications, I would follow #kristina's advice and use Django Channels.
Just remind that your application needs to be ASGI (Async). So your application server needs to be one like uvicorn, daphne, hypercorn, etc.

Related

Flask - User to Profile Relationships

I'm working with Flask-restplus and I am at a point where I would like to associate each User in my user model to a type of profile, where each user can be associated with one or many profile types. I'm wondering how you guys would go about this. So far, here's what I'm thinking/planning to do. NOTE: I'm not very experienced in web development, so there's a chance I don't know the best way to accomplish this.
Step 1: Create a one-to-many (clients need to also be employees, see below) field (profile_types) relating to a static table that just lists all possible profile options. EXAMPLE:
PK PROFILE TYPE
1 provider
2 employee
3 client
.....
The idea here is to track different information and allow for different views/endpoints for users who are tied to certain profile types. Example, employees would provide a valid login authentication and be directed to page A while a client would be directed to page B, etc. We're also planning on collecting different data points within each profile model.
So an instance of a user might look like this, user1.profile == [client, employee'].
NOTE: This is more important for data collection (ie age of employee, start date, etc) than it is for creating directives based on permissions.
Step 2: Upon creating the new user, a signal fires off the creation of a profile based on the profile_types supplied to the user instance. I've used signals with django in the past, is there a signal library for Flask?
Step 3: An empty profile instance(s) now exists for that user. It will be up to a superuser to upload data in bulk or manually fill out profile information.
Is this a sensible way to go about this? My other though is to create a bunch of Boolean fields in the User model is_provider, is_employee, is_client, etc. All fields that are True get assigned a profile instance. What's the best way to go about this?
Thanks everyone!
Seeing that are you try to validate multiple profile types, you may use
if user.profile_type in ['employee', 'client']
Now, if you want to add an super user I think you can use this
if user.profile_type in ['employee', 'client'] and user.profile_type == 'superuser'
Now, you relationship is more like 'many-to-many', because you are saying that an client also needs to be an employee, if you mean that some endpoints needs to be accessible for employees and clients, then you need to use a 'many-to-one' relationship (an Stackoverflow question which explains what is that)
For your instances, there is Flask Marshmallow, which has an amazing compatibility with Flask SQLAlchemy if you are using an database, but Flask Marshmallow can work alone.

Signal for the default user registration of django

I would like after creating a user to run a method and create content in other tables of this user that was created but I do not have a user model since I use the default model for the record.
Problems:
-I do not have user model (use the default model)
-I want to choose the newly created user to create the other records in other tables
-I'm not an expert in django (I'm just trying to solve a problem in another area and this would help)
I like the way to do it in this post:
https://simpleisbetterthancomplex.com/tutorial/2016/07/28/how-to-create-django-signals.html
Creating a signals.py to control the signals
You can attach a Django signal to the Django default User models with no problems, for example:
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
The instance argument is the new user recently created into the database, so you can use it as a reference to to add the new tables.
As well, you can put this function in your models.py as well, not necessarily need to create a signals.py

how to log model inserts,updates and deletes in django

how to log model inserts,updates and deletes?
I am not using django admin,in my app there are multiple tables
i just want to records only which model or table name, field name,previous value,who edited,and what time
to log table?
Who edited (my app uses SSO,it should pick up remote user automatically)
can you please suggest any built in function or module in django to records this kind of logs ,if possible can you plz add few lines of django code or any ref links?
Thanks in advance
You can try this:
from django.db.models.signals import post_save
def logging_function(sender, **kwargs):
# do your logging
post_save.connect(logging_function)
Python has a logger http://docs.python.org/library/logging.html What's wrong with that?
You can, also, add an event table to your Django models and write to that table.
For real fun, you can create a decorator which writes to that table.
You can search, too. You'll find things like this: http://djangosnippets.org/snippets/2111/

Should I place custom registration code in Views, Models or Managers?

I'm rolling my own custom registration module in Django based on django.contrib.auth. My registration module will have some extra functionality and help me reduce my dependency on other django modules that I'm currently using like django-registration and django-emailchange. I've run into a what-the-best-way-to-do-it problem here.
Note: All the user accounts are based on django.contrib.auth.models.User model.
When the user clicks the "sign-up" link, the request gets passed to my view named register. I have a custom form which has four fields — username, email, password1 and password2. The form is based on django.forms.Form. The form provides basic validation e.g. passoword1 and password2 are the email; the email/username do not exist.
When the data gets POSTed back to my register view, I call the is_valid() method of the form, after which, I create a new user by calling a Manager method called create_user() in django.contrib.auth.models.UserManager. I need to add more custom functionality at this point like sending activation emails, etc. As a best-practice method, where should this logic be? Should this be in a method of the User Model? Should it be where it is currently - the Manager of the Model? Or should this be placed into a custom save() method of my sign-up Form?
Thanks.
Different from Chris, I believe on the philosophy of fat models, thin views.
The more code you can factor inside models, the more reusable your codebase is. Views concerns should be simply managing the request/response cycle and dealing with GET/POST parameters.
In this case, sending activation emails is related to the event of creating a new User. For those cases, Django already provides this abstraction through signals.
http://docs.djangoproject.com/en/1.2/topics/signals/#topics-signals
So, as an example, you can have in your models.py:
from django.contrib.models import User
from django.db.models.signals import post_save
def send_welcome_email(self):
# Reusable email sending code
User.send_welcome_email = send_welcome_email
def welcome_emails(sender, instance, created, **kwargs):
if created:
instance.send_welcome_email() # `instance` is User
post_save.connect(welcome_emails, sender=User)
Similarly, you can have this for when a User is deleted, or everytime a User is saved, etc. Signals are a good abstraction to event-driven tasks.
My recommendation is to not re-solve a problem that django-registration solves quite nicely. It has a pluggable backend system that lets you customize it as much or as little as needed.

Set and use flags against a users profile model in Django

I have a simple webapp in Django for an iPhone app.
I want to prompt the user to review our product, but just once. I then don't want to show that prompt again.
So would the best practise way of implementing this to be to add a new entry to the user profile model with a bolean field: "reviewed" - and then set that flag when the user completes the action?
I would then check for that entry in my template and display or not, the prompt.
I've not yet worked with database models, extended the user model, or saved to custom DB fields, so any thoughts or examples on this would be most welcome. I'm a little nervous as my site has live users and I won't want to break the user tables.
If you are using MySQL or PostgreSQL, you can do some ALTER TABLE without loosing any data.
In Django, it is quite easy to add a profile for the user.
Make sure, to create the profile if it doesn't exist :
try:
profile = request.user.get_profile()
except UserProfile.DoesNotExist:
# If DoesNotExists, Create an empty one
profile = UserProfile(user=request.user)
profile.save()
More information here :
http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users
http://www.djangobook.com/en/1.0/chapter12/#cn222
There are a variety of ways to do this. I suggest the following:
Django has a messaging framework, built by design to show messages to users only once when the software creates them. Whenever X is created/modified/deleted etc, you can add the message to the user via User.message_set.create(message='Whatever you like'). This will be shown to the user once. This relies on django sessions, which I assume you're using since you're relying on the built-in user model. These messages are stored in auth_message.
HTH

Categories

Resources