Django Model Inheritance - Query parent model for 'unknown' relationship - python

Take the following as an example:
class Manufacturer(models.Model):
name = models.CharField(max_length=200, blank=False)
slug = models.SlugField(max_length=200, blank=False, unique=True)
class Category(models.Model):
name = models.CharField(max_length=200, blank=False)
slug = models.SlugField(max_length=200, blank=False, unique=True)
class Product(models.Model):
category = models.ForeignKey(Category, related_name='products')
manufacturer = models.ForeignKey(Manufacturer, related_name='products')
name = models.CharField(max_length=50, blank=False)
slug = models.SlugField(max_length=200, blank=False, unique=True)
class CarMixin(models.Model):
color = models.CharField(max_length=50, blank=False)
num_wheels = models.IntegerField()
class CellPhoneMixin(models.Model):
screen_size = models.IntegerField()
class Car(Product, CarMixin):
pass
class Food(Product):
pass
class CellPhone(Product, CellPhoneMixin):
pass
what I am trying to do is create a 'base' class called Product and apply a variety of 'sub-product-types' using Model Inheritance.
The reason I am not using the Django's 'Abstract Model Inheritance' is because I actually want a table in my DB to hold all the products, so I can make a query like Product.objects.all() to get all the products, then type product.car to get all the field values for the related Car object.
However, the problem I am running into is that a product can have a relationship with any one of Car, Food or CellPhone. So, I can't do product.car if it has a relationship with Food. There is no way in knowing which 'relationship' a Product object has. Is it related to Car? Food? CellPhone?
How should I approach this? Is there a better database schema I should be using?

Related

Should I use oneToMnay or ManyToMany in django

I am new in django and trying to create a website where I can search for vehicles and see what parts I have for this vehicle.
I have two databases, one with vehicles and one with parts:
class Vehicle(models.Model):
vehicle_id = models.BigIntegerField(primary_key=True)
vehicle = models.CharField(max_length=255)
def __str__(self):
return self.vehicle
class Part(models.Model):
part_id = models.BigIntegerField(primary_key=True, db_column='part_id')
part_name = models.CharField(max_length=255, db_index=True, null=True)
catalog_code = models.CharField(max_length=255, null=True)
price = models.CharField(max_length=255, default=None, null=True)
description = models.CharField(max_length=255, default=None, null=True)
vehicle_id = models.ForeignKey(Vehicle, on_delete=models.PROTECT, null=True)
def __str__(self):
return self.part_name
Now I using oneToMany, but can't figure out if it is correct and how can I see all parts for one vehicle
You implemented the relationship correctly. One to many is a way to go here.
You can make your life easier by defining related_name in the ForeighKey:
vehicle_id = models.ForeignKey(Vehicle, on_delete=models.PROTECT, null=True, related_name="parts")
and use the following constructs when referring to the vehicle parts:
myvehicle.parts.all()
myvehicle.parts.filter(part__part_id=1)
Side comment: I do not think that it was a good idea to define id fields explicitly. Django sets model id fields automatically (and defines them as primary keys).

Django: how to count posts related to a category in django?

i have a model class Category and also a model class Course. i want to count all the courses that are related to a model e.g: Web Devlopment - 26 Courses i dont know how to go about this since the this are two diffrent models.
class Category(models.Model):
title = models.CharField(max_length=1000)
class Course(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
course_title = models.CharField(max_length=100, null=True, blank=True)
course_category = models.ForeignKey(Category, on_delete=models.DO_NOTHING, null=True, blank=True)
First, you need to set the related_name attribute in the course_category field.
class Course(models.Model):
...
course_category = models.ForeignKey(Category, realted_name="courses" on_delete=models.DO_NOTHING, null=True, blank=True)
Next, you can use this name to aggregate the query as the following.
from django.db.models import Count
cateogries = Category.objects.annotate(number_of_courses = Count("courses")).all()
Then, each of the categories will have the number_of_courses field that indicates the number of courses.

Django, have model to be related to many instances of itself

I have a model:
class Industry(models.Model):
name = models.CharField(max_length=60, unique=True, null=False, blank=False)
I want it to have a sub_industries field that will hold all of its sub industries, which should be instances of Industry model.
I cannot be ManyToMany because each industry has only one parent industry.
You can add a ForeignKey to itself with:
class Industry(models.Model):
name = models.CharField(max_length=60, unique=True)
parent_industry = models.ForeignKey(
'self',
null=True,
related_name='sub_industries'
)
You can use NULL/None to express that an industry has no parent.

Many-to-many relation and form with extra field

I am struggling with Many-to-Many model and form. What is the best way to show extra level field when creating a new Person with skill. I am going also to edit it later.
I am trying to achieve an effect in forms like that:
[input text] name
[select] skill name (there are choices in the model)
[input text] level of the skill
I tried things which people were suggesting but I couldn't make it to work. For example inlineformset + through.
Later on, I would like also to give the user a chance to add multiple sets of skill+level, maybe it is worth to think about it in advance?
My models and form:
class PersonSkill(models.Model):
person = models.ForeignKey('Person', on_delete=models.CASCADE)
skill = models.ForeignKey('Skill', on_delete=models.CASCADE)
level = models.CharField(max_length=50, choices=[(1, 'working'),
(2, 'advanced'),
(3, 'champion')], null=True, blank=True)
class Skill(models.Model):
name = models.CharField(max_length=50, null=True, blank=True)
def __str__(self):
return self.name
class Person(models.Model):
name = models.CharField(max_length=30, null=True, blank=True)
skill = models.ManyToManyField('Skill', through='PersonSkill', blank=True)
def __str__(self):
return self.name
class PersonForm(forms.ModelForm):
class Meta:
model = Person
fields = ('name',)

filter on foreign and many to many relationship field

I'm struggling getting the right query for my project. Here is an example of my model :
from django.db import models
class Brand(models.Model):
name = models.CharField(max_length=30)
handle = models.SlugField(max_length=30, unique=True, null=True, blank=True)
def __unicode__(self):
return self.name
class Product(models.Model):
product_id = models.SlugField(unique=True)
brand = models.ForeignKey(Brand, on_delete=models.SET_NULL, blank=True, null=True)
collections = models.ManyToManyField('Collection')
def __unicode__(self):
return self.product_id
I am trying to get all the Brand_name based on the value of the Product.collection
Eg: Shoes is a Product.collection, I want to get all the Brand_name for collection - shoes
I tried __ method also. Somehow it is not working.
You should try something like this:
Brand.objects.product_set.filter(collections__name="Shoes").values('brand__name')
Brand.objects.filter(
product__collection=product.collection
).values_list('name', flat=True).distinct()
product is instance of Product.
Add a related_name to your foreign key like below,
brand = models.ForeignKey(Brand, on_delete=models.SET_NULL, blank=True,
null=True, related_name='products')
And then you can try below query and it'll return you a list of all the Brand.name which has product__collections_name='Shoes'.
Brand.objects.filter(products__collections__name='Shoes').values_list('name', flat=True)

Categories

Resources