Identify what model belongs a unique field (primary key) - django

I would like with an unique field, to obtain the name of the model where it belongs. I was trying to use the get_model but it has another purpose.
Suppose that you have a school with multiple classrooms (each classroom is a model), and you wan to search a student with just the ID of him, receiving the name of the classroom where the student is.
So you type the ID (primary key) and the function will return you the class (model) where the student belong

I would like with an unique field, to obtain the name of the model where it belongs.
To get the model, to which a field belongs, you can use the model attribute:
Returns the model on which the field is defined. If a field is defined
on a superclass of a model, model will refer to the superclass, not
the class of the instance.
The above will answer your question, but a bigger issue is with this:
Suppose that you have a school with multiple classrooms (each
classroom is a model), and you wan to search a student with just the
ID of him, receiving the name of the classroom where the student is.
This is not a sustainable model and will cause issues as each classroom means a new table. This structure will cause you problems when you are doing searches across classrooms.
The second issue is you are confusing the value of a field with the name of the field. A primary key (the id) is a value. You can search for values if you know what field there are in, if you want to retrieve a record with primary key value 1, you would write a query like this:
SELECT * FROM classroom_table WHERE id = 1
In Django, this is Classroom.objects.get(id=1)
You can't go the other way around, that is "find me the table, that has the value "1" in the field of id" which is what you are asking to do here.
You need to fix your database structure so that there is one model for students, and one model for classroom; and a student can belong to many classrooms:
class Student(models.Model):
name = models.CharField(max_length=200)
class Classroom(models.Model):
students = models.ManyToMany(Student)
Now you can do things like find all classrooms for a student with id 1:
student = Student.objects.get(id=1)
for room in student.classroom_set.all():
print(room)

This question isn't very clear.
If you have a Student model and a Classroom model, and there is a ForeignKey from Student to Classroom, then you need to get the student from the primary key:
student = Student.objects.get(pk=my_pk_value)
and then get its classroom:
student.classroom

Related

Get Primary key of an element(Teacher) which is referred in student model django

I am new to Django and I don't know how to get access the primary key. I have a scenerio in which there are two users teacher and student one-to-one relationship to abstract user.In my case teachers create student accounts, I have created teachers accounts successfully,I also want to save students registered by the teachers which also know how to do it,but my problems is I also want to save the teacher in student model who registered that particular student, for this I want to get that teacher object(The teacher which is adding student at that time) which I can't,can someone provide suggestions or code how to do it?
Models.py File:
class User(AbstractUser):
is_student=models.BooleanField(default="False")
is_prof=models.BooleanField(default="False")
class Teacher(models.Model):
user=models.OneToOneField(User,on_delete=models.CASCADE)
designation=models.CharField(max_length=30)
class Student(models.Model):
user=models.OneToOneField(User,on_delete=models.CASCADE)
teacher=models.ForeignKey(Teacher,on_delete=models.CASCADE,default="")
batch=models.CharField(max_length=30)
Below my piece of approach to add student, user is created successfully but what to do in last line student= so I can teacher object through teacher_id:
obj=User.objects.create_user(
username=myids[iterate],password=passwords[iterate],
is_student=True,is_prof=False)
obj.save()
Student.objects.create(user=obj,teacher=(What to do?),batch="F-14")
If you create a field that is a ForeignKey, Django automatically creates a "twin field" named field_id, that stores the id. Updates to the some_object.field reflect in the some_object.field_id, and vice versa.
You can thus use the teacher_id field instead here:
obj= User.objects.create_user(
username=myids[iterate],
password=passwords[iterate],
is_student=True,
is_prof=False
)
obj.save()
Student.objects.create(user=obj, teacher_id=myteacherid, batch="F-14")
An alternative is to first fetch the Teacher object with the given id, and then use this, but this is less efficient, since it will result in two queries to construct the object: one to fetch the Teacher, and one to create the Student:
obj= User.objects.create_user(
username=myids[iterate],
password=passwords[iterate],
is_student=True,
is_prof=False
)
obj.save()
my_teacher = Teacher.objects.get(pk=myteacherid)
Student.objects.create(user=obj, teacher=myteacher, batch="F-14")
You can get the teacher object and assign it to 'teacher' field in Student model.
teacher = get_object_or_404(Teacher, pk=primary_key_of_teacher)
student = Student(user=user_object teacher=teacher batch=student_batch)
student.save()

django nested models field access

