How to load data from multi-level nesting object - python-3.x

```
when i do the School.objects.filter() query , how to load student object in single
query using School.objects.filter()
```
class School(models.Model):
name = models.CharField(max_length=50)
grade = models.ForeignKey(Grade)
class Grade(models.Model):
name = models.CharField(max_length=10)
class Student(models.Model):
name = models.CharField(max_length=50)
grade = models.ForeignKey(Grade)
when i try to load the student object using the school.objects.filter(), its load only school object, when i use select_related('grade'), its load grade object in single sql query how can i use select_related('student'), with school.objects.filter()

Going from Grade to Student is a reverse-ForeignKey relation, which is many-to-one, not one-to-one. You can't do this with select_related.
I'm not absolutely sure but I think you can use prefetch_related:
School.objects.filter(...).prefetch_related( 'grade__students')

you can do something like this:
schools = School.objects.filter(...).prefetch_related('grade__student_set')
for school in schools:
students_for_school = school.grade.student_set.all()
print(students_for_school)
One thing to note is that prefetch_related() will make an additional query here, so this will require two queries
https://docs.djangoproject.com/en/4.0/ref/models/querysets/#prefetch-related

Related

how to make a field unique based on another filed in django models?

I want to make a field unique based on another field in the same model, this is my model:
class Shop(models.Model):
name = models.CharField(max_length=50)
class Product(models.Model):
name = models.CharField(max_length=50, unique=True)
shop = models.ForignKey(Shop, on_delete=models.CASCADE)
I want the product's name to be unique only based on Shop, for example, if we have the product a from shop a, shop a can not make another product with the name a but shop b can make a product with name a.
for example we have name = models.CharField(unique_for_date=date_field) in models, which make the name unique for the date at date_field.
is there anything like unique_for_date?
can I handle this operation in models or I should try to handle it in view or form?
On your Product table:
class Product(...):
...
class Meta:
unique_together = ('shop', 'name')
This will ensure Products must have a unique name across the Shop they are related to.

Add element in many to many field and preserve order

class Country(Models.Model):
code = models.CharField(max_length=50)
name = models.CharField(max_length=500)
class Meta:
unique_together = (('code', 'name'),)
db_table = 'md_country'
class UserSettings(models.Model):
...
default_countries = models.ManyToManyField(Country, db_table='user_default_countries', related_name='default_countries')
I have two models inside django models, what im trying is when i add Country models to default_countries i want to preserve order. Currently when i append manytomany field django automatically sort by Country name (alphabetical order)
I have this code
# iterate one by one to preserve fetching order
country_models = [Country.objects.get(id=_id) for _id in request.data[default_countries]]
user_settings.default_countries.clear()
for c in country_models:
user_settings.default_countries.add(c)
After this when i inspect user_settings.default_countries i have ordered countries by name in alphabetical order.
I want to preserve when adding element. If i want to add France and Australia and i order the list like that i on the end when i pull data from db i want it to be ordered like that. Now on this example i have Australia then France.
EDIT:
I checked the database and when inserting the data, it insert in right order
For example if i want France(73) then Australia(13), France has smaller id so its inserted first. There is a problem with django when pulling the data from database.
So as I understand correct you want to sort by insert order:
someSetting = UserSettings.objects.first()
countries = someSetting.default_countries.order_by('id')
I found the workaround.
Firstly i defined new property inside model where default_countries is.
#property
def ordered_default_countries(self):
return self.default_countries.all().order_by('-id')
Then in serializer where i serialize this field i just pointed default_countries field to ordered_default_countries.

Django dynamic form subclass list

I'm trying to understand how can I define model as a class containing 2 integers and 1 charfield and then make it a part of another model.
Example of data I need
I guess in object oriented programming I should define model class like this:
class Component(models.Model):
pipe_type = models.CharField(max_length=200)
length = models.IntegerField()
amount = models.IntegerField()
And then I don't know how can I use it with django models, it should be something like this:
class Item(models.Model):
name = models.CharField()
components_needed = ? LIST OF Component class ?
Also, since components needed size will wary for objects, it should be possible to extend it's size with button on a page, for example there could be 3 input fields and next to them would be "+" and "-" button to add/remove another set of 3 input fields
I spent entire day looking for solution, but at this point I'm not sure if django can handle this. I'm new to python and django, so there are many things I do not understand.
I will be grateful for any kind of help
the only way now( you canot put multi FK in one cell) is like django itself using with user/groups so you need 3 models.
in django there is group, user and user_group so i suggesting for you:
class Component(models.Model):
pipe_type = models.CharField(max_length=200)
length = models.IntegerField()
amount = models.IntegerField()
class Item(models.Model):
name = models.CharField()
class Item_Component(models.Model):
Component = models.ForeignKey(Component, on_delete=models.CASCADE)
Item = models.ForeignKey(Item, on_delete=models.CASCADE)
so now in third model you can have multiple rows with item and with diffrent component.
open yours db viewer app and see django user_group table.

