Skip to content

Commit 228ed1d

Browse files
add user profile photo and make it editable (#125)
* add user profile photo and make it editable
1 parent 53ea98d commit 228ed1d

7 files changed

Lines changed: 87 additions & 31 deletions

File tree

home/admin.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from import_export.admin import ImportExportMixin, ImportExportModelAdmin
1313

1414
from home.models import (
15+
SDC,
1516
About,
1617
Allocation,
1718
AllocationForm,
@@ -25,6 +26,7 @@
2526
LeftLongRebate,
2627
LeftShortRebate,
2728
LongRebate,
29+
Menu,
2830
Period,
2931
Rebate,
3032
Rule,
@@ -34,8 +36,6 @@
3436
StudentBills,
3537
UnregisteredStudent,
3638
Update,
37-
Menu,
38-
SDC,
3939
)
4040
from home.utils.rebate_checker import max_days_rebate
4141

@@ -181,6 +181,7 @@ def generate_table(self, request, queryset):
181181
)
182182
caterer_bill.save()
183183

184+
184185
@admin.register(Menu)
185186
class MenuAdmin(admin.ModelAdmin):
186187
model = Menu
@@ -203,6 +204,7 @@ def reset_menu_urls(self, request, queryset):
203204
menu.sheet_url = ""
204205
menu.save()
205206

207+
206208
@admin.register(Form)
207209
class about_Admin(admin.ModelAdmin):
208210
model = Form
@@ -277,6 +279,7 @@ class about_Admin(ImportExportMixin, admin.ModelAdmin):
277279
None,
278280
{
279281
"fields": (
282+
"photo",
280283
"name",
281284
"email",
282285
"roll_no",
@@ -930,6 +933,7 @@ def name(self, obj):
930933
return obj.email.name if obj.email else ""
931934

932935
actions = ["export_as_csv", "fix_duplicates", "shift_caterer"]
936+
933937
def export_as_csv(self, request, queryset):
934938
"""
935939
Export action available in the admin page
@@ -1207,10 +1211,16 @@ class about_Admin(admin.ModelAdmin):
12071211
@admin.register(SDC)
12081212
class SDCAdmin(admin.ModelAdmin):
12091213
model = SDC
1210-
search_fields = ("student__name", "student__roll_no", "student__email", "position", "year")
1214+
search_fields = (
1215+
"student__name",
1216+
"student__roll_no",
1217+
"student__email",
1218+
"position",
1219+
"year",
1220+
)
12111221
list_display = ("student", "name", "position", "year")
12121222
list_filter = ("position", "year")
1213-
autocomplete_fields = ["student"]
1223+
autocomplete_fields = ["student"]
12141224

12151225
fieldsets = (
12161226
(
@@ -1234,13 +1244,14 @@ def export_as_csv(self, request, queryset):
12341244
Export action available in the admin page
12351245
"""
12361246
import csv
1247+
12371248
from django.http import HttpResponse
12381249

12391250
response = HttpResponse(content_type="text/csv")
12401251
response["Content-Disposition"] = 'attachment; filename="SDC.csv"'
12411252
writer = csv.writer(response)
12421253
writer.writerow(["Student", "Name", "Position", "Year"])
1243-
1254+
12441255
for obj in queryset:
12451256
writer.writerow([obj.student, obj.name, obj.position, obj.year])
12461257

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 5.0.8 on 2025-03-27 10:49
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('home', '0008_sdc'),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name='student',
15+
name='photo',
16+
field=models.ImageField(blank=True, default=None, help_text='This contains the photo of the Student', null=True, upload_to='photos/', verbose_name='Photo'),
17+
),
18+
]

home/models/students.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ class Student(models.Model):
88
Stores Student Details
99
"""
1010

11+
photo = models.ImageField(
12+
_("Photo"),
13+
upload_to="photos/",
14+
null=True,
15+
blank=True,
16+
default=None,
17+
help_text="This contains the photo of the Student",
18+
)
1119
name = models.CharField(
1220
_("Name of Student"),
1321
max_length=50,

home/views.py

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from django.utils.timezone import now
1212

1313
from home.models import (
14+
SDC,
1415
About,
1516
Allocation,
1617
AllocationForm,
@@ -21,6 +22,7 @@
2122
Form,
2223
LeftShortRebate,
2324
LongRebate,
25+
Menu,
2426
Period,
2527
Rebate,
2628
Rule,
@@ -30,8 +32,6 @@
3032
StudentBills,
3133
UnregisteredStudent,
3234
Update,
33-
Menu,
34-
SDC,
3535
)
3636

3737
from .utils.get_rebate_bills import get_rebate_bills
@@ -97,6 +97,7 @@ def rules(request):
9797
# context = {"caterer": caterer}
9898
# return render(request, "caterer.html", context)
9999

100+
100101
def menu(request):
101102
"""
102103
Display the menu along with caterer information on a single page.
@@ -105,15 +106,13 @@ def menu(request):
105106
caterers = Caterer.objects.filter(visible=True)
106107

107108
context = {
108-
"menus": list(menus),
109+
"menus": list(menus),
109110
"caterers": caterers,
110111
}
111112

112113
return render(request, "menu.html", context)
113114

114115

