Skip to content

Commit 38c8f29

Browse files
Fixed major issues with delete.cascade
New relationship: User <--one to one <--- Profile <---one to one -- profile picture <---- one to one --- upload record Had to change it this way to ensure upload record is deleted when user is deleted
1 parent 53eca41 commit 38c8f29

File tree

7 files changed

+42
-48
lines changed

7 files changed

+42
-48
lines changed

backend/apps/search/serializers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ class Meta:
1616

1717
def get_image_url(self, result_data):
1818
# Ensure that the profile and profile_picture exist before accessing them
19-
if hasattr(result_data, "profile") and hasattr(result_data.profile, "profile_picture") and hasattr(result_data.profile.profile_picture, "upload"):
20-
return UploadRecord.objects.build_url(result_data.profile.profile_picture.upload)
19+
if hasattr(result_data, "profile") and hasattr(result_data.profile, "profile_picture") and hasattr(result_data.profile.profile_picture, "upload_record"):
20+
return UploadRecord.objects.build_url(result_data.profile.profile_picture.upload_record)
2121
return None # Return None if there's no profile picture
2222

2323
def get_subjects(self, result_data):

backend/apps/uploads/managers.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@
55
from cloudinary import CloudinaryImage
66

77
class ProfilePictureManager(models.Manager):
8-
def create(self, profile, upload_record):
8+
def create(self, profile):
99
# Create a new UploadRecord instance with the provided data
1010
profile_picture = self.model(
11-
profile=profile,
12-
upload=upload_record
11+
profile=profile
1312
)
1413
# Save the instance to the database
1514
profile_picture.save()
@@ -27,6 +26,10 @@ def delete_upload(self, cloudinary_public_id):
2726
result = cloudinary.uploader.destroy(cloudinary_public_id, invalidate = True)
2827
return result
2928

29+
def add_profile_picture(self, upload_record, profile_picture):
30+
upload_record.profile_picture = profile_picture
31+
upload_record.save(update_fields=['profile_picture'])
32+
3033
def create(self, upload_data):
3134
# Replace 'Z' with '+00:00' for compatibility with fromisoformat
3235
compatible_created_at = upload_data['created_at'].replace('Z', '+00:00')

backend/apps/uploads/migrations/0008_alter_uploadrecord_profile.py

Lines changed: 0 additions & 20 deletions
This file was deleted.

backend/apps/uploads/migrations/0009_remove_uploadrecord_profile_profilepicture_profile.py renamed to backend/apps/uploads/migrations/0008_remove_profilepicture_upload_and_more.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Generated by Django 5.1.6 on 2025-04-10 23:20
1+
# Generated by Django 5.1.6 on 2025-04-11 07:35
22

33
import django.db.models.deletion
44
from django.db import migrations, models
@@ -7,11 +7,15 @@
77
class Migration(migrations.Migration):
88

99
dependencies = [
10-
('uploads', '0008_alter_uploadrecord_profile'),
10+
('uploads', '0007_alter_uploadrecord_profile'),
1111
('users', '0009_alter_tutorprofile_rating'),
1212
]
1313

1414
operations = [
15+
migrations.RemoveField(
16+
model_name='profilepicture',
17+
name='upload',
18+
),
1519
migrations.RemoveField(
1620
model_name='uploadrecord',
1721
name='profile',
@@ -21,4 +25,9 @@ class Migration(migrations.Migration):
2125
name='profile',
2226
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='profile_picture', to='users.profile'),
2327
),
28+
migrations.AddField(
29+
model_name='uploadrecord',
30+
name='profile_picture',
31+
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='upload_record', to='uploads.profilepicture'),
32+
),
2433
]

backend/apps/uploads/models.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,21 @@
55
from cloudinary.models import CloudinaryField
66
from django.core.exceptions import ValidationError
77

8+
# A model that acts as a container for the profile picture of user
9+
class ProfilePicture(models.Model):
10+
profile = models.OneToOneField(Profile, on_delete=models.CASCADE, related_name = "profile_picture", null = True) #changed
11+
# Link the custom manager to the model
12+
objects = ProfilePictureManager()
13+
14+
def save(self, *args, **kwargs):
15+
# Always validate before saving
16+
self.full_clean()
17+
super().save(*args, **kwargs)
18+
19+
def __str__(self):
20+
first_name = self.profile.user.first_name
21+
return f"{first_name}'s profile picture"
22+
823
# https://blog.nonstopio.com/well-handling-of-cloudinary-with-python-drf-api-28271575e21f
924
# Model that acts a container for all upload related information
1025
class UploadRecord(models.Model):
@@ -23,25 +38,10 @@ class UploadRecord(models.Model):
2338

2439
# default = 1 for first user (for now)
2540
description = models.TextField(default="", blank=True, null=False)
41+
profile_picture = models.OneToOneField(ProfilePicture, on_delete=models.CASCADE, related_name='upload_record', null = True)
2642

2743
# Link the custom manager to the model
2844
objects = UploadRecordManager()
2945

3046
def __str__(self):
31-
return self.file_name
32-
33-
# A model that acts as a container for the profile picture of user
34-
class ProfilePicture(models.Model):
35-
profile = models.OneToOneField(Profile, on_delete=models.CASCADE, related_name = "profile_picture", null = True) #changed
36-
upload = models.OneToOneField(UploadRecord, on_delete=models.CASCADE)
37-
38-
# Link the custom manager to the model
39-
objects = ProfilePictureManager()
40-
41-
def save(self, *args, **kwargs):
42-
# Always validate before saving
43-
self.full_clean()
44-
super().save(*args, **kwargs)
45-
46-
def __str__(self):
47-
return self.upload.file_name
47+
return self.file_name

backend/apps/users/managers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,6 @@ def get_result_data(self, search_results):
8787
'hourly_rate',
8888
'state',
8989
'city',
90-
'profile__profile_picture__upload' #changed
90+
'profile__profile_picture__upload_record' #changed
9191
)
9292
return search_results

backend/apps/users/views.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ def register_profile(request):
6464
last_name = request.data["lastName"]
6565
password = request.data["password"]
6666
# TODO: replace "1" with "role" once that is handled by the frontend
67-
# role = request.data["role"] # Get the selected role
67+
68+
#role = request.data["role"] # Get the selected role
6869
role = 3
6970
# Create user
7071
user = User.objects.create_user(
@@ -82,12 +83,13 @@ def register_profile(request):
8283

8384
# Store optional profile picture
8485
if image:
86+
# Use the manager method to create and save profile picture
87+
profile_picture = ProfilePicture.objects.create(profile)
8588
# Use the manager method to handle file upload
8689
upload_data = UploadRecord.objects.upload(image)
8790
# Use manager method to create and save metadata
8891
upload_record = UploadRecord.objects.create(upload_data)
89-
# Use the manager method to create and save profile picture
90-
ProfilePicture.objects.create(profile, upload_record)
92+
UploadRecord.objects.add_profile_picture(upload_record, profile_picture)
9193

9294
# Create Tutor Profile if role is Tutor
9395
if int(profile.role) == Profile.TUTOR:

0 commit comments

Comments
 (0)