Yii2 : Getting class name from relation attribute

I went through all API documentation of Yii 2.0 to find a way to reverse back to relation class name from a model attribute.
let us suppose that class Customer has a relation
$this->hasOne(Country::className(), ['id' => 'countryId']);
and in a controller function the parameter was the attribute "countryId". How is it possible to detect the class name for the related model
Get the name of the class by removing Id from the end of the variable and capitalize it. But I cannot image any situation where this would be a normal development practice. You can also define am array to make this translation for the model.
You can try to use http://php.net/manual/en/intro.reflection.php to get the names of all the functions and try to guess the name of the relation / model based on the name of the field. If you name your classes and relation fields in a proper name then you should be able to try to again guess the model.
This still feels like a hack, create a function that returns the name of the model based on the field... easiest solution. I know you try to be lazy but this is a hacky way of programming.
I'm not very clear on what data you have to start with here. If you only have a column countryId I am not sure. But say you have the relation name 'country' and the following code in your Customer model:
public function getCountry()
{
return $this->hasOne(Country::className(), ['id' => 'countryId']);
}
This is what I would do:
$relationName = 'country';
$customer = new Customer;
$relation = $customer->getRelation($relationName);
$relationModelClass = $relation->modelClass;
You could look at \yii\db\ActiveQuery::joinWithRelations() for how they do it.

Design a document database schema

I'm vainly attempting to learn how to use object databases. In database textbooks the tradition seems to be to use the example of keeping track of students, courses and classes because it is so familiar and applicable. What would this example look like as an object database? The relational database would look something like
Student
ID
Name
Address
Course
ID
Name
PassingGrade
Class
ID
CourseID
Name
StartTime
StudentClass
ID
ClassID
StudentID
Grade
Would you keep StudentClasses inside of Classes which is, in turn, inside Course and then keep Student as a top level entity?
Student
ID
Name
Address
Course
ID
Name
Classes[]
Name
StartTime
Students[]
StudentID
So you have Courses, Students and Classes, which are parts of Courses and visited by Students? I think the question answers itself if you think about it. Maybe it's clearer if you go away from the pure JSON of MongoDB and look at how you would define it in an ODM (the equivalent of an ORM in RDBs) as document based DBs don't really enforce schemas of their own (example is based on MongoEngine for Python):
class Student(Document):
name = StringField(max_length=50)
address = StringField()
class Attendance(EmbeddedDocument):
student = ReferenceField(Student)
grade = IntField(min_value=0, max_value=100)
class Class(EmbeddedDocument):
name = StringField(max_length=100)
start_time = DateTimeField()
attendance_list = ListField(EmbeddedDocumentField(Attendance))
class Course(Document):
name = StringField(max_length=100)
classes = ListField(EmbeddedDocumentField(Class))
This would give you two collections: one for Students and one for Courses. Attendance would be embedded in the Classes and the Classes would be embedded in the Courses. Something like this (pseudocode):
Student = {
name: String,
address: String
}
Course = {
name: String,
classes: {
name: String,
start_time: DateTime,
attendance_list: {
student: Student,
grade: Integer
}[]
}[]
}
You could of course put the grade info in the student object, but ultimately there really isn't much you can do to get rid of that extra class.
The whole point of an OODBMS is to allow you to design your data model as if it were just in memory. Don't think of it as a database schema problem, think of it as a data modelling problem on the assumption that you have a whole lot of VM and a finite amount of physical memory, You want to make sure that you don't have to boil an ocean of page faults (or, in fact, database I/O operations) to do the operations that are important.
In a pure OODB, your model is fine.

Resources