Reputation: 1632
I'm trying to mimic eBay's multi listing function. Basically, eBay allows users to specify two variations of their choice, for example size and color
. Each variation will have different data, for example:
Color: red, green
Size: 12, 9
Then it gets a bit confusing for example:
quantity for color red, size 12: 15
quantity for color red, size 9: 12
quantity for color green, size 12: 20
quantity for color green, size 9: 59
The user will have to specify the quantity for each mixture of variation, first variation takes precedence.
To complicate matters Name and Color are examples only. They can be different properties.
How can I apply this in database level? Currently I'm just producing a list like so:
[color blue,size = 12,Quantity = 24,Price = 299,size = 23,Quantity = 43,Price = 298]
Planning to store the list as string in a field, and using JSON to rebuild it.
The problem is, unnecessary processing will be required for every request. For example if Quantity decreases, then I can't just edit a field, I would have to use flags to find right Quantity from the list (unnecessary processing), and make appropriate changes to the list, and then store it again.
Looking for an alternative approach? I can't create fields for variations because they're specified by the user.
Looking for some direction.
My current Table looks like:
class Auction(models.Model):
auction_id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=50)
description = models.TextField(validators=[MaxLengthValidator(1000)])
price = models.PositiveSmallIntegerField(default = 0)
bid = models.PositiveSmallIntegerField(default = 0)
image = models.ImageField(upload_to = 'img/', default = 'img/None/no-img.jpg')
......
# stores multi listing list/dict
multi_listing = models.CharField(max_length=200)
flag = models.BooleanField(default=False)
slug = models.SlugField(unique=True, default = (randint(0,1000000)))
def __unicode__(self):
return self.name
Upvotes: 2
Views: 364
Reputation: 53734
Planning to store the list as string in a field, and using JSON to rebuild it.
If you take this approach at all, you should be using a database that has a native JSON field. Of the databases that are officially supported by django only Mysql and Postgresql has it. Unfortunately the mysql version isn't fully supported by Django and you will need third party libraries.
Of the two, postgresql has the richer set of functionality and provides better indexing options. In fact, JSONB in postgresql is good enough to rival Mongodb.
If JSON is your choice, it has to be Postgresql JSONB. Nothing else will come even close. With JSONB there is no need to rebuild anything and you don't need to fetch the complete field just to update one of the items in the JSON dictionary.
But the data structure you have chosen is wrong. It should be more like
[{'color': 'blue' , 'size': 12, 'Quantity': '24', 'Price': 299},
{'size': 23, 'Quantity': 43, 'Price' :298}]
But oops, that's still an Array
Tip: Arrays are not sets; searching for specific array elements can be a sign of database misdesign. Consider using a separate table with a row for each item that would be an array element. This will be easier to search, and is likely to scale better for a large number of elements.
Nevertheless, a JSON array can be more effective than an ArrayField
This is the more traditional way of doing this. And probably better than using JSON, definitely better if you are not using postgresl. Your model might look like this:
class Auction(models.Model):
auction_id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=50)
description = models.TextField(validators=[MaxLengthValidator(1000)])
bid = models.PositiveSmallIntegerField(default = 0)
image = models.ImageField(upload_to = 'img/', default = 'img/None/no-img.jpg')
flag = models.BooleanField(default=False)
slug = models.SlugField(unique=True, default = (randint(0,1000000)))
def __unicode__(self):
return self.name
class Pricing(models.Model):
# stores multi listing list/dict
price = models.PositiveSmallIntegerField(default = 0)
color = models.CharField(max_length=12)
size = models.IntegerField(max_length=200)
auction = models.ForeignKey(Auction)
because 'color' and 'size' is defined by user, it could be name something else. For example they may choose a different variation instead of 'size' and 'color', they might choose 'material' and 'color', so then how would you name the field?
This explaination tilts the scales in favor of JSON. However there is still two other alternatives that could possibly be considered. The first is redis. Not to use redis as a complete replacement for your RBMS but to store the user defined properties in redis.
The second alternative is to completey switch to a nosql database such as mongo. Unfortunately though Django doesn't play very well with nosql.
Upvotes: 2