3 way many to many relationship in Django - python

I have a Person model, a Semester model, and a Room model.
I'm trying to do a 3 way many to many relationship.
I've achieved this with an associative entity (a 4th model), which has 3 foreign keys (one for Person, one for Semester, and one for Room).
What is the Django-ish way of doing this using the built in ManyToManyField? Or is it inappropriate to use that with a 3 way m2m? I was looking at funneling 2 ManyToManyFields using the through parameter, but I wanted to see if anyone else had figured this out.
Thanks.

Related

Many to Many data-structure in python

I was wondering how I could implement a many-to-many relationship data-structure. Or if something like this already exists in the wild.
What I would need is two groups of objects, where members from one group are relating to multiple members of the other group. And vice versa.
I also need the structure to have some sort of consistency, meaning members without any connections are dropped, or basically cannot exist.
I have seen this answer (it involves SQL-lite database), but I am not working with such huge volumes of objects, so it's not an appropriate answer for this context Many-to-many data structure in Python
Depending on how big your dataset is, you could simply build all possible sets and then assign booleans to see whether the relationship exists.
itertools.combinations
can be of help to generate all possible combinations.
Consistency can then be added by checking if any connections are True for each value.
I do not claim this is the prettiest approach, but it should work on smaller datasets.
https://docs.python.org/2/library/itertools.html#itertools.combinations

Many to one relationship on a junction table (many to many) or a custom field type?

Currently, I have two tables, Exercise and WorkoutPlan. These will have a many to many relationship.
Exercise
- ID
- Name
...
WorkoutPlan
- ID
- Name
- Exercises (Many to Many with Exercise through WorkoutPlanExercise)
...
In this Many to Many relationship table, I need to store information about a number of sets, such as there min_rest, max_rest, min_repetitions and max_repetitions.
Where I'm stuck is, is trying to figure out the best solution to do this. My first solution is to have another table (WorkoutPlanExerciseSet) that has a many to one relationship with the many to many table (WorkoutPlanExercise), as shown below.
WorkoutPlanExercise
- ID
- ExerciseID
- WorkoutPlanID
- Sets (One to Many with WorkoutPlanExerciseSet)
WorkoutPlanExerciseSet
- WorkoutPlanExerciseID
- MinRepititions
- MaxRepititions
- MinRest
- MaxRest
My second solution is to store all the information about the exercise set, in a single row in the many to many relationship table (WorkoutPlanExercise). For example:
WorkoutPlanExercise
ID ExerciseID WorkoutPlanID Sets Repititions Rest
1 1 1 3 10-12, 10-10, 12-12 90-120, 60-90, 30-30
To note, both the rest time and number of repetitions, can be a range or a single number. For the second solution, I think I would create a custom Django Form Field.
Which is better? Is the former bad database design? Is the latter bad application design?
If it makes any difference, I wish to be able to easily display the information in a user friendly manner, such as:
Example Workout Plan
Exercise Sets Repetitions Rest
Pull Ups 3 10 - 12 90 - 120
8 - 10 30
6 - 8 30
I guess second. Read about custom through field here.
UPDATE: see comments.
UPDATE 2, 3:
Actually, both are very nice. It depends on how you want to process data, stored in Repetitions and Rest fields. If you want to do heavy manipulations and calculations with data, e. g. calculate total rest time for WorkoutPlan or total number of repetitions for Exercise, then using former approach will be slightly easier.
UPDATE 4:
Storing data of the same kind as CSV in one field is bad idea. You will have a lot of fun if you have to change schema in the future. Use first approach. Also link1, link2.

Effective implementation of one-to-many relationship with Python NDB

I would like to hear your opinion about the effective implementation of one-to-many relationship with Python NDB. (e.g. Person(one)-to-Tasks(many))
In my understanding, there are three ways to implement it.
Use 'parent' argument
Use 'repeated' Structured property
Use 'repeated' Key property
I choose a way based on the logic below usually, but does it make sense to you?
If you have better logic, please teach me.
Use 'parent' argument
Transactional operation is required between these entities
Bidirectional reference is required between these entities
Strongly intend 'Parent-Child' relationship
Use 'repeated' Structured property
Don't need to use 'many' entity individually (Always, used with 'one' entity)
'many' entity is only referred by 'one' entity
Number of 'repeated' is less than 100
Use 'repeated' Key property
Need to use 'many' entity individually
'many' entity can be referred by other entities
Number of 'repeated' is more than 100
No.2 increases the size of entity, but we can save the datastore operations. (We need to use projection query to reduce CPU time for the deserialization though). Therefore, I use this way as much as I can.
I really appreciate your opinion.
A key thing you are missing: How are you reading the data?
If you are displaying all the tasks for a given person on a request, 2 makes sense: you can query the person and show all his tasks.
However, if you need to query say a list of all tasks say due at a certain time, querying for repeated structured properties is terrible. You will want individual entities for your Tasks.
There's a fourth option, which is to use a KeyProperty in your Task that points to your Person. When you need a list of Tasks for a person you can issue a query.
If you need to search for individual Tasks, then you probably want to go with #4. You can use it in combination with #3 as well.
Also, the number of repeated properties has nothing to do with 100. It has everything to do with the size of your Person and Task entities, and how much will fit into 1MB. This is potentially dangerous, because if your Task entity can potentially be large, you might run out of space in your Person entity faster than you expect.
One thing that most GAE users will come to realize (sooner or later) is that the datastore does not encourage design according to the formal normalization principles that would be considered a good idea in relational databases. Instead it often seems to encourage design that is unintuitive and anathema to established norms. Although relational database design principles have their place, they just don't work here.
I think the basis for the datastore design instead falls into two questions:
How am I going to read this data and how do I read it with the minimum number of read operations?
Is storing it that way going to lead to an explosion in the number of write and indexing operations?
If you answer these two questions with as much foresight and actual tests as you can, I think you're doing pretty well. You could formalize other rules and specific cases, but these questions will work most of the time.