115-
116-
117116
def links(request):
118117
"""
119118
Display the Forms Page :model:`home.models.links`.
@@ -477,12 +476,25 @@ def profile(request):
477476
478477
:template:`home/profile.html`
479478
"""
480-
text = ""
481479
student = Student.objects.filter(email__iexact=str(request.user.email)).last()
480+
if request.method == "POST" and request.user.is_authenticated:
481+
if student:
482+
try:
483+
logger.debug(request.FILES)
484+
file = request.FILES["profile-picture"]
485+
student.photo = file
486+
student.save()
487+
except Exception as e:
488+
logger.error(e)
489+
if url_has_allowed_host_and_scheme(request.path, allowed_hosts=None):
490+
return redirect(request.path)
491+
else:
492+
return redirect("/")
493+
text = ""
482494
socialaccount_obj = SocialAccount.objects.filter(
483495
provider="google", user_id=request.user.id
484496
)
485-
picture = "not available"
497+
picture = student.photo.url if student.photo else None
486498
allocation: Allocation | None = Allocation.objects.filter(email=student).last()
487499
show_allocated_enabled = False
488500
if allocation and allocation.period:
@@ -501,12 +513,10 @@ def profile(request):
501513
"Jain": "Yes" if allocation.jain else "No",
502514
}
503515
try:
504-
if socialaccount_obj:
516+
if not picture and socialaccount_obj:
505517
picture = socialaccount_obj[0].extra_data["picture"]
506-
else:
507-
picture = "not available"
508518
except (IndexError, KeyError):
509-
picture = "not available"
519+
logger.error("No picture found")
510520
semesters = Semester.objects.all()
511521
context = {
512522
"text": text,
@@ -545,13 +555,12 @@ def rebate_data(request):
545555
return JsonResponse(rebate_data)
546556

547557

548-
549558
def sdc_list(request):
550559
"""
551560
View to display the list of SDC members categorized by year and position.
552561
"""
553-
positions = ["Head", "Advisory", "Member"]
554-
years = [2024, 2025]
562+
positions = ["Head", "Advisory", "Member"]
563+
years = [2024, 2025]
555564
sdc_members = SDC.objects.all()
556565

557566
context = {
@@ -560,4 +569,3 @@ def sdc_list(request):
560569
"sdc_members": sdc_members,
561570
}
562571
return render(request, "sdc.html", context)
563-

qrscan/templates/mess_card.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
<img
1717
class="img-fluid rounded-4"
1818
src="{{ picture }}"
19-
alt="User Image"
2019
alt="profile photo"
20+
style="width: 120px; height: 120px; object-fit: cover;"
2121
/>
2222
</div>
2323
<h6 class="card-subtitle mt-2">{{ student.name }}</h6>

qrscan/views.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
from django.utils import timezone
2-
from django.shortcuts import render
1+
from allauth.socialaccount.models import SocialAccount
32
from django.contrib.auth.decorators import login_required
3+
from django.shortcuts import render
4+
from django.utils import timezone
5+
46
from home.models import Student
7+
58
from .models import MessCard
6-
from allauth.socialaccount.models import SocialAccount
9+
710

811
@login_required
912
def mess_card(request):
@@ -21,20 +24,22 @@ def mess_card(request):
2124
)
2225
allocation = student.allocation_set.last()
2326

24-
if(not allocation):
27+
if not allocation:
2528
raise ValueError("Allocation not found!")
2629
mess_card, _ = MessCard.objects.get_or_create(student=student)
2730

28-
if(not mess_card.allocation):
31+
if not mess_card.allocation:
2932
setattr(mess_card, "allocation", allocation)
3033
mess_card.save()
31-
elif((mess_card.allocation != allocation) and mess_card.allocation.period.end_date < timezone.localtime().date()):
34+
elif (
35+
mess_card.allocation != allocation
36+
) and mess_card.allocation.period.end_date < timezone.localtime().date():
3237
setattr(mess_card, "allocation", allocation)
3338
mess_card.save()
3439

35-
picture = "not available"
40+
picture = student.photo.url if student.photo else None
3641
try:
37-
if socialaccount_obj:
42+
if not picture and socialaccount_obj.exists():
3843
picture = socialaccount_obj[0].extra_data["picture"]
3944
except (IndexError, KeyError):
4045
picture = "not available"
@@ -47,4 +52,3 @@ def mess_card(request):
4752
}
4853

4954
return render(request, "mess_card.html", context=context)
50-

templates/profile.html

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,14 @@
1313
<div class="card mt-4">
1414
<div class="card-body" style="padding-left: 5%;">
1515
<h5 class="card-title">Your Profile</h5>
16-
<img class="img-fluid rounded-4" src="{{ picture }}" alt="User Image">
16+
<img class="img-fluid rounded-4" src="{{ picture }}" alt="User Image" style="width: 90px; height: 90px; object-fit: cover;">
17+
<form action="" method="POST" enctype="multipart/form-data" style="margin-top: 10px;">
18+
{% csrf_token %}
19+
<div style="display: flex; align-items: center; gap: 10px;">
20+
<input type="file" name="profile-picture" id="profile-picture" class="form-control" accept="image/*" required>
21+
<button type="submit" class="btn btn-primary" style="background-color: rgb(30, 55, 146)">Upload</button>
22+
</div>
23+
</form>
1724
<h6 class="card-subtitle mt-2">{{ student.name }}</h6>
1825
<span class="card-text">Roll Number: {{ student.roll_no }}</span><br>
1926
<span class="card-text">Email: {{ user.email }}</span><br>

0 commit comments

Comments
 (0)