pgtrigger to update another tables column with COUNT value - django

I'm trying to use triggers to track total reactions on a Video model. Whenever the Reaction model gets an INSERT or UPDATE request of reaction, it should update the video's reaction count with the value returned from the COUNT function. I just can't seem to understand how to make a simple update statement/function of the Video. Need Help.
Current code:
class Video(models.Model):
...
reaction_count = models.IntegerField(default=0, null=False, blank=False, unique=False)
class VideoReaction(models.Model):
class Meta:
db_table = "video_reaction"
triggers = [
pgtrigger.Trigger(
name = "VideoReaction_TRIGGER_count",
when = pgtrigger.After,
operation = pgtrigger.Insert | pgtrigger.Update,
func = "id_video__reaction_count = COUNT(reaction)"
)
]
id = models.CharField(max_length=10, primary_key=True, null=False, blank=False, unique=True)
id_user = models.ForeignKey(User, db_column="id_user", on_delete=models.CASCADE)
id_video = models.ForeignKey(Video, db_column="id_video", on_delete=models.CASCADE)
reaction = models.BooleanField(null=False, blank=False)
...

Related

How to add ArrayField in Django?

my models.py
class LiveClass_details(models.Model):
standard = models.ForeignKey(LiveClass, on_delete=models.CASCADE)
chapter_details = models.TextField(default='')
mentor_id = models.ForeignKey(Mentor, max_length=30, on_delete=models.CASCADE)
start_time = models.DateTimeField()
end_time = models.DateTimeField()
doubtClass = models.OneToOneField(DoubtClasses, on_delete=models.PROTECT, null=True, blank=True)
isDraft = models.BooleanField(default=True)
ratings = models.FloatField(default=0)
no_of_students_registered = models.IntegerField(default=0)
# registered_students = models.ManyToManyField(RegisteredNames, null=True, blank=True)
no_of_students_attended = models.IntegerField(default=0)
class Meta:
verbose_name_plural = 'LiveClass_details'
class RegisteredNames(models.Model):
name = models.CharField(max_length=100, unique=True)
liveclass_id = models.ForeignKey
I am creating a endpoint where when a user register himself his name will get added to registered_students , so i had made a registered students ManyToMany Field hoping it will get updated when a user is registered but then i understand that it will contain all the names that are present in the RegisteredNames Model meaning names registered across all the liveclasses but i want only the names that are registered for a particular liveclass in the field so i need a array like field which i think is not possible so please help me in improving my logic, how can i achieve it
The documentation and django tutorials are very good: https://docs.djangoproject.com/en/3.2/topics/db/models/ https://docs.djangoproject.com/en/3.2/intro/tutorial02/#creating-models
Your code is very close. You don’t need the many-to-many field, and you need to specify the type of the Foreign key relationship in the RegisteredNames. You can do this:
class LiveClass_details(models.Model):
standard = models.ForeignKey(LiveClass, on_delete=models.CASCADE)
chapter_details = models.TextField(default='')
mentor_id = models.ForeignKey(Mentor, max_length=30, on_delete=models.CASCADE)
start_time = models.DateTimeField()
end_time = models.DateTimeField()
doubtClass = models.OneToOneField(DoubtClasses, on_delete=models.PROTECT, null=True, blank=True)
isDraft = models.BooleanField(default=True)
ratings = models.FloatField(default=0)
no_of_students_attended = models.IntegerField(default=0)
class Meta:
verbose_name_plural = 'LiveClass_details'
class RegisteredNames(models.Model):
name = models.CharField(max_length=100, unique=True)
liveclass = models.ForeignKey(LiveClass_details, on_delete=Models.CASCADE)
Then, simply:
name = RegisteredNames.objects.create(name="Dhruv", liveclass_id=1)
To get all the registered names from a liveclass_details:
names = LiveClass_details.objects.get(id=1).registerednames_set.all()
num_reg = len(names)

How i can change my query to work in django?

I want to make a request from two tables at once, I registered dependencies in the class. But the request does not work for me. What is wrong with him?
views.py
def payments(request):
paymentsss = Transaction.objects.select_related("currency_id")[:5]
return render(request, "payments.html", {"paymentsss": paymentsss})
models.py
class Transaction(models.Model):
id = models.BigIntegerField(blank=True, null=False, primary_key=True)
currency_id = models.ForeignKey(Currency, null=True, on_delete=models.CASCADE)
deal_id = models.ForeignKey(Deal, null=True, related_name='deal', on_delete=models.CASCADE)
service_instance_id = models.ForeignKey(ServiceInstance, null=True, related_name='service_instance', on_delete=models.CASCADE)
payment_source_id = models.ForeignKey(PayerPaymentSource, null=True, related_name='payment_source', on_delete=models.CASCADE)
payment_date = models.DateTimeField(blank=True, null=True)
amount = models.IntegerField(blank=True, null=True)
status = models.CharField(max_length=255, blank=True, null=True)
context = models.TextField(blank=True, null=True) # This field type is a guess.
class Meta:
managed = False
db_table = '"processing"."transaction"'`enter code here`
And Currency for example:
class Currency(models.Model):
id = models.SmallIntegerField(blank=True, null=False, primary_key=True)
name = models.CharField(max_length=128, blank=True, null=True)
iso_name = models.CharField(max_length=3, blank=True, null=True)
minor_unit = models.SmallIntegerField(blank=True, null=True)
class Meta:
managed = False
db_table = '"processing"."currency"'
My Error:
I would be glad if there is an example of how to make a larger request. From 3-4 tables.
Change the db_table
class Meta:
managed = False
db_table = 'processing.transaction'
class Meta:
managed = False
db_table = 'processing.currency'
You need to change the column names for the foreign keys: e.g. currency = ForeignKey(...) and deal = ForeignKey(...).
The field is a reference to the object itself, not to the id of the object. You can see that behind the scenes, Django queries using currency_id_id which doesn't make sense.
If your column name is currency_id (in your database), then your field name should be currency.

