Table as field in model - django

I have such models:
class Department(models.Model):
name = models.CharField(max_length=30)
schedule = models.ForeignKey('Schedule', on_delete=models.CASCADE)
class Schedule(models.Model):
post_name = models.CharField(max_length=30)
shift_start = models.TimeField(auto_now=False, auto_now_add=False)
shift_end = models.TimeField(auto_now=False, auto_now_add=False)
Each department have a schedule - some [post_name, shift_start, shift_end] lines for each post. If use ForeignKey there will be only one line instead of a list. Is it possible to create some Schedule tables and link each with certain Department?

Foreign key defines a 1 to N relationship between your models. If I understood right you would like 1 department to have N schedules. To achieve this each schedule should have a foreign key defining which department it belongs to.
So you should use ForeignKey for that, but put it in your Schedule model.
Here is how it should look:
class Department(models.Model):
name = models.CharField(max_length=30)
class Schedule(models.Model):
post_name = models.CharField(max_length=30)
shift_start = models.TimeField(auto_now=False, auto_now_add=False)
shift_end = models.TimeField(auto_now=False, auto_now_add=False)
department = models.ForeignKey(Department, on_delete=models.CASCADE, related_name='schedules')
Then after you've created a department and a couple of schedules for that department you can access them like so:
(lets assume the created department primary key is 1)
Department.objects.get(pk=1).schedules.all()

Related

How to inner join tables based on ManyToManyField and group by a parameter and get latest one in Django?

I have two models with ManyToManyField relationship:
class Education(models.Model):
title = models.CharField(default=None, max_length=100)
content = models.TextField(default=None)
price = models.ManyToManyField(Price)
class Price(models.Model):
cost = models.CharField(default=None, max_length=20)
created_at = models.DateTimeField(auto_now=True, null=True, blank=True)
I can fetch all rows like this:
result = Education.objects.filter(price__in=Price.objects.all()).select_related('Price')/
.values_list('title', 'content', 'price__cost', 'price__created_at')
But now i want to group by education.id and the cost parameter should be latest parameter that inserted(based on created_at).
So i want to have list of all Education with latest cost that inserted for every education.
Will it work for you, It will return the respective id
Education.objects.filter(price__in=Price.objects.all()).select_related('Price').values('id').annotate(price_id=Max('price__id'))

Django tables connection

I have 3 django tables connected like this:
Is there anyway to make a query for table Table that will get id_equip from table equip?
models.py
class Vendor(models.Model):
vendor_name = models.CharField(max_length=50)
def __str__(self):
return self.vendor_name
class Equipment(models.Model):
equipment_name = models.CharField(max_length=50)
id_vendor = models.ForeignKey(Vendor, on_delete=models.CASCADE, default=None)
def __str__(self):
return self.equipment_name
class Table(models.Model):
table_name = models.CharField(max_length=100)
id_vend = models.ForeignKey(Vendor, on_delete=models.CASCADE, default=None)
id_equip = models.ManyToManyField(Equipment)
This part of the django docs is relevant and helpful, I definitely recommend your review at least that section and ideally the whole page.
Your models are already denormalized as evidenced by Table.id_equip which relates to Equipment so you could do:
table = Table.objects.get(SOME_FILTER)
equipment_ids = list(table.id_equip.all().values_list('id', flat=True))
If you wanted to go through the vendor I'd suggest:
table = Table.objects.get(SOME_FILTER)
equipment_ids = list(Equipment.objects.filter(vendor_set__table_set=table).values_list('id', flat=True))
I would recommend that you don't name your relationship fields with id_. With an ORM, these fields should represent the instances of the Model they are mapping to. For example:
class Table(models.Model):
name = models.CharField(max_length=100)
vendor = models.ForeignKey(Vendor, on_delete=models.CASCADE, default=None)
equipment = models.ManyToManyField(Equipment)
If you're trying to create the model on top of an existing table, you can make use of the db_column parameter when defining the field.
vendor = models.ForeignKey(Vendor, on_delete=models.CASCADE, default=None, db_column="id_vend")

how can each user get increment and unique id on same table in django

