Django dynamic form subclass list - python-3.x

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.

Related

How to load data from multi-level nesting object

```
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

Two properties that relate to each other in another model

Sorry that the title might be confusing but I'm not native english speaker and very new to django terms.
I have a scenario like this: A department can have many branches. I have a student model where he has two properties, Department and Branch.
When I select his department , I want it to accept (and show in admin panel) only the branches that are related to that department , my code so far is this:
class Entity(models.Model):
id = models.UUIDField(primary_key=True , default = uuid.uuid4, editable=False)
class Department(Entity):
name = models.CharField(max_length=100, null=False)
class Branch(Entity):
name = models.CharField(max_length=100, null=False)
dep = models.ForeignKey(Department, related_name='branches', on_delete=models.CASCADE)
class Student(Entity):
#Some Fields here
department = models.ForeignKey(Department, related_name='students', on_delete=models.CASCADE)
branch = models.ForeignKey(Branch, related_name='students', on_delete=models.CASCADE)
Assuming I have a 2 departments (CE and CS), CE has 2 branches and CS has 3 branches , What I want is, when I choose a student's department in the admin panel, I want the branches to be shown (to select from) only the one that exists on that department , what I'm getting is 5 branches (in this example).
How can I solve this ?
NOTE: I haven't played with anything related to the admin panel except registering the models.
Thanks in advance and sorry if the title or any other part is not very correct.
There are two solutions:
override save() function and check branch.
Check branch inside form by overriding clean_branch()
It's better to implement both.

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 Queryset Values of Children and Parent

I am looking for a way to retrieve a parent field during a query of the the children records. At this time I have the following example model.
class Record(models.Model):
event_title=models.CharField(max_length=500)
event_description=models.CharField(max_length=4000)
class SecondTable(models.Model):
event_code=models.ForeignKey(Record, default=0, on_delete=models.CASCADE)
wasfun=models.BoolField(default=True)
When I view the values of the queryset and select_related below, the values from the parent don't seem to be included (i.e. event_description). However, the .query property shows all the fields being selected.
SecondTable.objects.all().select_related("event_code").values()
Is there a way to see all values from the joined tables? Sorry for a newbie question. Thanks!
I think not in only one line, but you can try with next:
values_second_table = [s.name for s in SecondTable._meta.fields]
values_first_table = ['event_code__{}'.format(r.name) for r in Record._meta.fields]
my_values = values_second_table + values_first_table
SecondTable.objects.all().select_related("event_code").values(*my_values)

Resources