Name and related_purchase validation for non-games
This commit is contained in:
		| @ -72,6 +72,10 @@ textarea:disabled { | ||||
|   @apply dark:bg-slate-700 dark:text-slate-400; | ||||
| } | ||||
|  | ||||
| .errorlist { | ||||
|   @apply mt-4 mb-1 pl-3 py-2 bg-red-600 text-slate-200 w-[300px]; | ||||
| } | ||||
|  | ||||
| @media screen and (min-width: 768px) { | ||||
|   form input, | ||||
|   select, | ||||
|  | ||||
| @ -58,7 +58,8 @@ class PurchaseForm(forms.ModelForm): | ||||
|     related_purchase = forms.ModelChoiceField( | ||||
|         queryset=Purchase.objects.filter(type=Purchase.GAME).order_by( | ||||
|             "edition__sort_name" | ||||
|         ) | ||||
|         ), | ||||
|         required=False, | ||||
|     ) | ||||
|  | ||||
|     class Meta: | ||||
| @ -82,6 +83,27 @@ class PurchaseForm(forms.ModelForm): | ||||
|             "name", | ||||
|         ] | ||||
|  | ||||
|     def clean(self): | ||||
|         cleaned_data = super().clean() | ||||
|         purchase_type = cleaned_data.get("type") | ||||
|         related_purchase = cleaned_data.get("related_purchase") | ||||
|         name = cleaned_data.get("name") | ||||
|  | ||||
|         # Set the type on the instance to use get_type_display() | ||||
|         # This is safe because we're not saving the instance. | ||||
|         self.instance.type = purchase_type | ||||
|  | ||||
|         if purchase_type != Purchase.GAME: | ||||
|             type_display = self.instance.get_type_display() | ||||
|             if not related_purchase: | ||||
|                 self.add_error( | ||||
|                     "related_purchase", | ||||
|                     f"{type_display} must have a related purchase.", | ||||
|                 ) | ||||
|             if not name: | ||||
|                 self.add_error("name", f"{type_display} must have a name.") | ||||
|         return cleaned_data | ||||
|  | ||||
|  | ||||
| class IncludeNameSelect(forms.Select): | ||||
|     def create_option(self, name, value, *args, **kwargs): | ||||
|  | ||||
							
								
								
									
										18
									
								
								games/migrations/0030_alter_purchase_name.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								games/migrations/0030_alter_purchase_name.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| # Generated by Django 4.1.5 on 2023-11-15 12:04 | ||||
|  | ||||
| from django.db import migrations, models | ||||
|  | ||||
|  | ||||
| class Migration(migrations.Migration): | ||||
|  | ||||
|     dependencies = [ | ||||
|         ("games", "0029_alter_purchase_related_purchase"), | ||||
|     ] | ||||
|  | ||||
|     operations = [ | ||||
|         migrations.AlterField( | ||||
|             model_name="purchase", | ||||
|             name="name", | ||||
|             field=models.CharField(blank=True, default="", max_length=255, null=True), | ||||
|         ), | ||||
|     ] | ||||
| @ -2,6 +2,7 @@ from common.time import format_duration | ||||
| from datetime import datetime, timedelta | ||||
| from django.conf import settings | ||||
| from django.db import models | ||||
| from django.core.exceptions import ValidationError | ||||
| from django.db.models import F, Manager, Sum | ||||
| from zoneinfo import ZoneInfo | ||||
|  | ||||
| @ -118,9 +119,7 @@ class Purchase(models.Model): | ||||
|         max_length=2, choices=OWNERSHIP_TYPES, default=DIGITAL | ||||
|     ) | ||||
|     type = models.CharField(max_length=255, choices=TYPES, default=GAME) | ||||
|     name = models.CharField( | ||||
|         max_length=255, default="Unknown Name", null=True, blank=True | ||||
|     ) | ||||
|     name = models.CharField(max_length=255, default="", null=True, blank=True) | ||||
|     related_purchase = models.ForeignKey( | ||||
|         "Purchase", | ||||
|         on_delete=models.SET_NULL, | ||||
| @ -147,6 +146,10 @@ class Purchase(models.Model): | ||||
|     def save(self, *args, **kwargs): | ||||
|         if self.type == Purchase.GAME: | ||||
|             self.name = "" | ||||
|         elif self.type != Purchase.GAME and not self.related_purchase: | ||||
|             raise ValidationError( | ||||
|                 f"{self.get_type_display()} must have a related purchase." | ||||
|             ) | ||||
|         super().save(*args, **kwargs) | ||||
|  | ||||
|  | ||||
|  | ||||
| @ -1231,6 +1231,19 @@ textarea:disabled) { | ||||
|   color: rgb(148 163 184 / var(--tw-text-opacity)); | ||||
| } | ||||
|  | ||||
| .errorlist { | ||||
|   margin-top: 1rem; | ||||
|   margin-bottom: 0.25rem; | ||||
|   width: 300px; | ||||
|   --tw-bg-opacity: 1; | ||||
|   background-color: rgb(220 38 38 / var(--tw-bg-opacity)); | ||||
|   padding-top: 0.5rem; | ||||
|   padding-bottom: 0.5rem; | ||||
|   padding-left: 0.75rem; | ||||
|   --tw-text-opacity: 1; | ||||
|   color: rgb(226 232 240 / var(--tw-text-opacity)); | ||||
| } | ||||
|  | ||||
| @media screen and (min-width: 768px) { | ||||
|   form input, | ||||
|   select, | ||||
|  | ||||
		Reference in New Issue
	
	Block a user