Where to add Many to Many in django? - django

So, Am creating a app where user can add universities to their fav or wishlist ! The problem is, am just confused how and where add ManyToMany ?
Model Student:
name = models.CharField
.....
Model University:
name = models.CharField
.....
Model Wishlist:
wish = models.ManyToMany(University)
Is this correct, is it okay to create a seprate model class as "wishlist" or can i have the wishlist on the Student:
Am totally confused, all i need to do is "user needs to able to click heart button and add university to wishlist and if they reclicks it needs to removed"

If a Student can only have one wishlist, it makes no sense to define an extra model with a ManyToManyField. This would result in creating an extra table, and thus make queries less effective, and programs less readable.
In that case, you can define a ManyToManyField from your Student to the University, so:
class Student(models.Model):
name = models.CharField(max_length=128)
wishlist = models.ManyToManyField('University', blank=True)
# ⋮
class University(models.Model):
name = models.CharField(max_length=128)

Related

what is related_name and related_query_name in django?

i have an issue with the code in django framework regarding to related_name and related_query_name in django. please django expert explain the related_name in django, the code is below:
related_name='+'
Related Name
Django maintains backward relation on each object for easy access to related objects. Suppose you have two models named "School" and "Student" and one school can have multiple students. So you will have model definition something like this
class School(models.Model):
name = models.CharField(max_length=55)
city = models.Charfield(max_length=55)
class Student(models.Model):
name = models.CharField(max_length=55)
school = models.ForeignKey(School)
Now if you have an school objects then you can access all students of that school with writing query explictly.
school = School.objects.get(id=1)
# Now if need all students of this school, first thing that come in your mind would be
Student.objects.filter(school=school)
# But instead of this, you can access all students by
school.student_set.all()
Here student_set is the default, related name made by Django. But you can have your custom related names like this
class Student(models.Model):
name = models.CharField(max_length=55)
school = models.ForeignKey(School, related_name='students')
# Now you can do
school.students.all()
Special Character in related name
If you define related_name='+' then backward relation would not be available on object and school.student_set.all() will give you error.
If you’d prefer Django not to create a backwards relation, set related_name to '+' or end it with '+'. For example, this will ensure that the User model won’t have a backwards relation to this model:
Related Query Name
related_query_name is similar to related_name but it gets used in queryset.
If you need to apply some filter on student via school model, then you would do
School.objects.filter(student__name='abc')
But if you define related_query_name then you can do
class Student(models.Model):
name = models.CharField(max_length=55)
school = models.ForeignKey(School, related_query_name='abc')
# Now you can do
School.objects.filter(abc__name='abc')
Refer doc for further reference: https://docs.djangoproject.com/en/3.0/ref/models/fields/

How to call a a field of one model A into another model B so that b can work as a view

I have created a model called Department, Course. Models are as follow
This is the model for departments and course
class Departments(models.Model):
Department_Id = models.IntegerField(primary_key=True)
Department_Name = models.CharField(max_length=200)
Department_Code = models.CharField(max_length=200)
class Course(models.Model):
Course_Id = models.IntegerField(primary_key=True)
Department_Id = models.ForeignKey(Departments, on_delete=models.CASCADE)
Course_Name = models.CharField(max_length=200)
Course_Code = models.CharField(max_length=200)
I want to create a model called view which can be later on called for search. I want a view model in a such a way that it consit of the data in concat form i.e. name= Department_name+ Course_Name
class View (models.model):
view_id= models.IntegerField(primary_key=True)
Name= Department_name(I want this from Departments table)
+ Course_Name(I want this from Course table)
I try using one to one relation . I would really appricate the help
It's not clear why you'd want to do that. It's never a good idea to duplicate data from one model into another one, as it can lead to inconsistencies.
You can add a ForeignKey in View to your Course model and then when you do f"{view.course.name} {view.course.department.name}" you already have your string:
class View(models.Model):
course = models.ForeignKey(Course, on_delete=models.CASCADE)
def name(self):
return f"{self.course.name} {self.course.department.name}"
Notes:
Don't call your foreign key Department_id because it's not referring to the id but to the object itself in the Django ORM: department = models.ForeignKey(Department, on_delete=models.CASCADE). As you can see, this makes reading the code much simpler: self.course.Department_id is a Department object not an integer, so self.course.department makes more sense.
Don't prefix your field names with the class, it just makes the code so much less readable: Do you prefer department.name or department.Department_name?
The View model is still a mystery to me, as you can search without it. You can search for example for courses with a matching department name like this:
Course.objects.filter(department__name__icontains="maths")
which will return all courses with "maths" in their department name.
Remove all the ids from your models, they are created automatically by Django anyway (and called id). Again, department.id is much easier to read than department.Department_id. Also in your code, you have to generate the ids yourself since you don't set them to auto-populate.