How to Make Subquery's Value Change According to Parent Query's Conditions?

I am making a messenger app and tracking unread messages per chat room and per user. My models are like these:
class Room(models.Model):
id = models.BigAutoField(primary_key=True)
slug = models.SlugField(unique=True, max_length=255, allow_unicode=True)
name = models.CharField(max_length=100)
participants = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='participants')
def unread_messages_count(self, user):
last_checked_message_id = Subquery(models.Message.objects.filter(
room_listeners__receiver=user, room_listeners__room=self).values('id')[:1])
return self.messages.filter(id__gt=last_checked_message_id).count()
class Message(models.Model):
id = models.BigAutoField(primary_key=True)
slug = models.SlugField(unique=True, max_length=255, allow_unicode=True)
room = models.ForeignKey(Room, on_delete=models.CASCADE, related_name="messages")
sender = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.SET_NULL)
text = models.TextField(blank=True)
created_date = models.DateTimeField(auto_now_add=True, db_index=True)
class RoomListener(models.Model):
id = models.BigAutoField(primary_key=True)
receiver = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='room_listeners')
room = models.ForeignKey(Room, on_delete=models.CASCADE, related_name='room_listeners')
last_checked_message = models.ForeignKey(Message, default=Message.objects.first, on_delete=models.PROTECT,
related_name='room_listeners')
I could get a number of unread messages by writing unread_messages_count() in Room model. In addition, I want to get a number of unread messages per user. But I am confused with the way Subquery works. I want to do something like this:
class User(AbstractUser, RelationshipStatus):
id = models.BigAutoField(primary_key=True)
def unread_messages_count
last_checked_message_id = Subquery(models.Message.objects.filter(
room_listeners__receiver=self).values('id'))
return self.room_listeners.room.messages.filter(id__gt=last_checked_message_id).count()
But I know this is wrong... because last_checked_message_id does not change depending on parent query's status. It is a fixed value. How can I make a subquery's value change according to parent query's conditions?

Cannot query "ABC": Must be "Image" instance

I came across an error message within the model.py. I would appreciate if you guys could give me some assistance on this; the following are parts of the model.py:
class WorkJob(models.Model):
id = models.AutoField(primary_key=True)
share = models.ForeignKey(FShare, on_delete=models.PROTECT)
aftId = models.ForeignKey(AftId, null=True, blank=True, on_delete=models.PROTECT)
history = HistoricalRecords()
def __str__(self):
if self.aftId:
return self.aftId.aft
else:
return str('AFT-NA')
class Image(models.Model):
id = models.AutoField(primary_key=True)
imagingJob = models.OneToOneField(WorkJob, on_delete=models.PROTECT)
md5 = models.CharField(max_length=32, null=True, blank=True)
originalCopy = models.ForeignKey(Disc, related_name='originalCopy', null=True, blank=True, on_delete=models.PROTECT)
workingCopy = models.ForeignKey(Disc, related_name='workingCopy', null=True, blank=True, on_delete=models.PROTECT)
history = HistoricalRecords()
def __str__(self):
return self.imagingJob.fileShare.identifier
class Copy(models.Model):
id = models.AutoField(primary_key=True)
image = models.ForeignKey(Image, on_delete=models.PROTECT)
disc = models.ForeignKey(Disc, on_delete=models.PROTECT, related_name='copy')
history = HistoricalRecords()
def aftId(self):
return self.image.imagingJob.aftId.aft
the next class is the one that I have problems.
class TFI(models.Model):
id = models.AutoField(primary_key=True)
createDate = models.DateTimeField(auto_now_add=True, null=True)
status = models.IntegerField(choices=STATUS_OPTIONS, default=0)
history = HistoricalRecords()
def check_third(self):
if self.status == 5:
im = 0
third_imajob = WorkJob.objects.filter(share=self.share)
for ima in third_imajob:
if Copy.objects.filter(image__exact=ima.aftId).exists():
# some code blablabla
else:
break
The line that the error message says that it is problematic is:
if Copy.objects.filter(image__exact=ima.aftId).exists():
I am not certain why is it saying that the instance must be with Image. The line clearly is extracting from class Copy and WorkJob. I did see that that the Copy.image has a foreignkey reference to class Image but I am not certain how to troubleshoot this. Thanks in advance!
EDIT: following is also a part of the code and the above code has also been added.
class AftId(models.Model):
id = models.AutoField(unique=True, primary_key=True)
aft = models.CharField(unique=True, max_length=30)
assignedTo = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.PROTECT)
history = HistoricalRecords()
def __str__(self):
return self.aft
You are trying to compare some aftID instances and Image.
I can't see your aftId model but I guess it has an image foreign key field, so your query should be Copy.objects.filter(image__exact=ima.aftId.image).exists()

