django model to yeild specific HTML output without redundancy in the model - django

I have 3 models (supervisor, students, and allocation)
I am building an allocation system where multiple students can be allocated to one supervisor
Now I want my model to be able to yeld this output
Example of how i want the output to come out
Here are the structure of my model
class StudentProfile(models.Model):
stud_id = models.UUIDField(default=uuid.uuid4, primary_key=True, unique=True)
user_id = models.OneToOneField(User,blank=True, null=True, on_delete=models.CASCADE)
programme_id = models.ForeignKey(Programme, on_delete=models.CASCADE)
session_id = models.ForeignKey(Sessi`**enter code here**`on, on_delete=models.CASCADE)
type_id = models.ForeignKey(StudentType, on_delete=models.CASCADE)
dept_id = models.ForeignKey(Department, on_delete=models.CASCADE)
class SupervisorProfile(models.Model):
super_id = models.UUIDField(default=uuid.uuid4, primary_key=True, unique=True)
user_id = models.ForeignKey(User, on_delete=models.CASCADE)
dept_id = models.ForeignKey(Department, on_delete=models.CASCADE)
class Allocate(models.Model):
allocate_id = models.UUIDField(default=uuid.uuid4, primary_key=True, unique=True)
stud_id = models.ForeignKey(StudentProfile, on_delete=models.CASCADE)
super_id = models.ForeignKey(SupervisorProfile, on_delete=models.CASCADE)
now my main focus is the Allocate model where the allocation is made, and there is a lot of redundancy any suggestions on how to improve my model to remove redundancy in yielding the expected HTML output would be appreciated šŸ™

As far as I understand, you need to assign several students to one Supervisor
For this, you only need to use ForeignKey in class StudentProfile
As below:
supervisor=models.ForeignKey(Supervisor,on_delete=models.DO_NOTHING)
But if you need to connect a student to several Supervisor, you should use ManyToManyField
ManyToManyField automatically creates a third table like class Allocate of yourself
For more information, refer to the hire.
It is also possible to reduce the redundancy by considering the department.
However
It doesn't seem that less redundancy can be found in sql database
I hope it was useful

Related

is it possible to have two parameters in limit_choices_to in django models?

