I have a model in which one of its fields is a postgres.fields.JSONField.
The Json that is going to be stored there is a variable dictionary of IDs referencing other items (possible relations/attributes) in the database.
Allow me to be more specific:
Basically, I'm trying to create a discount system, in which some discounts would apply to certain products. The JSON field contains the constraints to know what products can receive a discount.
For instance:
If I want to apply a 50% off to all products that fall under the "Beverages" category, and the "Beverages" category has id
5
in the database, the discount record would look like:discount_type='percent' discount='0.5' filter_by={ 'category': [5] }
If I wanted to apply a $20 off to all the products in the "Beverages" category AND that are manufactured by, let's say, CocaCola, the
filter_by
dictionary would look like:discount_type='fixed amount' discount='20' filter_by={ 'category': [5], 'manufacturer': [2] # Assuming coca-cola is the Manufacturer # with id==2 in the 'Manufacturers' # table of the database (NOTE: this is # needed since CocaCola manufactures # products besides "Beverages") }
If I wanted to apply a 25% off to a particular product (let's say to the product whose
id
is3
) the dictionary would look like:discount_type='percent' discount='0.25' filter_by={ 'id': [3] }
This idea seems to be flexible enough for my needs, and I'm happy (so far) with it.
Now, the problem comes on how to enter these values in the Django admin area for the Discount
model.
As expected, the filter_by
dictionary renders as as a text field that initially looks like this:
If I want to add fields to it, I need to write the exact JSON of what I want... Which means that if I want to apply a discount to the "Beverages" category, I need to go figure out which ID that category has in the database, and then manually type {"category": [5]}
, while being extremely careful when typing the '
, the :
, make sure that I don't miss a ]
or a [
...
Thaaaat... well, that is not very helpful...
Since I am only going to be filtering by a few fields (category
, manufacturer
, product
...) which are actually lists of IDs of other elements of the database, I would like to show a big MultiSelect box per thingy I can filter for, so I can see a user friendly list of all the elements I can filter by, select a few, and then, when I click on "Create discount", I would get the filter_by
dictionary (I'm still far from worrying about how to generate the dictionary, since I don't even know how to properly render the Admin form).
Something like what Django Admin automatically did for my Products' categories:
That is really, really, nice: One product can belong to several categories. For that, Django renders, side by side, two <select multiple
boxes, with the available categories, and the categories that the product already belongs to... I can add/remove categories through the stroke of a mouse... Really, really nice. But Django can do that because it knows that the categories
are a ManyToMany
relation in the Product
model.
class Product(models.Model):
parent = models.ForeignKey('self', null=True, blank=True)
manufacturer = models.ForeignKey('Manufacturer')
categories = models.ManyToManyField('Category',
related_name='products', blank=True)
The problem with the Discount
model is that there is no ManyToMany
field to category
, manufacturer
or product
. Poor Django doesn't know that a Discount
is related to all those things: It only knows there's a Json
field.
I would really like to be able to show a bunch of those <select>
in the Django Area listing all the possible filters (Category
, Manufacturer
, ID
...) that can be stored in the filter_by
dictionary (one entry with the double <select>
for Category
showing all the available categories in the database, one entry for Manufacturer
, showing all the available manufacturers... etcetera). But I really, really don't know how to do that.
I could bore you with a bunch of tries I've done, using Widgets
, trying to represent the JSON field through a form
, through forms.ModelMultipleChoiceField
(which by the way, seems to have been the closest thing to what I want, although still very far)... But I think that is kind of pointless, since nothing came close to what I wanted.
As usual, thank you for reading this huge email and thank you in advance. Any hint will be really appreciated, even just a you should take a look to "this"