Accessing the time where a field has been updated (Django models) - python

I need to create a system where the user have to change his password every "x" number of days. I managed to achieve this by saving a UTC timestamp representing the time when the user has created/modified his password.
My question is, instead of saving the timestamp in the database, is it possible to get a timestamp representing the time when the field has been changed through some of django's built-in functions? This way I could access when was the last time the user has updated his password without having to add a dedicated field in the model to save the timestamp in it.

No, there is no field that shows you which field updated in which time, you should implement it your self
you should use set_password everywhere to manage update password time
password_updated_at = models.DateTimeField(_('password updated at'))
def set_password(self, raw_password):
r = super(User, self).set_password(raw_password=raw_password)
self.password_updated_at = timezone.now()
self.save()
return r
def is_password_updated_at_expired(self):
duration = (timezone.now() - self.password_updated_at).total_seconds()
return duration > settings.PASSWORD_UPDATE_EXPIRE_TIME, duration

Related

Django Execute Function When DateTimeField Equals Current Date and Time

So I have implemented a subscription product to my website.
When they start the subscription, the current date and time is stored into the database. When they cancel the subscription, a period of time is added onto the start date so I know when to cancel the subscription and change some values elsewhere.
This is fine, I know how to use Django and Python, however, I am stuck on the last bit of, when the cancel date comes around in the future.
Question: How do I execute a function when the cancel date (in the db) is equal to current date and time.
Below is an simple example of the model I will be using:
models.py
class Subscriptions(models.Model):
subscription_id = models.AutoField(primary_key=True)
start_date = model.DateTimeField(auto_now_add=True)
cancel_date = model.DateTimeField(auto_now_add=False)
person_id = model.ForeignKey('Persons')
class Persons(models.Model):
person_id = models.AutoField(primary_key=True)
value_to_change = models.BooleanField()
Before you ask I have not attempted any code as I couldn't find a solution for this problem. Thanks <3
Without Celery, installed on UNIX system providing CRON (cron doku: e.g. https://www.computerhope.com/unix/ucrontab.htm):
write a Command https://docs.djangoproject.com/en/2.1/howto/custom-management-commands/ that fetches the objects for which cancel_date is in the past and that have not been cancelled yet. (If you do the lookup with datetime.now() (a very precise lookup with the finest granularity), you would have to be more than lucky to find anything.)
You should add another date field that tells you when the system actually ran the cancellation, and you should allow both the cancel_date and cancelled_date to be null.
# models.py
class Subscriptions(models.Model):
subscription_id = models.AutoField(primary_key=True)
start_date = model.DateTimeField(auto_now_add=True)
cancel_date = model.DateTimeField(auto_now_add=False, null=True)
cancelled_date = model.DateTimeField(null=True)
person_id = model.ForeignKey('Persons')
# under myapp/management/command/cancellation.py
class CancellationCommand(BaseCommand):
def handle(self, *args, **options):
now = datetime.now()
to_cancel_qs = Subscriptions.objects.exclude(
cancelled_date__isnull=False).filter(
cancel_date__lte=now)
for sub in to_cancel_qs.all():
# do your cancelling
sub.cancelled_date = now
sub.save()
# or: to_cancel_qs.update(cancelled_date=now)
install a cron job that runs this command via ./manage.py your_command at a regular time

Django. Python. How to get current user's activity log?

I need to pass the current user's entire activity log to an html page, but it seems I cannot find any helpful solution regarding the same.
Is it possible? If yes, please direct me in the right way?
Thanks in advance!
Update:
I found a solution making use of a get() call to django's LogEntry model, but I am clueless as to what shall be the appropriate parameters for doing the same.
Yet another UPDATE:
I am looking for a way to access the activity log of a particular user from the django's log entries WITHOUT saving it to any database
Take a look below listed.....Hope it will help::
lets example::
Create Two Field in Models:
last_activity_ip = models.IPAddressField()
last_activity_date = models.DateTimeField(default = datetime(1960, 1, 1))
user = models.OneToOneField(User, primary_key=True)
Since the User and UserActivity models are now related one-to-one we can now type:
Run the Query Like this:
a = User.objects.get(username__exact='mpcabd')
print a.useractivity.last_activity_ip
b = UserActivity.objects.get(user=a)
print b.user.username
** To track the activity use this **
activity = None
try:
activity = request.user.useractivity
except:
activity = UserActivity()
activity.user = request.user
activity.last_activity_date = datetime.now()
activity.last_activity_ip = request.META['REMOTE_ADDR']
activity.save()
return
activity.last_activity_date = datetime.now()
activity.last_activity_ip = request.META['REMOTE_ADDR']
activity.save()
This question don't has a short answer, you can use sentry project by side of main django project. below link can helping you:
https://sentry.readthedocs.org/en/latest/

Django values get year from DateTimeField

I have a page where users can search for other users. The search is called with AJAX and the results are returned using JSON with the following code:
return HttpResponse(json.dumps({'users': list(users.values('first_name', 'last_name', 'gender', 'zip_code__city', 'zip_code__state')) }))
I have the users birthday stored in the model with birthday = models.DateTimeField(). I am trying to return just the year of the birthday with the results, but I am having trouble. Returning the whole date would work as well as I can always parse out the year later.
When I try just adding 'birthday' to the arguments in values, I get an error that it is not JSON serializable. I also tried 'birthday__year', but that returned an error that there was no such thing as 'year'.
How do I get the DateTimeField into the list?
Build a models.py method to return the year:
models.py
from django.db import models
class MyModel(models.Model):
birthday = models.DateTimeField()
def get_year(self):
return self.birthday.year
Then call this function from your views.py
You can't set a dynamic default like this, nor should you really need to store it in a database
Just make it a property (maybe even cached_property)
#property
def age(self):
return date.today().year - self.DOB.year

How to prevent DateField record addition for past days in Django

If I have a DateField() field in a model in Django, how can I prevent adding entries for dates older than today?
I can do it on the views.py level, but it would still be exploitable from the Django admin site.
To make matters worse, I have a design decision to have separate DateField() and TimeField() fields in the same model. Can I prevent addition into older (date+time) than the current time? It doesn't make sense to book a past flight, even if it was just an hour old. My problem, though, is that I have to have separate DateField() and TimeField(); not a single DateTimeField().
Maybe try the Model.clean() method. This will raise ValidationErrors in the right places (will show form errors in admin instead of 500).
The clean method will allow the expiry date to be saved in the past only if it is an existing record and the expiry has not changed.
from datetime import datetime
from django.core.exceptions import ValidationError
class MyModel(models.Model)
expires = models.DateTimeField()
def __init__(self, *args, **kwargs):
super(Game, self).__init__(*args, **kwargs)
self.__old_expires = self.expires
def clean(self):
" Make sure expiry time cannot be in the past "
if (not self.id or self.__old_expires != self.expires)
and self.expires <= datetime.now():
raise ValidationError('MyModel entries cannot expire in the past.')
Docs: https://docs.djangoproject.com/en/dev/ref/models/instances/#django.db.models.Model.clean

Django - how to implement lock data

I have a database table. Some database items can be edited by a user, but only one user can edit the table content at a time, and if after 2 hours the user hasn't finished editing, other users can edit the table. How can I do this?
The table is like this:
class NodeRevision(BaseModel, NodeContent):
node = models.ForeignKey(Node, related_name='revisions')
summary = models.CharField(max_length=300)
revision = models.PositiveIntegerField()
revised_at = models.DateTimeField(default=datetime.datetime.now)
suggested = models.BooleanField(default=False)
suggest_status = models.CharField(max_length=16,default="")
Should I add a BooleanField to it, such as editing_locked=models.BooleanField(default=False) ? Or something else? And how could I implement the 2 hour check?
You'd need a locked_at time field and locked_by field.
Every time somebody loads an edit page, update the database with the locked_at and locked_by information.
To implement the 2 hour restriction, I'd just have the results calculated only when a user asks for permission (as opposed to polling / updating models). When a user tries to edit a model, have it check locked_by/locked_at and return a Boolean whether it's editable by the user or not.
def can_edit(self, user):
if user == self.locked_by:
return True
elif self.locked_at and (self.locked_at - datetime.datetime.now()).total_seconds > 2*60*60:
return True
return False

Categories