Django ORM modeling issue


I have a need to model a series of conditions as in the following in a model

Here’s the model that contains that conditions

class Goal(models.Model):
	achieved = models.BooleanField(default=False)
	visible = models.BooleanField(default=False)
	conditions = ?????

conditions are the conditions to be met to achieve the goal.

Conditions are combination of different items combined with ANDs or ORs
These are the possible items for the condition.

  1. Other Goal object. A goal can be achieved based on other goal or many other goals. This can be a list of other goals
  2. Price value(A goal can be achieved when you purchased an item which is worth given value - the price). It can be IntegerField rather than object
  3. Duration value(A goal can be achieved when you played with a toy for certain amount of time). This can be Integer as well, no tan object
  4. Store object(A goal can be achieved when you bought toys from certain stores).
    1) A goal can be achieved when you bought toys from Store A and Store B
    2) A goal can be achieved when you bought a toy in one of these stores - Store A, Store B or Store C

I am not sure what is the best way to model this condition in Django ORM
Any help would be appreciated.

@KenWhitesell , do you have any suggestion?

If you’ve seen enough of my initial responses, you may have noticed that my first response typically includes a question or two. You might then guess that this response is going to contains more questions than suggestions - and you would be right! :grinning:

My first question concerns what you are needing to do with these conditions.

I’d guess that you’d be looking to return some value from a view based upon whether or not the conditions have been met? (Or is that the purpose of the achieved attribute?

Are you also looking to do something like filter queries based upon the conditions? (Not the result of the condition, but the condition itself - e.g. return a list of all Goals with a condition including a Price value condition.)

Are you needing a visual representation of the conditions to be displayed in a view?

How frequently are these going to be evaluated as to whether or not they’ve been achieved?

Making a distinction for the moment between an “aggregate goal” (a goal consisting of satisfying a set of “specific goals”) and a “specific goal” (a goal being evaluated using criteria external to the goals themselves, such as a Price value goal) - How are you planning to implement the evaluation of a “specific goal”?

For clarity and verification of understanding -
Is #4 just a restatement of having “specific goals” of “Buy from Store A”, “Buy from Store B”, “Buy from Store C”, and then using the combinations allowed from the premise (“Conditions … combined with ANDs and/or ORs”) such that 4.1 could be expressed as “Buy from Store A” AND “Buy from Store B” and 4.2 could be expressed as “Buy from Store A” OR “Buy from Store B” OR “Buy from Store C”?

Is there a need to provide for an unbounded nesting of conditions?
(e.g. Having a condition: “Generic X” AND “Generic Y”, where “Generic X” is “Buy from Store A” OR “Buy from Store B” and “Generic Y” is “Buy from Store C” OR “Buy from Store D”)

Finally (for now?)

Is there a relationship between these Goals, and Users or some other entity?

1 Like

I need to check against those conditions and if the conditions are met, I will add a badge(unique icon) to the user.
I will need to visualize the conditions as well.
Not sure how frequently are these going to be evaluated but not so often.
For primitive values, I just need to compare those values to corresponding objects.
For objects like goals, I need to check out user’s profile if user has already achieved the goals.
#4 is just one type of condition, we just need to check against if the user bought from that specified store.

There’s a need for unbounded nesting of goals.
So Goal A can depend on Goal B and Goal B can depend on Goal C.
So user achieve Goal A by this order - Goal C, Goal B and then Goal A.

If user achieves goals, then they are added to user profile and in UI, they are appeared as badges(icons) which are another fields of goals.

Hope this answers to your questions

We’re close - however, I’m still not clear on how you want to implement this:

For example let’s say that Goal D is “Buy from Store A”. How are you planning to implement that test? Are you looking to implement a method for every possible goal? Or is that one of the open questions associated with your original post?

The app will send log data to API and I will check that log to see if it is bought from Store A

Of course, I need to filter out what Goal objects I need to check against.

But I’d like to skip that for now, at it is brain hurting now. :slightly_smiling_face:

Hope you are doing well!
So I was thinking of storing all the rules as JSON, stringify that and put that string into models.TextField.
How does it sound?
Do you have any better suggestion?

First, I’d always recommend a JsonField over a TextField for storing JSON data.
But I’m still not clear on how you’re planning to implement your goals and your different evaluation processes. It’s easy to say “oh, I’ll just toss everything I need into a JSON field” - but what are you going to do with it?
Do you have a solid schema identified for your Json? What are you planning on storing in it? How will that translate to an actual evaluation process?
I think the database schema design will be easier once you’re clear on the specifics of the implementation of the processes involved.

I also think database schema design will be easier without any doubt.
Then the preconditions field should be ManyToManyField for sure.
I don’t see any problem with Other goal objects.
But how should I related to Price or Duration or Store object.
Price is just a value and I don’t think I need to save all those Prices on database. The same for Duration.
They are just values, specified values.
It’s not meaningful to save all of them in database for this precondition.
That’s what I think.
And also we have to save AND, OR operators along with each condition.
Hope this explains what I am thinking.

I still look forward your inputs

So I’m still thinking you’re one step ahead of where you should be.

I believe you’ve still got a “business logic” issue to address before you can properly design your schema.

I’d be breaking this larger issue down into two smaller steps. First, I would address how I’d be handling the primitives - the specific goals that are evaluated individually using actual data. Only after having a working implementation of specific goal evaluation would I begin to address the abstract goals containing combinations of specific goals and other abstract goals.

For the primitives - precisely how are you going to implement these tests? Ignore all the combinations, conditions, etc for the moment.
Pick one goal, e.g. “Buy from Store A”. What is your code going to look like to implement the evaluation of that goal? How does / will that evaluation differ for that from “Buy from Store B”? Or from “Item purchased is worth a given value”?

As I see it, those goal implementations are different from your “abstract” goals which are some combination of other “abstract” goals and “specific” goals.

So at a minimum, I’d be looking at two tables - one for each type of goal. For the purposes of this discussion, I’ll call them AbstractGoal and SpecificGoal. The SpecificGoal is the database representation of the implementation of a specific goal. The AbstractGoal is a representation of the set of conditions that could be nested and combined to create the final result. (And, for the purposes of uniformity of reference, I might create an AbstractGoal for each SpecificGoal such that a person having only one SpecificGoal is still processed by making a reference to an AbstractGoal.)

You’ll then want to decide on a representation of your AbstractGoal - and that’s going to be up to your comfort level with parsing such a representation.
For example, let’s say that all AbstractGoals are identified by some ID number. (simple numeric primary key) You could choose among:

  • Algebraic notation: e.g. (15 & 23) | (4)
    • Read that as goals 15 and 23 or goal 4
  • RPN: e.g. 15 23 and 4 or
  • Nested JSON operations: e.g. {‘or’: [4, {‘and’: [15, 23]}]}
    • That’s just a sample idea, I’m not sure that’s the precise syntax I’d use
  • Some other DSL you design

Any of the above would be suitable, you just need to be able to parse and evaluate the expressions.

1 Like

Thanks, @KenWhitesell
I am going to do that with JsonField