Skip to content

Commit 9af135f

Browse files
Merge pull request #393 from MySecondLanguage/added-image-field-in-variant
Added image field in variant
2 parents c461dfd + 741a9e5 commit 9af135f

File tree

4 files changed

+117
-2
lines changed

4 files changed

+117
-2
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Generated by Django 4.2.11 on 2025-02-20 09:50
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("order", "0037_alter_order_options"),
10+
]
11+
12+
operations = [
13+
migrations.AlterField(
14+
model_name="order",
15+
name="reservation_status",
16+
field=models.CharField(
17+
choices=[
18+
("RESERVED", "Reserved"),
19+
("RELEASED", "Released"),
20+
("FAILED", "Failed"),
21+
("NOT_RESERVED", "Not Reserved"),
22+
("DISPATCHED", "Dispatched"),
23+
],
24+
default="NOT_RESERVED",
25+
max_length=20,
26+
),
27+
),
28+
]

nxtbn/product/admin_types.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,51 @@
77
from nxtbn.product.admin_filters import CategoryFilter, CategoryTranslationFilter, CollectionFilter, CollectionTranslationFilter, ProductFilter, ProductTagsFilter, ProductTranslationFilter, TagsTranslationFilter
88

99

10+
class ProductVariantNonPaginatedType(DjangoObjectType):
11+
db_id = graphene.Int(source="id")
12+
display_name = graphene.String()
13+
humanize_price = graphene.String()
14+
variant_thumbnail = graphene.String()
15+
16+
def resolve_humanize_price(self, info):
17+
return self.humanize_total_price()
18+
19+
def resolve_variant_thumbnail(self, info):
20+
return self.variant_thumbnail(info.context)
21+
class Meta:
22+
model = ProductVariant
23+
fields = (
24+
'name',
25+
'sku',
26+
'track_inventory',
27+
'product',
28+
'price',
29+
'variant_thumbnail',
30+
'alias',
31+
)
32+
33+
def resolve_display_name(self, info):
34+
if self.name:
35+
return self.name
36+
37+
if self.sku:
38+
return self.product.name + " - " + self.sku
39+
40+
return self.product.name + " - " + self.sku
41+
42+
1043

1144
class ProductGraphType(DjangoObjectType):
1245
description_html = graphene.String()
1346
db_id = graphene.Int(source="id")
47+
all_variants = graphene.List(ProductVariantNonPaginatedType)
48+
product_thumbnail = graphene.String()
49+
50+
def resolve_all_variants(self, info):
51+
return self.variants.all()
52+
53+
def resolve_product_thumbnail(self, info):
54+
return self.product_thumbnail(info.context)
1455
class Meta:
1556
model = Product
1657
fields = (
@@ -30,8 +71,11 @@ class Meta:
3071
'tags',
3172
'tax_class',
3273
'related_to',
74+
'variants',
3375
'meta_title',
3476
'meta_description',
77+
'all_variants',
78+
'product_thumbnail',
3579
)
3680

3781
interfaces = (relay.Node,)
@@ -105,13 +149,19 @@ class Meta:
105149
interfaces = (relay.Node,)
106150
filter_fields = ('name',)
107151

152+
153+
108154
class ProductVariantAdminType(DjangoObjectType):
109155
db_id = graphene.Int(source="id")
110156
display_name = graphene.String()
111157
humanize_price = graphene.String()
158+
variant_thumbnail = graphene.String()
112159

113160
def resolve_humanize_price(self, info):
114161
return self.humanize_total_price()
162+
163+
def resolve_variant_thumbnail(self, info):
164+
return self.variant_thumbnail()
115165
class Meta:
116166
model = ProductVariant
117167
fields = (
@@ -120,6 +170,7 @@ class Meta:
120170
'track_inventory',
121171
'product',
122172
'price',
173+
'variant_thumbnail',
123174
)
124175
interfaces = (relay.Node,)
125176
filter_fields = ('name', 'sku', 'track_inventory', 'product', 'price')
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Generated by Django 4.2.11 on 2025-02-20 09:50
2+
3+
from django.db import migrations, models
4+
import django.db.models.deletion
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
("filemanager", "0002_initial"),
11+
("product", "0018_alter_productvariant_currency"),
12+
]
13+
14+
operations = [
15+
migrations.AddField(
16+
model_name="productvariant",
17+
name="image",
18+
field=models.ForeignKey(
19+
blank=True,
20+
null=True,
21+
on_delete=django.db.models.deletion.SET_NULL,
22+
to="filemanager.image",
23+
),
24+
),
25+
]

nxtbn/product/models.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ class ProductVariant(MonetaryMixin, AbstractUUIDModel, AbstractMetadata, models.
287287

288288
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='variants')
289289
name = models.CharField(max_length=255, blank=True, null=True)
290+
image = models.ForeignKey(Image, null=True, blank=True, on_delete=models.SET_NULL)
290291

291292
compare_at_price = models.DecimalField(max_digits=12, decimal_places=3, validators=[MinValueValidator(Decimal('0.01'))], null=True, blank=True) # TO DO: Handle this field which is still not used in the project.
292293

@@ -369,12 +370,22 @@ def humanize_total_price(self, locale='en_US'):
369370

370371
def variant_thumbnail(self, request):
371372
"""
372-
Returns the URL of the first image associated with the variant.
373+
Returns the URL of the first image associated with the product variant.
373374
If no image is available, returns None.
374375
"""
376+
if self.image and hasattr(self.image, 'image') and self.image.image:
377+
image_url = self.image.image.url
378+
full_url = request.build_absolute_uri(image_url)
379+
return full_url
375380

376381
if self.product.images.exists():
377-
return self.product.product_thumbnail(request)
382+
first_image = self.product.images.first()
383+
if first_image and hasattr(first_image, 'image') and first_image.image:
384+
image_url = first_image.image.url
385+
full_url = request.build_absolute_uri(image_url)
386+
return
387+
return None
388+
378389

379390
def get_valid_stock(self): # stocks that available for sell
380391
stock_data = self.warehouse_stocks.aggregate(

0 commit comments

Comments
 (0)