Django complex models and Nested Queries

How to write a complex query to
1) create a student,Course,OptionOne - example -
student_name=John,
rollno = 20
course1 = this field will refence a field in OptionOne, OptionOne will
reference the course desired. enter code here
**illustration** - John Selects mathematics as the first option, while Mike
selects Geoography as Option One, Mathematics as Option Two
2) Select all students who opt mathematics as option one
3) Select the student alongwith the course he opted
django.db import models
# Create your models here.
class Course(models.Model):
course_name = models.CharField(max_length=200)
course_code = models.CharField(max_length=200)
class PriorityOne(models.Model):
course = models.OneToOneField(Course, verbose_name=("Course"),
on_delete=models.CASCADE)
class PriorityTwo(models.Model):
course = models.OneToOneField(Course, verbose_name=("Course"),
on_delete=models.CASCADE)
class PriorityThree(models.Model):
course = models.OneToOneField(Course, verbose_name=("Course"),
on_delete=models.CASCADE)
class Student(models.Model):
student_name=models.CharField(max_length=200)
rollno = models.CharField(max_length=200)
course1 = models.OneToOneField(PriorityOne,on_delete=models.CASCADE)
course2 = models.OneToOneField(PriorityTwo,on_delete=models.CASCADE)
course3 = models.ForeignKey(PriorityThree, on_delete=models.CASCADE)
You can use a M:M field here if multiple students can take the same course. The course will have the ManyToMany field referencing the Student model. This means multiple course objects can be associated with a student and a Student can have multiple Courses. I know it seems a little weird on where you define the M2M field. If you want to set a priority list, then you can define an integer field with the top priority course pk. That is of course one way of doing it. Any of the syntax for M2M fields are here Django M2M docs. If you need further explanation, I will be glad to help.

How do I delete a single instance of an intermediate model in a Django Many-to-many (through) relationship?

This is a M2M relationship, that has the intermediate model 'Membership' (the intermediate model stores extra information about the relationship between a student and a course, using the 'through' keyword). In my case the extra relationship is the grade a student has in each of his courses. MY PROBLEM IS: I can't find a way in django to delete/remove only one of the relationships between one of the courses and the grade the student has.
class Student(models.Model):
name = models.CharField(max_length=128)
def __str__(self):
return self.name
class Course(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Student, through='Membership')
def __str__(self):
return self.name
class Membership(models.Model):
student = models.ForeignKey(Student, on_delete=models.CASCADE)
group = models.ForeignKey(Course, on_delete=models.CASCADE)
grade = models.CharField(max_length=64)
Since 'Membership' is an intermediate model, it disables the remove(), that would be accesible in a normal ManyToMany relationship.
You can use the clear() method, but his would remove every grade the student has in a course relationship. For example: If 'Carlos' was in 5 different courses with 5 different grades for each course, and also some other student 'Maria'
c = Course
c.members.clear()
would clear every grade relationship. You can see another example in the docs:
https://docs.djangoproject.com/en/2.0/topics/db/models/#extra-fields-on-many-to-many-relationships
And if I try to use the remove() method I get an attribute error:
m1 = 'instance of a Membership'
m1.remove()
AttributeError: 'Membership' object has no attribute 'remove'
In the django admin, I am able to remove a single 'Membership object'==='grade relationship' but I can't figure out a way to remove it on the shell or on my code that does't use the clear() method (which does't work form me cause it clears every relationship)
Please Help :///
You should just delete the membership.
m1.delete()

How to use django ORM for dynamic binding relation?

Well, this is the problem, I have a username column and I defined it in the models.py.
And a user may take some courses( the course may changes in the future), the relation between user and courses is 1 vs multi, which means a user can take multi courses and a courses could be taken by several users.
I am new to django and DB design, how to represent this in Django with ORM?
def user(models.Model):
name = models.CharField(max_length=30)
class courses(models.Model):
course = models.CharField(max_length=100)
Following #djsutho thought, define a many-to-many relationship:
class user(models.Model):
name = models.CharField(max_length=30)
courses = models.ManyToManyField(courses)
class courses(models.Model):
course = models.CharField(max_length=100)
Then, for example, querying courses per user would be as easy as:
courses.objects.filter(user__name='Bob')
Also note that, by Django model naming convention, model class names should start with a upper case letter: user should be User, courses - Courses.
Also note that the model name should not be in a plural form - better name courses as Course. Also better rename course field to name.
So, finally, here's the picture:
class User(models.Model):
name = models.CharField(max_length=30)
courses = models.ManyToManyField(Course)
class Course(models.Model):
name = models.CharField(max_length=100)
Hope that helps.