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

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.

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).

Unique field value Django model

So, i have two models: RetailStore and Product. Product contains a ForeignKey to RetailStore and a field named sku. Basically what i need is to make sure that the sku field is unique into a store, but not between all stores, e.g:
Store1: Product(sku="sku1"), Product(sku="sku2"), Product(sku="sku3"), Product(sku="sku1") <- can't have this last one because it already exists.
Store2: Product(sku="sku1"), Product(sku="sku2"), Product(sku="sku3") <- This is ok
Store3: [...] <- Same goes for others Store.
My Models
class RetailStore(StandardModelMixin):
cnpj = models.CharField(
blank=False, null=False, unique=True, max_length=200, validators=[validate_cnpj], verbose_name="CNPJ"
)
[other fields...]
class Product(StandardModelMixin, SoftDeletionModel):
sku = models.CharField(blank=False, null=False, max_length=200, verbose_name="SKU")
[other fields...]
retail_store = models.ForeignKey(
RetailStore,
on_delete=models.CASCADE,
blank=True,
null=True,
related_name="products",
verbose_name="Retail Store",
)
You can use UniqueConstraint so you can have the same SKUs in different stores, but not in one.
class Product(StandardModelMixin, SoftDeletionModel):
...
class Meta:
constraints = [models.UniqueConstraint(
fields=['sku', 'retail_store'],
name='unique_sku_in_store'
)]
You'll need to apply validate_unique to this.
Django offers unique_together, but it grants uniqueness to a single model and not between models.
Docs: https://docs.djangoproject.com/en/dev/ref/models/instances/#django.db.models.Model.validate_unique

Multiple user types and ratings in Django

I'm making a DRF backend with three user types: customer, personal trainer and gym owner. I want all the fields in the CustomUser class to apply to each user type. I also want some specific attributes to each user type (for example photo only for personal trainer and gym owner). Is this the right way to do it?
# models.py
class CustomUser(AbstractUser):
USER_TYPE_CHOICES = (
('customer'),
('personal_trainer'),
('gym_owner'),
)
user_type = models.CharField(blank=False, choices=USER_TYPE_CHOICES)
name = models.CharField(blank=False, max_length=255)
country = models.CharField(blank=False, max_length=255)
city = models.CharField(blank=False, max_length=255)
phone = models.CharField(blank=True, max_length=255)
ratings = models.ForeignKey(Rating, on_delete=models.CASCADE, null=True)
created_at = models.DateField(auto_now_add=True)
def __str__(self):
return self.name
class Customer(models.Model):
user = models.OneToOneField(
CustomUser, on_delete=models.CASCADE, primary_key=True)
class PersonalTrainer(models.Model):
user = models.OneToOneField(
CustomUser, on_delete=models.CASCADE, primary_key=True)
photo = models.ImageField(upload_to='photos/%Y/%m/%d/', blank=True)
class GymOwner(models.Model):
user = models.OneToOneField(
CustomUser, on_delete=models.CASCADE, primary_key=True)
photo = models.ImageField(upload_to='photos/%Y/%m/%d/', blank=True)
I also have a ratings model. I want to be able to leave a rating as a customer to a personal trainer or a gym. Each rating will have a one to one relation with it's owner and it's target. I'm not sure however how I can make the relations..?
# models.py
class Rating(models.Model):
STAR_CONVERSION = (
(1, 'One Star'),
(2, 'Two Stars'),
(3, 'Three Stars'),
(4, 'Four Stars'),
(5, 'Five Stars'),
)
rating = models.PositiveSmallIntegerField(choices=STAR_CONVERSION)
caption = models.TextField(blank=True)
owner = models.OneToOneField(Customer, on_delete=models.CASCADE)
# I want a target as a one to one relation to either PersonalTrainer or GymOwner
target = models.OneToOneField(*either personal trainer or gym owner*)
You need to make both owner and target a ForeignKey rather than a OneToOneField. With the latter, you could only have one rating for every customer and one for every provider, which would be a bit restrictive :).
For PersonalTrainer and GymOwner, you need model inheritance. The parent model would either be an abstract class (with the data saved in the tables of the individual child models), or (preferably in this case as the fields of both models are the same) the data would be saved in the parent model (e.g. Provider), while the child models would be proxy models based on the parent model's data, but providing different behaviour where appropriate.
The Django docs have quite a lot to say about the different inheritance options.
class Provider(models.Model):
user = models.OneToOneField(
CustomUser, on_delete=models.CASCADE, primary_key=True)
photo = models.ImageField(upload_to='photos/%Y/%m/%d/', blank=True)
class PersonalTrainer(Provider):
class Meta:
proxy = True
class GymOwner(Provider):
class Meta:
proxy = True
class Rating(models.Model):
# ...
owner = models.ForeignKey(Customer, on_delete=models.CASCADE)
target = models.ForeignKey(Provider, on_delete=models.CASCADE)

django model field depend on the value of another field

The use case of my application is I will have various fields to fill and among them one is Industry field and another is Segment Field for brand. The industry field is like category that brand falls into. So, if i choose the industry as Health Care for XYZ brand then the segment field should show the items like 'Ayurveda', 'Dental Clinics' (all health care related items). Basically, its like sub-category.
Here is a sample model
class Industry(models.Model):
name = models.CharField(max_length=150, blank=True, null=True)
class Meta:
verbose_name = 'Industry'
verbose_name_plural = 'Industries'
def __str__(self):
return self.name
class Segment(models.Model):
industry = models.ForeignKey(Industry, related_name='segment', on_delete=models.CASCADE)
name = models.CharField(max_length=150, blank=True, null=True)
class Meta:
verbose_name = 'Segment'
verbose_name_plural = 'Segments'
def __str__(self):
return f'{self.industry.name} - {self.name}'
class BusinessModel(models):
industry = models.ForeignKey(Industry, blank=False, null=False, related_name='industry', on_delete=models.CASCADE)
# segements = models.ForeignKey()
total_investment = models.CharField() # will be choice field
This is a simple model and I have not created Segment model as I am not sure how to approach to this problem. I am just curios to know, if for such case, do i have to something special in models.py or in the view side. Such type of things get arise during development phase, thus, I want to be clear on problem solving pattern in django.
UPDATE
https://www.franchisebazar.com/franchisor-registration here if you choose industry inside Business model section, the segment will be updated accordingly.
You can have a 3 model design like
class Industry(models.Model):
name = models.CharField(max_length=150, blank=True, null=True)
class Segment(models.Model):
name = models.CharField(max_length=150, blank=True, null=True)
class Mapping(models.Model):
industry = models.ForeignKey(Industry)
segment = models.ForeignKey(Segment)
You need to define relations between your models. You can find documentation about ManyToMany relation here which is suitable in your case.
you can use ChainedForeginKey.. Check the below links
customizing admin of django to have dependent select fields
https://django-smart-selects.readthedocs.io/en/latest/installation.html

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

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?

Categories

Resources