Each time i want to add an invoice, i want to have a unique invoice_id which is an increment number (+1), but the problem is that i have a multiple users app, so i get the error that this invoice_id already exist. how can i customize the ids so each user can have its ids following the latest of same user.
class Company(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=64)
class Invoice(models.Model):
company = models.ForeignKey('Company', on_delete=models.CASCADE)
invoice_id = models.CharField(max_length=20, unique=True)
name = models.CharField(max_length=256)
add an last_invoice field in your company record. Then let it do the work for you by adding a function that generates new invoice:
class Company(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=64)
last_invoice = models.CharField(max_length=20)
def get_invoice(self):
l_newNum = self.last_invoice + '1' #your number here
self.last_invoice = l_newNum
self.save()
return l_newNum
class Invoice(models.Model):
company = models.ForeignKey('Company', on_delete=models.CASCADE)
#you no longer need unique as it will create a mess between companies
invoice_id = models.CharField(max_length=20)
name = models.CharField(max_length=256)
def save(self):
self.invoice_id = self.company.get_invoice()
super(Invoice,self).save()
You need to fill in the details here and there, but this should work for you. IDeally I would suggest that the get_invoice is actually used to automatically create Invoice entry for the company, but this would depend on the concrete case you are building.

Django intermediate table with a many-to-many field instead foreign key?

I have 2 models in my application:
User
Tower
My goal is to associate many towers to a user using an intermediate table because I need to add a period of time.
So I have something like this in my models:
class Tower(models.Model):
name = models.CharField(max_length=128)
class User(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField('Tower', through='Dates')
class Dates(models.Model):
user = models.ForeignKey('User', on_delete=models.CASCADE)
tower = models.ForeignKey('Tower', on_delete=models.CASCADE)
begin_date = models.DateTimeField()
end_date = models.DateTimeField()
But my goal was to have the field tower in class Dates to a many-to-many like this:
tower = models.ManyToManyField('Tower', blank=True)
So that i can associate many towers to a user in a certain period. But unfortunately django says that i need to use forgeignkey to Tower and User classes.
Have any solution for this? To apply directly the many-to-many field in the intermediate table? Or I must create a new class, sort of a GroupTower, that have a many-to-many field to the Tower class? Something like this:
class Tower(models.Model):
name = models.CharField(max_length=128)
class GroupTower(models.Model):
tower = models.ManyToManyField('Tower', blank=True)
class User(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField('Tower', through='Dates')
class Dates(models.Model):
user = models.ForeignKey('User', on_delete=models.CASCADE)
tower = models.ForeignKey('GroupTower', on_delete=models.CASCADE)
begin_date = models.DateTimeField()
end_date = models.DateTimeField()
Thanks in advance.
There is so many ways that you can design the database.
An example:
class Tower(models.Model):
name = models.CharField(max_length=128)
class User(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField('UserTower')
class UserTower(models.Model):
user = models.ForeignKey('User', on_delete=models.CASCADE)
tower = models.ManyToManyField('Tower')
begin_date = models.DateTimeField()
end_date = models.DateTimeField()
In this design you can add many UserTower instances to a user and each UserTower instance can have many towers.
Now if you query the members for a user:
User.objects.get(pk=1).members.all()
You will have members grouped by periods of time if you saved them this way but it requires you to write some codes to avoid duplicates for begin_date, begin_date and user.
And now if you need towers:
user_members = User.objects.get(pk=1).members.all().values_list('tower', flat=True)
towers = Tower.objects.filter(pk__in=user_members).distinct()
This design is okay only if you really don't want duplicates with same begin_date and begin_date which i can't find a reason for.
You can still have all the features if you add multiple instances with same begin_date, begin_date and user but different tower.

getting the pk of other model from one model

models.py
class Customer(models.Model):
customer_name = models.CharField(max_length=50)
address = models.CharField(max_length=100)
bill_no = models.CharField(max_length=8)
class Sell(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
date = models.DateField(auto_now_add=True)
total = models.IntegerField()
vat = models.IntegerField()
How do get the customer id from Sell model/object?
like Sell.objects.get(pk=..)
You can get using foreign key concept.
Here you can get the pk of Customer model using customer field of Sell model, it will be customer__pk.
Similarly customer_name you can get by customer__customer_name and address using customer__address and bill_no using customer__bill_no.
Note: Remember it is fieldnameincurrentmodel__othermodelfieldname, it is the double underscore.
Sell.objects.get(pk=customer__pk)