Django many to many with two models? - django

I have two models Students, University. By using this, student can apply for a course in university and the requirements is when a student apply for a course in university, i need to create a application ( planning to create separate model for application )
And this application can been accessed by both student & university. The purpose of making both access the application is because there are many post apply data's to be manipulated later !
So how to create a common application table - so both can access or its not effecient to create a seprate table ?
Please guide on how to tackle this !
Option1: Can a many to many be combined with Student and University to create a application model
Option2: Add manytomany field to students model itself with University as foreign key ?
I have records about more than 1 million so am bit concerned about efficiency ! Which is better option to handle two way communication

The best way to handle this would be to have the intermediate model Application to contain foreign keys to both Student and University.
Having both foreign keys in the Application model would guarantee a many-to-many relationship between the Student and University.
The solution would be like so:
class Student(models.Model):
email = models.EmailField(max_length=255)
class University(models.Model):
name = models.TextField()
class Application(models.Model):
applicant = models.ForeignKey(
"Student",
on_delete=models.CASCADE
)
university = models.ForeignKey(
"University",
on_delete=models.CASCADE
)

Option1: Can a many to many be combined with Student and University to create an application model
Option1 is answered by Ren.
For explanation, you may check Django Features and Libraries
University of Michigan Video
Option2: This won't fulfill your requirements. Indeed Django will automatically generate a table to manage many-to-many relationships. You need to manually specify the intermediary table, you can use the through option to specify the Django model that represents the intermediate table that you want to use. i.e. Option 1
See ManyToManyField official doc.

Related

Django - Many to Many Relationship with Workouts & Exercises

I'm currently stuck on how to do the following:
I want to track workouts and see the progress being made with the exercises.
Each workout has a name, body weight, date, and exercises.
I want to select the exercises when adding the workouts(exercises are already pre-created with a name and some tags), however, each workout is different, meaning the reps, sets, and weight for the exercise is different every time.
I'm not sure how to make a model for this.
I've added an image of a simple design I made to show what I'm after
Hope someone can help me, I'm pretty sure it's a simple solution however, my brain is stuck atm.
Image Of Design
First an foremost, I'd recommend reading through the Django models docs to get an idea of what models represent and how they work.
To address your question, I think you've correctly identified all of the information you need to create your models, so let's go through them step by step.
Architecture
It's helpful to take a step back and think about the entities in your app. Identify what they are, what attributes they posses and which of these attributes are atomic i.e. cannot be their own entity.
Workout - You mentioned that you want to track workouts with each one having name, body weight, date, and exercises. All of these attributes except for exercises seem to be atomic as they can be represented with fundamental datatypes (strings, floats, datetimes etc.). Moreover, one workout can have many exercises indicating that we need to abstract it into its own entity.
Exercise - You identified that exercises are pre-set and need to have a name and tags. A name is something we can represent with a string, however one exercise can have multiple tags, meaning it's not atomic (has a one-to-many relationship). This means we need to extract it into its own entity.
Tag - From what you said, a tag simply has one attribute which is a name that can be represented by a string. One tag can belong to many exercises.
You may be wondering where we are storing the reps, sets and weight data for each exercise in each workout. This is actually going to require an extra entity that stores the many-to-many relationship between Exercise and Workout. Let's call this Workout-Exercise.
With this information we could draw a Entity Relationship Diagram as such:
This gives us what we need to start creating Django models.
Models
Let's start with the Exercise and Tag entities. We can simply translate these directly into Django models:
from django.db import models
class Tag(models.Model):
name = models.CharField(max_length=200)
class Exercise(models.Model):
name = models.CharField(max_length=200)
tags = models.ManyToManyField(Tag)
Here we've created the two models and specified a many-to-many relationship between Exercise and Tag. This means that an Exercise object can have many Tag objects e.g. you can call exercise.tags.all() to get all of the tags for a given Exercise object.
The tricky part comes when we are creating the Workout-Exercise entity. When we use ManyToManyField in Django, it normally automatically creates a mapping model/table that we don't see. However, in the case where we want to store extra information about these relations (as we do in our use-case) we have to use a through model.
On this model we have to define the two foreign keys for the models we are linking along with the data types for the extra field data we want to store. In this case the foreign keys are Workout and Exercise, and the extra data are reps, sets and weight. The model definitions could therefore look like:
class WorkoutExercise(models.Model):
workout = models.ForeignKey(
'Workout',
on_delete=models.CASCADE,
)
exercise = models.ForeignKey(
Exercise,
on_delete=models.CASCADE,
)
reps = models.IntegerField()
sets = models.IntegerField()
weight = models.DecimalField(max_digits=5, decimal_places=2)
class Workout(models.Model):
name = models.CharField(max_length=200)
body_weight = models.DecimalField(max_digits=5, decimal_places=2)
date = models.DateTimeField(auto_now_add=True)
exercises = models.ManyToManyField(
Exercise,
through=WorkoutExercise
)
If you're confused about any of the model data type choices I've recommended, please take a look at Django model docs.
With this set-up you should be able to access and insert all of the data you need. If you need more information on how to access any of the many-to-many relationship data, please look at the Django many-to-many docs.
Sources
https://docs.djangoproject.com/en/3.2/topics/db/models/
https://www.1keydata.com/database-normalization/first-normal-form-1nf.php
https://en.wikipedia.org/wiki/One-to-many_(data_model)
https://docs.djangoproject.com/en/3.2/topics/db/examples/many_to_many