I'll shorten the code as simple as possible. Supposedly, we do have two models.
models.py > Products table
CATEGORY = (
('Hard Disk Drive', 'Hard Disk Drive'),
('Solid State Drive', 'Solid State Drive'),
('Graphics Card', 'Graphics Card'),
('Laptop', 'Laptop'),
('RAM', 'RAM'),
('Charger', 'Charger'),
('UPS', 'UPS'),
('Mouse', 'Mouse'),
('Keyboard', 'Keyboard'),
('Motherboard', 'Motherboard'),
('Monitor', 'Monitor'),
('Power Supply', 'Power Supply'),
('Router', 'Router'),
('AVR', 'AVR'),
('Tablet', 'Tablet'),
('System Unit', 'System Unit'),
('Audio Devices', 'Audio Devices'),
('CPU', 'CPU'),
('Others', 'Others'),
)
class Product(models.Model):
model_name = models.CharField(max_length=100, null=True, blank=True)
asset_type = models.CharField(max_length=20, choices=CATEGORY, blank=True)
date = models.DateField(null=True, blank=True)
And the other table > Order table
class Order(models.Model):
product_order = models.ForeignKey(Product, on_delete=models.CASCADE, null=False)
employee = models.ForeignKey(User, models.CASCADE, null=False)
date = models.DateTimeField(auto_now_add=True)
remarks = models.TextField()
And we all know that adding this code will limit the foreignkey choices under the Order form.
limit_choices_to={"asset_type": "Hard Disk Drive"}
limit_choices_to={"asset_type": "Solid State Drive"}
My goal here is to show items from Products table whose asset_type is either "Hard Disk Drive" OR "Solid State Drive". I've read the documentation of Django for "limit_choices_to" and can't see any pertaining to some kind of solution in here. Thank you in advance who knows a way to make this possible.
You can work with the __in lookupĀ [Django-doc] to specify a list of allowed values:
class Order(models.Model):
product_order = models.ForeignKey(
Product,
on_delete=models.CASCADE,
limit_choices_to=dict(asset_type__in=['Hard Disk Drive', 'Solid State Drive'])
)
# ā€¦
Note: Specifying null=FalseĀ [Django-doc] is not necessary: fields are by default not NULLable.
Note: It is normally better to make use of the settings.AUTH_USER_MODELĀ [Django-doc] to refer to the user model, than to use the User modelĀ [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.

Django access manytomany field from related_name in a view

I have what i think is a simple question but I am struggling to find out how it works. I get how related name works for foreign keys but with many to many fields it seems to break my brain.
I have two 3 models at play here. A User, TeamMember and Team Model as seen below.
User model is the built in django model.
#TeamMember Model
class TeamMember(models.Model):
member = models.ForeignKey(User, on_delete=models.SET(get_default_team_member), verbose_name='Member Name', related_name="team_members")
...
#Team Model
class Team(models.Model):
name = models.CharField(max_length=50)
manager = models.ForeignKey(TeamMember, on_delete=models.SET_NULL, related_name="managers", null=True, blank=True)
team_lead = models.ForeignKey(TeamMember, on_delete=models.SET_NULL, related_name="tls", null=True, blank=True)
tps = models.ForeignKey(TeamMember, on_delete=models.SET_NULL, related_name="tps", null=True, blank=True)
members = models.ManyToManyField(TeamMember, blank=True, related_name="members")
...
Now in a view i want to access a specific users team. I thought i could do this by doing something like this:
member = TeamMember.objects.get(pk=1)
member_team = member.members.name
However if I print member_name than it prints nothing. If I try to access any of the other fields on that model like member.members.team_lead.first_name it fails to find the team_lead field. I understand that this has a .all() attribute but i thought it was tied to the team object through the members field. So if that member matches the team it would give me the team. So I thought it might be an issue if the same member was linked to more than one team (which is possible) so i tired something like this member.members.all().first().name and i get an error that states it cannot get name from NoneType.
Is there an easy way to get the team name from a relationship like this or am i better off just doing a team query with the user?
Thanks,
jAC
First of all, I would like to point out that you are not using the related_name (and related_query_name parameters in a proper way). I think this SO post will help you to understand the concept in a better way.
So, I would change the related_name (and related_query_name) values in the Team model as below,
class Team(models.Model):
name = models.CharField(max_length=50)
manager = models.ForeignKey(
TeamMember,
on_delete=models.SET_NULL,
related_name="teams",
related_query_name="team",
null=True,
blank=True,
)
team_lead = models.ForeignKey(
TeamMember,
on_delete=models.SET_NULL,
related_name="teams",
related_query_name="team",
null=True,
blank=True,
)
tps = models.ForeignKey(
TeamMember,
on_delete=models.SET_NULL,
related_name="teams",
related_query_name="team",
null=True,
blank=True,
)
members = models.ManyToManyField(
TeamMember, blank=True, related_name="teams", related_query_name="team"
)
...
Now in a view i want to access a specific user's team.
Since the Team and TeamMember models are connected via ManyToManyField, you may have "zero or more" Teams associated with a single TeamMember
So, the following query will get you all the teams associated with a particular TeamMemeber
team_member = TeamMember.objects.get(pk=1)
all_teams = team_member.teams.all()
You can also iterate over the QuerySet as,
team_member = TeamMember.objects.get(pk=1)
for team in team_member.teams.all():
print(team.name)
For anyone wondering what I did based on JPG's advice was the for loop option
team_member = TeamMember.objects.get(pk=1)
teams = [t.name for t in team_member.members.all()]
I personally do not care which team i get as my need in this case is just to pass a team through even if it is none. So i just use team = team[0] if teams.count() > 0 else "No team"

Having trouble linking two fields with one another, then implementing them to another model

I'm working on a project which helps users find jobs.
So one of the models, named Oferta is used for details about a job. Someone who is looking for emplooyes, just completes a form which is based on this model, and people will be looking at it.
Here's this model:
class Oferta(models.Model):
solicitant = models.ForeignKey(User, on_delete=models.CASCADE)
cor = models.CharField(max_length=50)
dataSolicitare = models.DateField(default=date.today)
denumireMeserie = models.CharField(max_length=50)
locuri = models.IntegerField()
agentEconomic = models.CharField(max_length=50)
adresa = models.CharField(max_length=150)
dataExpirare = models.DateField()
experientaSolicitata = models.CharField(max_length=200)
studiiSolicitate = models.CharField(max_length=200)
judet = models.CharField(max_length=20)
localitate = models.CharField(max_length=25)
telefon = models.CharField(max_length=12)
emailContact = models.EmailField(max_length=40)
rezolvata = models.BooleanField(default=False)
def __str__(self):
return self.cor
The COR field is the code asociated to a job. Also, denumireMeserie means job name.
So these should be linked. Let's say, if code 1 means "Cook", these should be link - there will be no other job with a different code, or another job for code 1.
So, in my opinion, these two fields should have a OneToOne relationship between them, if I'm not mistaken.
But these codes and jobs need to be implemented in the database - so they need a model too.
class CORMeserii(models.Model):
CodCOR = models.CharField(max_length=25, primary_key=True, unique=True)
MeserieCor = models.OneToOneField(CodCOR, max_length=50, unique=True, on_delete=models.CASCADE)
And here is how I tried to do it, but obviously it won't work, because onetoonefield needs a model as the first parameter.
So, my questions are:
How can I link these two fields as I told you, and then link Oferta.cor to CORMeserii.CodCOR and Oferta.denumireMeserie to CORMeserii.MeserieCor?
(because each job with its code and name should be implemented in the database, then chosen in each Oferta (which means offer))
As Dirk pointed out on your previous question, you have not understood what relationship fields do in Django.
A ForeignKey or a OneToOneField gives you access to the entire related object. This means you can access any of the fields on that related object.
So your Oferta model does not need a denumireMeserie field; that belongs on the other model, which we might call "Job". Oferta has a link to that model, ie a ForeignKey:
class Oferta(models.Model):
solicitant = models.ForeignKey(User, on_delete=models.CASCADE)
job = models.ForeignKey('Job', on_delete=models.CASCADE)
and Job has the details of the job:
class Job(models.Model):
cor = models.CharField(max_length=50)
denumireMeserie = models.CharField(max_length=50)
Now you can create a Job and an Oferta for that job:
my_job = Job.objects.create(cor=1, denumireMeserie='Cook')
my_oferta = Job.objects.create(job=my_job, ...rest of the fields...)
Now you can access the job name via the relationship:
print(my_oferta.job.denumireMeserie)
which will give you "Cook".

Django Models: One-to-Many Relationships, Reaching Across Tables -- How Can I get All Book objects with Reviews?

My Problem:
I have a handful of django models which are setup with various one-to-many relationships. I am trying to retrieve all Books which have a Review (I don't want to retrieve any books whom have no Reviews). Although what I'm trying to do seems relatively straight forward, I'm having real difficulty accomplishing my goal. It seems I may not properly understand how to reach across tables, and any advice anyone could provide in helping me better understand how to get all all Book objects which have a Review stored.
My Models:
class User(models.Model):
"""Creates instances of a `User`."""
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
email = models.CharField(max_length=50)
password = models.CharField(max_length=22)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = UserManager() # Attaches custom `UserManager` methods to our `User.objects` object.
class Author(models.Model):
"""Creates instances of a `Author`."""
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Book(models.Model):
"""Creates instances of a `Book`."""
title = models.CharField(max_length=100)
author = models.ForeignKey(Author, on_delete=models.CASCADE) # ties us into an author for the book. if author deleted, books delete too.
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Review(models.Model):
"""Creates instances of a `Review`."""
description = models.CharField(max_length=500)
user = models.ForeignKey(User, on_delete=models.CASCADE) # ties to user, if user deleted, deletes all user reviews
book = models.ForeignKey(Book, related_name="reviews") # book for review
rating = models.IntegerField() # user rating between 1-5
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = ReviewManager() # Attaches 'ReviewManager' to `Review.objects` methods.
What I've tried:
I've tried giving a related_name="reviews" to my Review.book property, and I've tried accessing reviews via Book.objects.all().reviews_set.all() or similar such queries, using _set.all() and am probably missing something / doing it incorrectly.
Desired Goal:
Retrieve all Book objects, whom have a Review attached to them (not retrieving Book objects whom have no Reviews).
Can anyone help point me in the right direction or tell me what I'm doing wrong? Thank you for your time reading!
Here's my best solution for gathering all books, whom have at least one review. This seems to be accomplishing my needs and answered my original question:
Book.objects.filter(review__gte=1).distinct()
This is saying, from Book model, get any books whom have a review gte (greater than or equal to) 1 -- and make sure they are distinct() ie, no duplicates.

2 OneToOneField defined for two tables. One got deleted but not other

I have defined two OneToOneFields in my model as below:
class StudentCrossMap(models.Model):
rfId = models.OneToOneField(StudentDailyTrans)
studentId = models.OneToOneField(StudentMaster)
When I apply delete on the model above giving rfId, the entry related to it in StudentDailyTrans gets deleted, BUT the one in StudentMasterdid not gets removed.
Ideally, if I am deleting the object from StudentCrossMap it should not be deleting the entries from mapped tables as those tables are not dependent on StudentCrossMap table.
Please advise if I am doing something wrong.
*Edit: Related tables
class StudentDailyTrans(models.Model):
rfId = models.CharField(max_length=30, primary_key=True)
schoolId = models.ForeignKey(SchoolMaster, on_delete=models.CASCADE, db_index=False)
fromTime = models.DateTimeField(null=True)
toTime = models.DateTimeField(null=True)
totalSwipeInstance = models.IntegerField(default=0)
lastUpdateTs = models.DateTimeField(auto_now=True)
class StudentMaster(models.Model):
studentId = models.IntegerField(primary_key=True)
schoolId = models.ForeignKey(SchoolMaster, on_delete=models.CASCADE)
parentId = models.ForeignKey(ParentMaster, on_delete=models.CASCADE)
class SchoolMaster(models.Model):
schoolId = models.IntegerField(primary_key=True)
subsStrtDt = models.DateTimeField(default=timezone.now)
class ParentMaster(models.Model):
parentId = models.AutoField(primary_key=True)
parentName = models.CharField(max_length=20, default='parent')
If I have understood what you have posted correctly, you are better off with a design like this.
class Student(models.Model):
id = models.IntegerField(primary_key=True)
school = models.ForeignKey(SchoolMaster, on_delete=models.CASCADE)
parent = models.ForeignKey(ParentMaster, on_delete=models.CASCADE)
rf = models.CharField(max_length=30, primary_key=True)
This is essentially, your old StudentMaster model. I have renamed it to Student. I have also renamed the field names to comply with the usual django naming convention (school instead of school_id for the foreign key)
Now you can delete StudentDailyTrans and StudentCrossMap we are saving the same data more efficiently and yet without redundancy. And that eliminates the problem you asked about!!
You will agree with me that the code is a lot more readable.