In my models.py I have a model 'courses'. A course can have one name and one description but multiple links and instructors. I tried to stablish this using foreign key relationship. Now, lets say I want access the name of a particular course, I can do so by c.name where c would be an object obtained by using a filter query. But how would I access lets say the second instructor of that course? Also how would I add a new instructor to that course?
class courses(models.Model):
name=models.CharField(max_length=200)
description=models.TextField()
class links(models.Model):
link=models.CharField(max_length=200)
course=models.ForeignKey(courses,on_delete=models.CASCADE)
class instructors(models.Model):
inst=models.CharField(max_length=200)
course=models.ForeignKey(courses,on_delete=models.CASCADE)
Adding a new instructor requires a courses object. So, you can do the following,
course = courses.objects.create(name="OS", description="course desc")
instructor = instructors.objects.create(inst="name", course=course)
How are you defining the order of instructors? If it is the creation of instructors object. then, you can access the second instructor of a course as the following.
all_instructors = instructors.objects.filter(course=course)
if len(all_instructors) > 1:
second_instructor = all_instructors[1]
N.B. You should rename your models to singular noun i.e. Course, Link, Instructor
Related
I have 3 classes and i want to filter them based on criteria taken form 3 classes. I am very new to django and especially model. Need your help.
Student, group and nondemandgroup are tables in my Db.
class Students():
name=models.CharField(max_length=200)
surname=models.CharField(max_length=200)
class Group20():
name=models.CharField(max_length=200)
studentss=models.ManyToManyField(Students)
math=models.DecimalField(decimal_places=2,max_digits=1000)
english=models.DecimalField(decimal_places=2,max_digits=1000)
class Nondemandgroup():
name=models.CharField(max_length=200)
studentss=models.ManyToManyField(Students)
acting=models.DecimalField(decimal_places=2,max_digits=1000)
cooking=models.DecimalField(decimal_places=2,max_digits=1000)
i want to get list of student who's final grade is met by fowlloing criteria:
final_grade = group20.objects.filter(math__gt=60, ((math+english+acting)/3)__gt=70)
acting is within nondemandgroup class so my final_grade doesn't work it says no such column as acting.
How to to make acting column work ? I tried Foreign key but it does not work and gives an error.
Or should i create a new model and filter within it where i will create foreign keys of 3 models ?
I am quite confused as i am very new to Django and models are confusing. Explored web however in my case i misunderstand smth and the formula does not work.
Let's go step by step. We want students matching the a given criteria.
First thing we see wrong is student is not connected to group in any way. So let's connect the students with groups
from django.db import models
class Student(models.Model):
name=models.CharField(max_length=200)
surname=models.CharField(max_length=200)
class Group20(models.Model):
student = models.ForeignKey(Student, on_delete=models.CASCADE)
name=models.CharField(max_length=200)
math=models.DecimalField(decimal_places=2,max_digits=1000)
english=models.DecimalField(decimal_places=2,max_digits=1000)
class Nondemandgroup(models.Model):
student = models.ForeignKey(Student, on_delete=models.CASCADE)
name=models.CharField(max_length=200)
acting=models.DecimalField(decimal_places=2,max_digits=1000)
cooking=models.DecimalField(decimal_places=2,max_digits=1000)
Now let's come to the part calculating the final grade
Lets get all user's from group20 model who have more than 60 in math. We also need the math and english to calculate average score along with acting. So let's get that value as well.
group20_objs = Group20.objects.filter(math__gt=60).values_list('student__name', 'math', 'english')
This will give value in the following format
[("studentA", "math_score_of_A", "english_score_of_A"), ...]
[("Chantel", "100", "100"), ("Chantel1", "90", "85"),..]
Now lets get the students who's average of math, english and acting is above 70.
final_students = []
for item in group20_objs:
student_name, math_score, english_score = item
# Get acting score for user
# Hoping student will have record here as well
acting_score = Nondemandgroup.objects.filter(student__name=student_name).first(). acting
if (acting_score + math_score + english_score)/3 >= 70:
final_students.append(student_name)
Now final_students list will contains students names with grades higher than 70. Do try to mix up the models if you want.
Also i recommend going through django models docs for a better understanding
Is there a by the book way of allowing a user to add columns to a sites database table. For example, if the site was about animals, one user might want to have stats like, 'walks per week' and 'type of food' about their breed of dog. but another user might want to keep track of how much milk their goat is producing.
So if i have an 'Animal' class with come basic info. like, 'breed', 'animal name', 'DOB', 'DOD'. But then, in the front end have a form that will allow the users to add all the other columns they would like.
Is this possible? hope I've explained it well enough.
#WillemVanOnsem already mentioned some good options in the comments. I'm going to chime in to say that modifying your schema's structure based on user input is an extremely bad idea and opens another avenue for abuse... for Django in particular, it means you either can't use the ORM's migration facilities for some of your models, or you probably have to do some really awful automation.
If your animal types are well-defined and consistent, you can consider (carefully) making them subclasses of the Animal model. Otherwise, this would be the simplest way to handle it (note that the following isn't valid code, it needs required arguments for the field types):
class AnimalAttribute(models.Model):
animal = models.ForeignKey(Animal)
name = models.CharField()
value = models.CharField()
This works best if attributes aren't shared, e.g. users are directly inputting their animals' names and attributes, not picking from an existing list.
If you need to provide a normalized list of attributes users can pick from (actual EAV, which is something you should avoid if possible, since it moves some of your data structure from code into the data persistence layer), doing that in your models is a little more complex. For example:
class Species(models.Model):
name = models.CharField()
class SpeciesAttribute(models.Model):
species = models.ForeignKey(Species)
name = models.CharField()
class Animal(models.Model):
name = models.CharField()
species = models.ForeignKey(Species)
class AnimalAttributeValue(models.Model):
animal = models.ForeignKey(Animal)
attribute = models.ForeignKey(SpeciesAttribute)
value = models.CharField()
I have the following model.
class Car(models.Model):
owner = models.ForeignKey('Driver')
class Country(models.Model)
name = models.CharField(max_length=255)
class Driver(models.Model):
name = models.CharField(max_length=255)
age = models.IntegerField()
country = models.ForeignKey('Country')
I want to select the name of drivers owning a car.
Car.objects.all().values('owner__name')
Do I need to use select_related() method, to avoid a join for each object, or it is redundant because implicit with values() method?
Car.objects.all().select_related('owner').values('owner__name')
In the same way, I want, this time, the name of countries with drivers owning a car. Which one is the best?
Car.objects.all().values('owner__country__name')
Car.objects.all().select_related('owner', 'country').values('owner__country__name')
Car.objects.all().select_related('owner__country').values('owner__country__name')
First, all the occurrences of .all() in your examples can be deleted; the manager (.objects) already has almost all methods of the QuerySet, except for .delete().
.select_related is only helpful when your eventual query returns model instances; then, all the foreign key of each instance will be pre-loaded.
But if you are using .values you are getting dictionaries, and there are no foreign key attributes to pre-load. So it should not be used in that case.
When you do .values('owner__name') Django already sees that it needs to join owners and cars, no extra queries are done.
In the last one you want Countries, so use Country.objects:
Country.objects.filter(driver__car__isnull=False).values('name')
I have the following models:
class Profile(models.Model):
user = models.ForeignKey(User)# User can have more than one profile
class Order(models.Model):
ship_to = models.ForeignKey(Profile)
class Shipping(models.Model):
order = models.ForeignKey(Order)# one order can have more than one shipping
shipping_company = models.ForeignKey(Shipping_company)
class Shipping_company(models.Model):
name = ...
So now i have the following structure:
User > Receiver > Order > Shipping > Shipping_company
The question is: How can i get all User models, who ordered with specific Shipping company?
If i make a query like this
User.objects.filter(receiver__order__shipping__shipping_company__pk=1)
i get
FieldError: Relation fields do not support nested lookups
if i make something like this
sh_comp = items.objects.get(pk=1) # __unicode__ returns "FedEx"
User.objects.filter(receiver__order__shipping__shipping_company=sh_comp)
the result is
ValueError: Cannot query "FedEx": Must be "Receiver" instance.
This seemed to be a simple and trivial task, but i can't make it work.
One approach that can be taken is as following(I am only considering the four models you have presented in your question),
You have foreign key of Shipping company in Shipping model. So you can make use of model function here on Shipping_company model.
Take a look at this model function
class Shipping_company(models.Model):
fields...
def get_profiles(self):
shippings = Shipping.objects.filter(shipping_company=self)
users = list(set([x.order.ship_to for x in shippings]))
Explanation:
shippings = Shipping.objects.filter(shipping_company=self)
will return all the shippings for one Shipping company(FedEx in your case). Further loop through the shippings to get ship_to from order field.
PS: You can take it as reference and design your own solution.
Walkthrough:
Lets say there is shipping company 'FedEx'. So we do,
fedex = Shipping_company.objects.get(name='FedEx')
Now, when you call get_profiles on fedex, like
fedex.get_profiles()
what will happen is this.
fedex instance refers to self in get_profiles() function now.
Using self(fedex), we filter out shippings by fedex.
Then we loop through those shippings to get order per shipping and each of that order has a ship_to(profile) foreign key.
I guess, you are getting confused because of the return statement.
In elaborate fashion the whole function will look something like this
def get_profiles(self):
users = list()
shippings = Shipping.objects.filter(shipping_company=self)
for shipping in shippings:
order = shipping.order
#Now you have an order per shipping, so you do
if not order.ship_to in users:
users.append(order.ship_to)
return users
I have a probably quite basic question: I am currently setting up a database for students and their marks in my courses. I currently have two main classes in my models.py: Student (containing their name, id, email address etc) and Course (containing an id, the year it is running in and the assessment information - for example "Essay" "40%" "Presentation" "10%" "Exam" "50%"). And, of course, Student has a ManyToMany field so that I can assign students to courses and vice versa. I have to be able to add and modify these things.
Now, obviously, I would like to be able to add the marks for the students in the different assignments (which are different from course to course). As I am very unexperienced in database programming, I was hoping one of you could give me a tip how to set this up within my models.
Thanks,
Tobi
Perhaps the way to go about it is to have a separate class for assignment, something like this.
class Assignment(models.Model):
ASSIGNMENT_TYPES = (
('essay', "Essay"),
...
)
ASSIGNMENT_GRADES = (
('a+', "A+"),
('a', "A"),
...
)
student = models.ForeignKey("Student")
course = models.ForeignKey("Course")
assignment_type = models.CharField(choices=ASSIGNMENT_TYPES, max_length=15, default='essay')
progress = models.IntegerField()
grade = models.CharField(choices=ASSIGNMENT_GRADES, max_length=3, default="a+")
This way you have one assignment connected to one student and one course. It can be modified relatively easy if you have multiple students per one assignment, by adding another class (for example StudentGroup) and including it in the model.
Hope that this helps :)
Create a model called "Assessments", which has a foreign key to Course. In addition ,create a field called "Assessment Type", another called "Assessment Result" and a final one called "Assesment Date". Should look like this:
ASSESSMENTS = (('E','Essay'),('P','Presentation'))
class Assessment(models.MOdel):
course = models.ForeignKey('Course')
assessment = models.CharField(choices=ASESSMENTS)
result = models.CharField(max_length=250)
taken_on = models.DateField()
overall_result = models.BooleanField()
is_complete = models.BooleanField()
Each time there is an exam, you fill in a record in this table for each assessment taken. You can use the overall result as a flag to see if the student has passed or failed, and the is_complete to see if there are any exams pending for a course.
You should look at models.py file of classcomm,
a content management system written in Django for delivering and managing Courses on the Web.
It has following Models
Department
Course
Instructor
Mentor
Enrollment
Assignment
DueDateOverride
Submission
Grade
ExtraCredit
Information
Resource
Announcement
You may not need such a complex relationship for you case, but it's wort looking into it's models design.
You can find more details on homepage of this project.