How do I get new Database changes since last login using Django and Python?

I need to get database changes for a user, but only the updates of the user since the last time they logged in. I will be passing in just an email. I have looked into session data but none of that looks very helpful to me. I am new to Python and Django and I have no idea where to start, any help would be appreciated. Here are my models:
class Device(models.Model):
serial = models.CharField(max_length=16, null=False, unique=True)
publickey = models.CharField(max_length=44, null=False)
def __str__(self):
return '%d: %s' % (self.id, self.serial)
class Pairing(models.Model):
device = models.OneToOneField(Device,on_delete=models.PROTECT,blank=False, null=False)
pairingcode = models.CharField(max_length=10, blank=False, null=False, unique=True)
def __str__(self):
return '%s: %s' % (self.device_id, self.pairingcode)
class UserDevice(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT,
null=False)
device = models.ForeignKey(Device, on_delete=models.PROTECT, null=False)
activation_date = models.DateTimeField(default=timezone.now, null=False)
friendly_name = models.CharField(max_length=20, null=True, blank=True)
is_owner = models.BooleanField(null=False, default=False)
is_admin = models.BooleanField(null=False, default=True)
is_alerts_enabled = models.BooleanField(null=False, default=True)
class Meta:
unique_together = ('user', 'device',)
def __str__(self):
return '%s => %s on %s' % (self.user.email, self.device.serial,
str(self.activation_date))
class Schedule(models.Model):
device = models.ForeignKey(Device, on_delete=models.PROTECT, null=False)
time = models.TimeField(null=False)
class Meta:
unique_together = ('device', 'time')
class PendingSchedule(models.Model):
device = models.ForeignKey(Device, on_delete=models.PROTECT, null=False)
user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.PROTECT, null=False)
time = models.TimeField(null=False)
class Meta:
unique_together = ('device', 'time')
class Tray(models.Model):
device = models.ForeignKey(Device, on_delete=models.PROTECT, null=False)
slot = models.IntegerField(null=False)
full = models.BooleanField(null=False)
time = models.DateTimeField(null=False)
class Meta:
unique_together = (('device', 'slot'), ('device', 'time'))
def __str__(self):
return 'Cup %s of %s %s' % (self.slot, str(self.device), "Full" if
self.full else "Empty")
class TrayStatus(models.Model):
device = models.ForeignKey(Device, on_delete=models.PROTECT, null=False)
slot = models.IntegerField(null=False)
reason = models.TextField(blank=False, null=False)
time = models.DateTimeField(null=False)
recorded = models.DateTimeField(auto_now_add=True, null=False)
expectedTime = models.DateTimeField(null=False)
class CheckIn(models.Model):
device = models.OneToOneField(Device, on_delete=models.PROTECT, null=False)
time = models.DateTimeField(null=False)
class UserProfile(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.PROTECT, null=False)
token = models.TextField(null=False, blank=True)
first_name = models.TextField(null=True, blank=True)
last_name = models.TextField(null=True, blank=True)
You have no last_modified fields on any of the relevant models, so start there:
class UserDevice(models.Model):
# other fields...
created = models.DateTimeField(autonow_add=True, db_index=True)
last_modified = models.DateTimeField(autonow=True, db_index=True)
These will get filled automatically and don't appear in model forms (editable is forced to False). For each of the models you want to track for changes, you need to add the last_modified field and optional created field.
Now you can get the objects based on User.last_login:
# Get our user object based on email
user = User.objects.get(email=email)
# Get list of modified devices
modified_devices = UserDevice.objects.filter(last_modified__gte=user.last_login)
# ... and trays
modified_trays = Tray.objects.filter(last_modified__gte=user.last_login)
A Device will not change if a Tray linked to it is changed, so neither will the last_modified field of the Device.
The created field is for you to show the difference between modification and creation if you wish to do so:
new_devices = UserDevice.objects.filter(created__gte=user.last_login)
The challenge you face, if how to handle ownership changes of the device. You will probably need to keep track of that separately.
There are several third-party packages that allow you to do what you need, for instance django audit log and django reversion.
You just need to pick the one that fits better your needs, both of them are very easy-to-integrate and use.