How can I create a model that represents a spreadsheet?

I am trying to build a table style app to allow tracking items in a spreadsheet that can be added to a branded website. My table would look something like this if using a spreadsheet:
Customer Name
Customer Address
Producer
Mark
233 Main St
Greg
Company
Date Ordered
Rep
Date Received
Cost
Quote Number
A
7/20/21
John
7/25/21
500
JDHP
B
7/20/21
Mary
C
7/23/21
John
7/25/21
1500
584D
D
7/18/21
Mary
7/22/21
400
J5HP
Effectively the idea is that I'd have a model that houses each Customer's different quotes. I have 2 categories of companies (public and private) that would each be tracked so I'm envisioning a large form that houses these three small forms (customer info, private company quotes and public company quotes). I would be including every company in every sheet whether we reach out to them for a quote or not so we know what options are still available if the customer requests more quotes.
I've been looking at the django formsets as a possible option but don't fully understand how they work. I watched some tutorials and read through the documentation but it seems like those will simply add a blank input after all complete ones already in the table. Is this a correct interpretation of how formsets work? Or would they effectively allow me to nest multiple forms within a larger form? Secondary to that is how would I implement this model? I tried company_date_ordered, company_rep, company_date_received, etc. for each company in my list but got a lot of clash errors.
Welcome to web development.
A few points:
It's been said, "Applications age like fish, data ages like wine" - what this means is its best to focus your attention on your data models and concern yourself less with the application code itself
Spreadsheets are themselves tables - meaning you wouldn't build a model that represents a spreadsheet but rather you would build a model that represents a row (object) or elements of each row (objects) of the spreadsheet
That being said, given your example let's consider what objects we are working with:
Your first "spreadsheet" looks like it could be a combination of a Customer and Producer table - for this example we will simplify this to just a Customer table which will contain the field producer
Your second spreadsheet is a bit more complex, it appears to join Company, something like an Order and possibly a Representative (and maybe even more) - let's break this down into each of its parts:
models.py
class Customer(models.Model):
"""
this is a simple model that represents a customer,
it doesn't have any relations to other tables
"""
name = models.CharField(...)
address = models.CharField(...)
producer = models.CharField(...)
class Order(models.Model):
"""
this table represents orders,
it will have relations to other tables, add them as needed
"""
# fields:
date_ordered = models.DateField(...)
date_received = models.DateField(...)
quote_number = models.CharField(...)
"""
an Order can only be associated to one Company
but a Company can have many Orders
therefore we will use a ForeignKey
the same goes for Representative
"""
# relations:
company = models.ForeignKey("Company", ..., related_name = "orders")
representative = models.ForeignKey(...)
class Company(models.Model):
"""
this model represents a Company
its related to Orders,
but the relation is defined on the Orders table
"""
name = models.CharField(...)
class Representative(models.Model):
...
Spend some time thinking about what your entities are and how they relate to one another. Once your data structure is well formed, you can start to build out interfaces for users to view, edit, and add to your tables - forms are a good way to start but they are certainly not the only option. Best of luck!

Best way to query/display multi-joined data from using Django