Here's the scenario:
I have a Student Model with subject field connected with Many-to-Many relationship to Subject Model
class Student(models.Model):
(...)
subject = models.ManyToManyField(Subject)
In Subject Model i have a program field connected with Many-to-Many relationship to Programs Model. Subject Model got also CharField name.
class Subject(models.Model):
(...)
program = models.ManyToManyField(Programs)
In Programs Model i have a field:
class Programs(models.Model):
name = models.CharField(max_length=40)
(...)
Django creates additional table for many-to-many fields. In my application I create (with form) a Program and Subject corresponding to Program. Then i create some Students and choose some subjects.
How can i access program name field (Student.objects.all()) and display what program name Student is using ? Is it possible, or i need to create additional fields in Student Model connected with Many-to-Many relationships with Program Model ?
Am I right in thinking that you want to return a list of the program names for the programs belonging to each subject in student.subject?
If so you could use this as a method of the Student model:
def get_program_names(self)
programs = []
for subject in self.subjects:
programs += [program.name for program in subject.program]
return programs
It sounds from your question, however, that you expect only one program name to be returned. if this is the case then maybe you should replace your manyToMany fields with ForeignKey fields, which give a one to one relationship between two models, meaning that this method should work:
def get_program_name(self):
return self.subject.program.name
(either way, there is no reason you should have to create a direct link between your student model and the program model, unless you wish to reduce the number of database calls, in which case you could add a field to Student which is updated with the latest program name or similar.)
I hope that I haven't misunderstood your question.

Django symmetrical ManyToMany field on 2 columns

In my model, how do I exlicitly state that I want a ManyToMany relationship with another column to be symmetrical, so that when calling an object_set from each object, it can go through the same database table to find the relationships?
An example
class Person(models.Model):
name = models.CharField(max_length=100)
employer = models.ManyToManyField(Organization)
class Organization(models.Model):
name = models.CharField(max_length=100)
Do I need to create a second ManyToManyField in the Organization class, in order to do something like
org1.person_set.all()
to get all persons employed by the organization and
pers1.organization_set.all()
to get all of the organizations a person might work for? Or will the single ManyToManyField symmetrically make the relationships?
You don't need to do anything.
Because the ManyToMany is hosted with Person, it will be:
pers1.employer.all()
and
org1.person_set.all()

Django. Many-To-Many Field for form, but not for model

I have DB that should have one field with type Many-To-Many, but it is not and I can't change this.
For example I have a list of students and a list of subjects. Subject should be many-to-many field in students table, but as i said it is not. Students table doesn't have this field at all. But there is still another table students-subjects that contains subject_id-student_id items.
How can I embed in student form some kind of subject field that could change students-subjects data when I save a student in DB? The problem is that I can't change the DB structure so need to make it only with help of Django.
There is no such thing as a 'Many-to-many field' for a database-table like you might know it of foreign keys. In database representation many-to-many relationships are realized by using an extra table that links the primary keys (usually the ids) of the records you want to set in relation. In your case that is the table students-subjects. Django uses this table when you define a many-to-many relationship in the model. You do not have to change your database structure at all, it will be working perfectly as it is now.
See the documentation: ManyToManyField
You'll have to set the db_table option with the name of your intermediary table (i.e. students-subjects). Then everything should work fine.
EDIT:
Considering your comment, the problem is that Django expects a certain naming convention (i.e. MODELNAME_id) which isn't provided by your table. Since you say that you cannot change the table itself, you have to try something else.
You have to create an extra Model for your intermediary table (students-subjects) and define the field 'students' as a foreign key to the students model and the field 'subjects' as a foreign key to the subjects model. Then for the many-to-many field you specifiy the option 'through' with the name of your intermediary table. Set the options 'db_column' to let Django know which names you'd like to use for the databse columns. 'db_table' in the meta class is needed to specify your database table name.
You get something like:
class StudentsSubjects(models.Model):
student = models.ForeignKey(Student, db_column='student')
subject = models.ForeignKey(Subject, db_column='subject')
class Meta:
db_table = 'students-subjects'
class Student(models.Model):
...
subjects = models.ManyToManyField(Subject, through='StudentsSubjects')
...
class Subject(models.Model):
...
I hope that will help you.
For more detail see: Extra fields on many-to-many relationship.

django: Switch the inherited model base class to different child

The base class model and inherited models are as follow:
class Profile(models.Model):
user = models.ForeignKey(User, unique=True)
...
class Student(Profile):
...
class Teacher(Profile):
...
I have object of Student class(the data for which are stored in two tables in db - Profile table and a Student table which has a pointer to Profile table). I need to assign that Profile table row to a Teacher object and delete the Student object, i.e. without losing the content of Profile table data and also retaining the same id for that row. How it should be done?
Thank you,
Any help would be appreciated..
Behind the scenes, Django creates a field on the Student and Teacher models called profile_ptr_id. So you'll probably have to manipulate that. Because of how Django's concrete inheritance works, each Student and Teacher object's primary key is actually this profile_ptr_id field. Thus, I am not sure having both a Student and Teacher object with the same profile_ptr_ids is allowed.
One way you can try to get around this is the following:
Create a new Profile object
Set the Student object's profile_ptr_id to the id of the new Profile object
Set the Teacher object's profile_ptr_id to the id of the old Profile object that the Student object was previously pointing to.
Delete the Student object
I've never tried this, so I really can't say if it will work or not...
If you have a student that you want to turn into a teacher with some or all fields, and you can afford to type out the fields, you can just do:
teacher = Teacher(id=student.id, user=student.user,
name=student.name, email=student.email, ...)
student.delete()
teacher.save()
It's important to set the ID and delete the old object before saving the new one with the same ID.