From d8b540ccd4b4adcd4544f377e2e13d44a5463069 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sat, 24 Jan 2026 07:55:38 +0000 Subject: [PATCH] changing image size in truck reg --- core/__pycache__/admin.cpython-311.pyc | Bin 10415 -> 13973 bytes core/__pycache__/models.cpython-311.pyc | Bin 31999 -> 34424 bytes core/admin.py | 61 ++++++++++++++++- ...lter_truck_driver_license_back_and_more.py | 33 +++++++++ ...iver_license_back_and_more.cpython-311.pyc | Bin 0 -> 1449 bytes core/models.py | 63 ++++++++++++++++-- core/templates/core/truck_register.html | 43 ++++++++++-- 7 files changed, 187 insertions(+), 13 deletions(-) create mode 100644 core/migrations/0022_alter_truck_driver_license_back_and_more.py create mode 100644 core/migrations/__pycache__/0022_alter_truck_driver_license_back_and_more.cpython-311.pyc diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index 93e60857a2a397b6bc0ecfdd456a2fb3d1957db3..1b97a8240b6d371eb5bc0bd5cddf670307c42b7d 100644 GIT binary patch delta 4956 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 delta 1726 zcmZuwO>7%Q6y90?#cMl`^Z&PY96L4}+xb&lpg^nUz1yyzl$o zyqS4kO|QRP`Gw0RaBSpe^kjX*N@XK?Yb88UVONAyRoZiQ<$A1^aEe`Vq{OuMte0>+ zr;_tN$e2XCbBR-2Y}E!uzQg7(F)M$F_DV*$cZv2LOAit4RgCeJnOLC2;QlyN&*y~W z*4VE!cnn3f$TLVVE5uA`O3#Iiaj?W?r;fStX};VV0Aojdt|V7b~D<1aI@$i7^y z2jpsJjzHOAiYh_)+N|Y6mKj2v@QL+TtA|~JCPHsT4P3E(Od9ghierRagh~6iuo>10N-z)MxnG)pEr%rY0; zQ_~rh%5qLqX(pal=@4vG)mIf9NllJtvvlf$s+^Im(AnZ0paJHfL4*#3!7}u+i6$~w z-2EQZj4uw~uYGp$^!@5Xi$nO8oP*%$Itl~gxOEKe<8V_vFO1?8;Yn!pM#!k4nfFF2 zP$LmK1{>Z%K}HqAb71yGhzy_EqLB4kAnvOp=V015C`_OP;RU$s3z3QZwl6@)5Y+km z$O$;*?;ttI_##FKZ6a^OFQKQ7Ttc@~jVIoa6H^&oozdwKhAeVg)#DT&U$Ro%gH9tXA-n^} z!XdH%YPgfUmR}AZCr5J_pF>z+P;kj|A{E!Pgqljp@-0%T23xMbR7wh^2&cdxD=SL!^iI_#=O@s>!G;HGCW9Hzy zXxNJ9XI=Ox8t5t5OKDYIqeh`ukpndDDQOjh2q`!cE09(8jDyk3Y+bNSQAMRRgL5H4 z)wr%Ia$LW~(=XA3amh?C!@FIt3Tqfan1{c*B4iCb-6New7N@2r^yE}V)@QToe@^-p z+D-HuG-lvRcVivO={mw~gbjow-040kjzR1J5z8jG3bHYD;e=k&%lkER^FfJe7stIfx z(E^_~e<+?48e;bL%2$-g!q&G8z Kkk<~i^Zx?0B&0|H diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index 2e8ff7de93a651815a818970fc3c70ddf4c3a50b..4bdc403cf2cacb3f72566aee4fde7a324bc60eec 100644 GIT binary patch delta 9205 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 N{bAIg(b-{U{|{;PxugI9 delta 7040 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', _('Expired')) - days = obj.days_until_expiry() + # Profile model might not have days_until_expiry, let's check + # Based on models.py read earlier, it doesn't have it. + # It has a commented out section that seems to be a start of it. + # I'll use inline calculation + if not obj.subscription_expiry: + return format_html('{}', _('No Expiry')) + + days = (obj.subscription_expiry - timezone.now().date()).days if days <= 7: return format_html('{} ({} {})', _('Expiring soon'), days, _('days')) @@ -48,9 +56,56 @@ class ProfileAdmin(admin.ModelAdmin): @admin.register(Truck) class TruckAdmin(admin.ModelAdmin): - list_display = ('display_truck_type', 'model', 'plate_no', 'owner', 'load_capacity') + list_display = ('display_truck_type', 'model', 'plate_no', 'owner', 'load_capacity', 'is_approved') search_fields = ('plate_no', 'owner__username', 'model') list_filter = ('truck_type_link', 'is_approved') + readonly_fields = ('truck_picture_preview', 'registration_front_preview', 'registration_back_preview', 'driver_license_front_preview', 'driver_license_back_preview') + + def truck_picture_preview(self, obj): + if obj.truck_picture: + return format_html('', obj.truck_picture.url) + return "-" + truck_picture_preview.short_description = _("Truck Picture Preview") + + def _file_preview(self, field): + if not field: + return "-" + url = field.url + ext = os.path.splitext(field.name)[1].lower() + if ext in ['.jpg', '.jpeg', '.png', '.webp', '.gif']: + return format_html('', url, url) + elif ext == '.pdf': + return format_html('
{}
', url, _("View PDF Document")) + return format_html('{}', url, _("View File")) + + def registration_front_preview(self, obj): + return self._file_preview(obj.registration_front) + registration_front_preview.short_description = _("Registration Front Preview") + + def registration_back_preview(self, obj): + return self._file_preview(obj.registration_back) + registration_back_preview.short_description = _("Registration Back Preview") + + def driver_license_front_preview(self, obj): + return self._file_preview(obj.driver_license_front) + driver_license_front_preview.short_description = _("Driver License Front Preview") + + def driver_license_back_preview(self, obj): + return self._file_preview(obj.driver_license_back) + driver_license_back_preview.short_description = _("Driver License Back Preview") + + fieldsets = ( + (None, {'fields': ('owner', 'truck_type_link', 'is_approved')}), + (_('Details (EN)'), {'fields': ('truck_type', 'model', 'load_capacity', 'color', 'year', 'plate_no', 'registration_expiry_date')}), + (_('Details (AR)'), {'fields': ('truck_type_ar', 'model_ar', 'load_capacity_ar', 'color_ar')}), + (_('Pictures & Documents'), {'fields': ( + 'truck_picture', 'truck_picture_preview', + 'registration_front', 'registration_front_preview', + 'registration_back', 'registration_back_preview', + 'driver_license_front', 'driver_license_front_preview', + 'driver_license_back', 'driver_license_back_preview' + )}), + ) @admin.register(Shipment) class ShipmentAdmin(admin.ModelAdmin): @@ -134,4 +189,4 @@ class HomeSectionAdmin(admin.ModelAdmin): list_display = ('title', 'section_type', 'order', 'is_active') list_editable = ('order', 'is_active') list_filter = ('section_type', 'is_active', 'background_color') - search_fields = ('title', 'title_ar', 'subtitle', 'subtitle_ar', 'content', 'content_ar') + search_fields = ('title', 'title_ar', 'subtitle', 'subtitle_ar', 'content', 'content_ar') \ No newline at end of file diff --git a/core/migrations/0022_alter_truck_driver_license_back_and_more.py b/core/migrations/0022_alter_truck_driver_license_back_and_more.py new file mode 100644 index 0000000..a8680e1 --- /dev/null +++ b/core/migrations/0022_alter_truck_driver_license_back_and_more.py @@ -0,0 +1,33 @@ +# Generated by Django 5.2.7 on 2026-01-24 07:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0021_appsetting_thawani_enabled'), + ] + + operations = [ + migrations.AlterField( + model_name='truck', + name='driver_license_back', + field=models.FileField(blank=True, null=True, upload_to='docs/', verbose_name='Driver License (Back Face)'), + ), + migrations.AlterField( + model_name='truck', + name='driver_license_front', + field=models.FileField(blank=True, null=True, upload_to='docs/', verbose_name='Driver License (Front Face)'), + ), + migrations.AlterField( + model_name='truck', + name='registration_back', + field=models.FileField(blank=True, null=True, upload_to='docs/', verbose_name='Registration (Back Face)'), + ), + migrations.AlterField( + model_name='truck', + name='registration_front', + field=models.FileField(blank=True, null=True, upload_to='docs/', verbose_name='Registration (Front Face)'), + ), + ] diff --git a/core/migrations/__pycache__/0022_alter_truck_driver_license_back_and_more.cpython-311.pyc b/core/migrations/__pycache__/0022_alter_truck_driver_license_back_and_more.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..662d902066e9ef48e767b8a753794c3e4065f2b7 GIT binary patch literal 1449 zcmb7DPgB!C6yKytXd+cu>-Y!3${^AULB@jz#u*)^%s9wF9S^;%X?7`T)1+>aw)Vuq zgGWyK4NwOTegr>4ndyPqt0!+|;Ka$@lq!S{4!gQmxDU< zqARvf3A?wju=ogB^?E?U(DBMB+_0LK=OE%)C6{2PhBUIP>^i1SgHYr;Ht_<2N|s%H z(^j!>2WI=ua;(g)_LaH0=UkgBST@P$6{eP4%d0ZQi(HrKQQh?|j6$D{a=enyu{^6r z@+m$AqVuuDjrkc<*B#X5?T;H zMa3L4z2LYcmYLz#$;ln~4i3eL9=|g;{2DQ%Qsjk^Nm|5?LZ6yVpH_o9FRm#%X#Tr9 zChz4UvP29NcMT;9Cz^&V5A&2MnXiAK8V?f_!2~M5U7LS*PXqenUP{hto2xwo=u@AJ zZhCV6=G6Z9>^_{{n(e~rZ`mKqKUX@%Mh74ge=df+QRtCLNm{*xG}w zE^J-wIFob?J22XVQ5QxRJ3dG{MjhDLgN-h1BpvVHfZFB@vFYTXE^B;#bzHH$vOkYY zaTnvx^(%K*n8mhJoI6f0^+(|;&2f7^t|;?1h*^)&u9smeC!X MIS`7YA=)_ZADBjh)&Kwi literal 0 HcmV?d00001 diff --git a/core/models.py b/core/models.py index 3384816..d8c35ff 100644 --- a/core/models.py +++ b/core/models.py @@ -5,8 +5,12 @@ from django.dispatch import receiver from django.utils.translation import gettext_lazy as _ from django.utils.translation import get_language from django.utils import timezone +from django.core.files import File import random import string +import os +from io import BytesIO +from PIL import Image class Country(models.Model): name = models.CharField(_('Country Name'), max_length=100) @@ -127,10 +131,10 @@ class Truck(models.Model): # Pictures truck_picture = models.ImageField(_('Truck Picture'), upload_to='trucks/', blank=True, null=True) - registration_front = models.ImageField(_('Registration (Front Face)'), upload_to='docs/', blank=True, null=True) - registration_back = models.ImageField(_('Registration (Back Face)'), upload_to='docs/', blank=True, null=True) - driver_license_front = models.ImageField(_('Driver License (Front Face)'), upload_to='docs/', blank=True, null=True) - driver_license_back = models.ImageField(_('Driver License (Back Face)'), upload_to='docs/', blank=True, null=True) + registration_front = models.FileField(_('Registration (Front Face)'), upload_to='docs/', blank=True, null=True) + registration_back = models.FileField(_('Registration (Back Face)'), upload_to='docs/', blank=True, null=True) + driver_license_front = models.FileField(_('Driver License (Front Face)'), upload_to='docs/', blank=True, null=True) + driver_license_back = models.FileField(_('Driver License (Back Face)'), upload_to='docs/', blank=True, null=True) is_approved = models.BooleanField(_('Is Approved'), default=False) created_at = models.DateTimeField(auto_now_add=True) @@ -166,6 +170,55 @@ class Truck(models.Model): return self.color_ar return self.color + def save(self, *args, **kwargs): + # Compress images + if self.truck_picture: + self.truck_picture = self.compress_image(self.truck_picture) + + # For docs, compress only if they are images + if self.registration_front: + self.registration_front = self.compress_image(self.registration_front) + if self.registration_back: + self.registration_back = self.compress_image(self.registration_back) + if self.driver_license_front: + self.driver_license_front = self.compress_image(self.driver_license_front) + if self.driver_license_back: + self.driver_license_back = self.compress_image(self.driver_license_back) + + super().save(*args, **kwargs) + + def compress_image(self, image_field): + if not image_field: + return image_field + + try: + # Check file extension + ext = os.path.splitext(image_field.name)[1].lower() + if ext not in ['.jpg', '.jpeg', '.png', '.webp']: + return image_field + + img = Image.open(image_field) + + # If already small enough, don't compress (optional, but good for performance) + # if image_field.size < 300 * 1024: return image_field + + if img.mode != 'RGB': + img = img.convert('RGB') + + # Resize if too large + max_size = (1200, 1200) + img.thumbnail(max_size, Image.LANCZOS) + + output = BytesIO() + img.save(output, format='JPEG', quality=70, optimize=True) + output.seek(0) + + new_name = os.path.splitext(image_field.name)[0] + '.jpg' + return File(output, name=new_name) + except Exception as e: + # Not an image or other error, return as is + return image_field + class Shipment(models.Model): STATUS_CHOICES = ( ('OPEN', _('Open for Bids')), @@ -421,4 +474,4 @@ class Transaction(models.Model): super().save(*args, **kwargs) def __str__(self): - return f"{self.receipt_number} - {self.user.username} ({self.amount})" + return f"{self.receipt_number} - {self.user.username} ({self.amount})" \ No newline at end of file diff --git a/core/templates/core/truck_register.html b/core/templates/core/truck_register.html index 5530196..3e8f942 100644 --- a/core/templates/core/truck_register.html +++ b/core/templates/core/truck_register.html @@ -125,6 +125,7 @@
{% trans "Documents & Photos" %}
+

{% trans "Photos will be automatically resized for better performance. PDF files are accepted for documents." %}

@@ -144,7 +145,15 @@ {% if truck.driver_license_front %}
- + {% with ext=truck.driver_license_front.name|lower %} + {% if ".pdf" in ext %} + + {% trans "View PDF" %} + + {% else %} + + {% endif %} + {% endwith %}
{% endif %} {{ form.driver_license_front }} @@ -154,7 +163,15 @@ {% if truck.driver_license_back %}
- + {% with ext=truck.driver_license_back.name|lower %} + {% if ".pdf" in ext %} + + {% trans "View PDF" %} + + {% else %} + + {% endif %} + {% endwith %}
{% endif %} {{ form.driver_license_back }} @@ -167,7 +184,15 @@ {% if truck.registration_front %}
- + {% with ext=truck.registration_front.name|lower %} + {% if ".pdf" in ext %} + + {% trans "View PDF" %} + + {% else %} + + {% endif %} + {% endwith %}
{% endif %} {{ form.registration_front }} @@ -177,7 +202,15 @@ {% if truck.registration_back %}
- + {% with ext=truck.registration_back.name|lower %} + {% if ".pdf" in ext %} + + {% trans "View PDF" %} + + {% else %} + + {% endif %} + {% endwith %}
{% endif %} {{ form.registration_back }} @@ -198,4 +231,4 @@
-{% endblock %} \ No newline at end of file +{% endblock %}