Search Between Two Models in Django

I apologize in advance is this question is too broad, but I need some help conceptualizing.
The end result is that I want to enable radius-based searching. I am using Django. To do this, I have two classes: Users and Places. Inside the Users class is a function that defines the radius in which people want to search. Inside the Places class I have a function that defines the midpoint if someone enters a city and state and not a zip (i.e., if someone enters New York, NY a lot of zipcodes are associated with that so I needed to find the midpoint).
I have those two parts down. So now I have a radius where people want to search and I know (the estimate) of the places. Now, I am having a tremendous amount of difficulty combining the two, or even thinking about HOW to do this.
I attempted doing the searching against each other in the view, but I ran into a lot of trouble when I was looping through one model in the template but trying to display results based on an if statement of the other model.
It seemed like a custom template tags would be the solution for that problem, but I wanted to make sure I was conceptualizing the problem correctly in the first place. I.e.,
Do I want to do the displays based on an if statement in the template?
Or should I be creating another class based on the other two in my models file?
Or should I create a new column for one of the classes in the models file?
I suppose my ultimate question is, based on what it is I want to do (enable radius based searching), where/how should most of the work be done? Again, I apologize if the question is overly broad.
Perhaps you could put it in the view which renders the search page.
asuuming you have a view function like search you could:
get users radius request.user.get_radius
search for places based on that radius relevant_places = Places.get_all_places_in_radius
Render those places to a user
Based on what you are describing, I believe GeoDjango would be worth your time to look into: http://geodjango.org/
Especially if you want to enable radius based searching, most of the heavy lifting is already done by GeoDjango, you'll just have to invest some time learning how to use it (which is a small fraction of the time you would have had to spend "reinventing the wheel", so to speak)
I just decided to add the function to the view so that the information can be input directly into the model after a user enters it. Thanks for the help. I'll probably wind up looking into geodjango.

Order a queryset in django by an annotated field and append the rest of the objects that did not fit the criteria

So this snippet practically explains what I want to do
bloc_results = bloc_results.annotate(num_mates=Count(profilebloc__profile__in=probable_mates)).order_by("-num_mates")
I know this is not possible but it was the easiest way I found to explain the situation. the variable probable_mates is a list filled with the pk's of a user table. So I have to get that number and order by it. That's no problem using filter. The thing is that using filter only retrieves the objects that match the id's on that probable_mates list, not all of them with the ones with the highest number of matches up at the top which is what I need to get. How can I do that with the Django ORM without going raw SQL? Thanks!
EDIT: I'll clarify a bit by explaining what this is doing: There are a bunch of clubs that will be added to this webapp and I need sorting by two different parameters. One is by the number of members of each club which is pretty easy. The second one if by "Club friends" so that all of the clubs are ordered by the number of common friends they have with the logged in user even if that user hasn't joined that club. Also that is not so hard. The problem is that when I get that queryset and order it it only displays the clubs that have club friends in common, not the rest. I need the ones that have club friends at the top, ordered by number of mutual club friends and the rest at the bottom, even if they don't have club friends in common.
Like akonsu said in his comment, I'm not exactly sure what you are trying to accomplish. That said, this sounds similar to this question I just answered. Adapted to your model names, does the following do what you want?
matches = bloc_results.objects.filter(profilebloc__profile__in=probable_mates)
matches = matches.annotate(Count('num_mates'))
results = matches.order_by('-num_mates')
If not, I think you need to clarify your question a bit.
I think you need to approach this from your profilebloc model. Count mates using that model, and then filter the results to leave only profile blocs that are in your bloc_results. Sorry, without your models I cannot be clearer.
This was a pretty badly explained question but I solved it by using the | operator to concatenate both querysets like this:
new_queryset = one_queryset | second_queryset
Did not have to use lists after all.

Categories

Resources