I'm new to Django, a question on query/display of joined tables.
I have a model setup with "managers" and "skills"...and a join table of "managerskills".
ManagerSkills has foreign key links to both the "manager" table and the "skill" table. This is a many to many table. (managers have many skills, skills belong to different managers)
I am looking to retrieve a list of managers, display them in a grid, and have a column for "skills", which would display a comma-separated list of skills associated with the manager.
class Manager(models.Model):
title = models.CharField(max_length=250)
class Skill(models.Model) :
skill = models.CharField(max_length=15)
class ManagerSkills(models.Model) :
manager = models.ForeignKey(Manager,on_delete=models.CASCADE)
skill = models.ForeignKey(Skill,on_delete=models.CASCADE)
How would I query this dataset to retrieve distinct list of managers, while also having reference to associated skills that can be output in table/grid?
Since this is a many to many relationship, you should declare it as such:
class Manager(models.Model):
skills = models. ManyToManyField("Skill", through="ManagerSkills")
...
Now in your template you can iterate through manager.skills.all.
(Note, if you don't have any other fields on ManagerSkills, you can remove the definition altogether along with the through attribute in the field; this makes managing skills in the admin easier.)

django - many-to-many and one-to-many relationships

I am working in django, am planning a database for rides for users.
each User can be on multiple Rides (over time) and each Ride can have multiple Users (passengers) in it.
Also, for each Ride there has to be only one Driver (also a User) so I think I have a many-to many relationship between the Rides and Users tables for what user is on what ride, and also a One-To-Many relationship between the Rides's Driver_id and the User_id. right?
My questions are-
I saw in the django docs that I should put a many-to-many field in One of the models. Does it matter which one? and also, does it create a new table like rides_users?
and also, what is the difference (in One-To-many relationship) between using a foreignKey field and a OneToManyField field?
EDIT:
Currently, there are my models:
def get_image_path(models.Model):
return os.path.join('photos',str(instance.id),filename)
class UserProfile(models.Model):
user=models.OneToOneField(User)
phone_number=models.CharField(max_length=12)
profile_picture=models.ImageField(upload_to=get_image_path, black=True, null=True)
class Ride(models.Model):
driver=models.ForeignKey(UserProfile, related_name="r_driver")
destination=models.ForeignKey(Destination, related_name="r_final_destination")
leaving_time=models.DateTimeField()
num_of_spots=models.IntergerField()
passengers=models.ManyToMany(UserProfile, related_name="r_passengers")
mid_destinations=models.ManyToMany(Destination, related_name="r_mid_destinations")
class Destination(models.Model):
name=models.CharField(max_length=30)
As you can see, each Ride has multiple mid_destination and multiple passengers. a Ride also has One driver and One final destination.
The Issue is - when a User adds a Ride, I want the driver, destination and mid_destinations and the rest of the fields to be set by the User (the driver is user adding the Ride), Except for the passengers field. I want the other Users to add themselves to the ride, so when the Ride is created the User (driver) doesn't have to set the passengers.
How do I go about it? and also, any other suggestions about the models?
There is no such thing as a OneToManyField.
It doesn't matter from a practical point of view which side the ManyToManyField lives on. Personally, I'd put it on Ride, both to avoid changing the User model and because conceptually I'd say that rides are the main objects here.
And yes, adding the field will automatically create the linking table.
what you want is probably something like this
class MyModel(models.Model):
driver = models.ForeignKey(to=User, related_name='r_driver')
# you need to use a related name if you want to link to the same model more than once
passengers = models.ManyToManyField(User, related_name="r_passengers")

Do a query through a foreignkey in Django

How do I travel through multiple foreign keys in Django? I've tried everything I can think of from the django docs, but I'm obviously missed something (extreme newbie). I have models for scientists, experiments, and theories.
If I want to look at a particular Theory (let's call it 'relativity') and get a list of all of the emails of scientists working on it (kept in the normal django user model), how do I do this?
class Experiment(models.Model)
experimenter = models.ForeignKey(Scientist)
theory = models.ForeignKey(Theory)
class Theory(models.Model)
name = models.CharField(max_length=100)
class Scientist(models.Model)
user = models.ForeignKey(User, unique=True)
institution = models.CharField(max_length=20, null=True, blank=True)
These are simplified versions of my models that I rewrote, so there are probably some errors in it, but the relationships are correct.
I've tried every kind of combinations of select_related(), get(), filter() but can't figure it out. Thanks in advance for your help!
User.objects.filter(scientist__experiment__theory__name=u'relativity')
Take a look at the Django documentation section about Lookups that span relationships. The net takeaway is:
To span a relationship, just use the field name of related fields across models, separated by double underscores, until you get to the field you want.
Ignacio's answer shows an example of using the double underscores on field names to span a relationship.
The other relevant portion of Django's documentation would be the Related objects section. Relationships in Django are asymmetrical in the way they are accessed. Forward/normal relationships are accessed as attributes of the models. Backward relationships are accessed:
Django also creates API accessors for the "other" side of the relationship -- the link from the related model to the model that defines the relationship. For example, a Blog object b has access to a list of all related Entry objects via the entry_set attribute: b.entry_set.all().