Django QuerySets - Related Models - django

I have a set of related models - main points included below:
class OrganisationDetails(models.Model):
FormFieldOrgID = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
FormFieldOrgCode = models.CharField(max_length=10, verbose_name='Organisation Code',
help_text='Enter organisation identifier', default='NULL', )
FormFieldOrgName = models.CharField(max_length=75, help_text='Enter Organisation Name',
verbose_name="Organisation Name")
class DepartmentDetails(models.Model):
FormFieldID = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
FormFieldDeptName = models.CharField(max_length=75, help_text='Enter Department Name',
verbose_name="Department name") # name for a department
FormFieldDescription = models.CharField(max_length=200, help_text='Enter department description ',
verbose_name="Department description") # describe the department
class OrgDeptLink(models.Model):
FormFieldID = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
FormFieldDeptID = models.ForeignKey(DepartmentDetails, on_delete=models.CASCADE, related_name='DepartmentDetails',
verbose_name='Department', help_text='Select department') # department
FormFieldOrgID = models.ForeignKey(OrganisationDetails, on_delete=models.CASCADE, related_name='SubordinateRole',
verbose_name='Organisation', help_text='Select organisation')
class OIRLinkStakeholders(models.Model):
FormFieldOIRStakeLinkID = models.UUIDField(primary_key=True, default=uuid.uuid4(), editable=False)
FormFieldOIRStakeholderID = models.ForeignKey(DepartmentDetails, on_delete=models.CASCADE,
help_text='Select Internal Stakeholder',
verbose_name='Stakeholder ID') # TODO Set list to Organisation Departments
FormFieldOIR = models.ForeignKey(OIROverview, help_text='Select OIR Document Name', on_delete=models.CASCADE,
verbose_name='OIR ID') # TODO Default to be set to a selected organisation
I would like to get: FormFieldDepartmentName from class DepartmentDetails(models.Model) using pk from Orgdetails - extract from views.py:
def oirdetails(request, pk):
orgdetails = OrganisationDetails.objects.filter(FormFieldOrgID=pk)
oiroverview = OIROverview.objects.filter(FormFieldOrgDetailID=pk)
alldepartments = OrgDeptLink.objects.filter(FormFieldOrgID=pk)
currentstake = OIRLinkStakeholders.objects.filter(
FormFieldOIRStakeholderID__DepartmentDetails__FormFieldOrgID_id__exact=pk)
The variable for currentstake is the one im trying to relate to:
ive include a snapshot of the relationships below
Ive had a look at the documentation - but cant grasp the concept of ORM in django "yet".
ANy advice most welcome

currentstake = OIRLinkStakeholders.objects.filter(
FormFieldOIRStakeholderID__DepartmentDetails__FormFieldOrgID_id__exact=pk)
was correct but in template had to use currentstake.FormFieldOIRStakeholderID_id

Related

Django Query across multiple models

So I am looking for some help (and hopefully and explanation) of how I access data across my multiple models because this one has left me completely snookered.
I have a system for the sale of events (events model) now these events have multiple products(products model) and variable prices dependant on when you book (prices model), this part is working fine.
Where I am struggling is there are also bundles of products (bundles table) which contain multiple products, and I need to get their attached prices. Now I have a list of bundles attached to the products being viewed but am struggling to query the ORM and get a full record - <Products (multiple)> - .
I'm not completely new at this but it has left my completely stumped so any help would be greatly received. I have attached a sketch of the DB to help visualise.
Thanks
EDIT: The model is now include below.
from events.models import events
import uuid
import datetime
class products(models.Model):
id = models.UUIDField(primary_key=True, unique=True, default=uuid.uuid4, editable=False, verbose_name="ProductID")
name = models.CharField(max_length=255, verbose_name="Product Name")
linkedtoevent = models.ForeignKey(to=events, on_delete=models.CASCADE, verbose_name="Linked Event ID")
def __str__(self):
return self.name
.
class price(models.Model):
id = models.UUIDField(primary_key=True, unique=True, default=uuid.uuid4, editable=False, verbose_name="PriceRecordID")
productid = models.ForeignKey(to=products, on_delete=models.CASCADE)
price = models.FloatField(verbose_name="price")
date_from = models.DateField(verbose_name="Date From")
date_to = models.DateField(verbose_name="Date To")
#property
def status(self):
today = datetime.date.today()
if today in (self.date_to, self.date_from):
return True
else: return False
class bundle(models.Model):
id = models.UUIDField(primary_key=True, unique=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=255, verbose_name="Product Name")
productsinbunble = models.ManyToManyField(products)
date_from = models.DateField(verbose_name="Date To")
date_to = models.DateField(verbose_name="Date From")
discount = models.FloatField(verbose_name="Discount")
def __str__(self):
return self.name

Django : pre selection or tags. model relations

Django Version is 2.1.7
Hello, i have a OneToMany Relation and i ask my self if there is a possibility to make some kind of pre-selection (Tags or so?) for my Farmers?
Because not every Farmer has or wants Chickens or he is specialist in Cows only.
Means, right now, whenever i want to assign an individual Animal to a Farmer, i see all Farmers displayed in my Django Admin. With a growing Number of Farmers it gets confusing. So i thought to insert some Kind of Model Field in my Farmers Model... like chickens = true or not true and cows = true or not true or to introduce a new model for every species.
My Goal is, to assign a set of species to a every farmer. So that the Next time i want to add a chicken django shows only Farmers that will work with Chickens on their Farmland, it makes no sense to Display all Farmers, when some Farmers know that they handel only a specific set of species.
As a Newbie i would guess i have to make some new models for every Species with a ManyToMany Relation? So Farmers >< Species X, Y, Z < Indiviual Anmial.
Thanks
class Farmers(models.Model):
name = models.CharField(max_length=100)
farm_img = models.ImageField(upload_to='farm/', max_length=255, null=True, blank=True)
slug_farm = models.SlugField(blank=True)
<...>
class Chickens(models.Model):
farmer = models.ForeignKey(Farmers, on_delete=models.CASCADE, null=True)
chickenname = models.CharField(max_length=100)
<...>
class Cows(models.Model):
farmer = models.ForeignKey(Farmers, on_delete=models.CASCADE, null=True)
cowname = models.CharField(max_length=100)
<...>
class Rabbits(models.Model):
farmer = models.ForeignKey(Farmers, on_delete=models.CASCADE, null=True)
cowname = models.CharField(max_length=100)
<...>
If we are using postgres as DB then arrayFieldlink
can be a good option for doing this job.
from django.contrib.postgres.fields import ArrayField
class Farmers(models.Model):
.... necessary fields
SAMPLE_CHOICES = (
('CHICKEN', 'CHICKEN'),
('COW, 'COW'),
('No Species', 'No Species')
.....
)
choices = ArrayField(
models.CharField(choices=SAMPLE_CHOICES, max_length=10, blank=True, default='No Species'),
)
Now whenever we need to filter on Farmer model based on choices we can do this like following
Farmer.objects.filter(choices__contains=['cow'])
Update
As you are using django-mysql database, following thing by django-mysql link here we can have field feature like ListField link and can easily achieve this.
class ChickenFarmers(models.Model):
name = models.CharField(max_length=100)
farm_img = models.ImageField(upload_to='farm/', max_length=255, null=True, blank=True)
slug_farm = models.SlugField(blank=True)
class CowFarmers(models.Model):
name = models.CharField(max_length=100)
farm_img = models.ImageField(upload_to='farm/', max_length=255, null=True, blank=True)
slug_farm = models.SlugField(blank=True)
class RabbitsFarmers(models.Model):
name = models.CharField(max_length=100)
farm_img = models.ImageField(upload_to='farm/', max_length=255, null=True, blank=True)
slug_farm = models.SlugField(blank=True)
class Chickens(models.Model):
farmer = models.ForeignKey(ChickenFarmers, on_delete=models.CASCADE, null=True)
chickenname = models.CharField(max_length=100)
class Cows(models.Model):
farmer = models.ForeignKey(CowFarmers, on_delete=models.CASCADE, null=True)
cowname = models.CharField(max_length=100)
class Rabbits(models.Model):
farmer = models.ForeignKey(RabbitsFarmers, on_delete=models.CASCADE, null=True)
cowname = models.CharField(max_length=100)
'''
I think at this point this will give you best relief
'''

Table Master and details with same foreign django

I am trying to create two models in django, Reservation and DetailsReservation, i need that models has a same userReservation .Example if i create a Reservation with id: 1 and User: 4, when create a Details with Reservation 1, should copy user in userbyReserva
class Reservation(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
userReservation = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
class DetailsReservation(models.Model):
Reservation = models.ForeignKey(Reservation, blank=False, on_delete=models.CASCADE, null=True)
userbyReserva = #same user that do reservate
You can access the user through the Reservation using a method as property. This is the easiest way to do that.
Some notes about the code:
always use a lower case name for the fields and without the camelNaming.
Avoid plurals on the models' name.
I would avoid using default=1 in a ForeignKey. Better raise an error if the relation is not set. (What happen if the User=1 is deleted?)
Do not copy the data if not necessary, you can use properties to access related field. The user is available only if a reservation is related to the DetailReservation object; detail_reservation.user will return None if the reservation is not set.
I don't understand why you created the reservation relation optional from DetailReservation.
Have a look
class Reservation(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = models.ForeignKey(User, on_delete=models.CASCADE, )
class DetailReservation(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
reservation = models.ForeignKey(Reservation, blank=False, related_name='details',
on_delete=models.CASCADE, null=True)
#property
def user(self):
return reservation.user if reservation else return None

Django connected SQL queries with filters

Example:
class Room(models.Model):
assigned_floor = models.ForeignKey(Floor, null=True, on_delete=models.CASCADE)
room_nr = models.CharField(db_index=True, max_length=4, unique=True, null=True)
locked = models.BooleanField(db_index=True, default=False)
last_cleaning = models.DateTimeField(db_index=True, auto_now_add=True, null=True)
...
class Floor(models.Model):
assigned_building = models.ForeignKey(Building, on_delete=models.CASCADE)
wall_color = models.CharField(db_index=True, max_length=255, blank=True, null=True)
...
class Building(models.Model):
name = models.CharField(db_index=True, max_length=255, unique=True, null=True)
number = models.PositiveIntegerField(db_index=True)
color = models.CharField(db_index=True, max_length=255, null=True)
...
I want to output all rooms in a table sorted by Building.number.
Data which I want to print for each room:
Building.number, Building.color, Building.name, Floor.wall_color, Room.last_cleaning
Furthermore I want to allow optional filters:
Room.locked, Room.last_cleaning, Floor.wall_color, Building.number, Building.color
With one table it's no Problem for me, but I don't know how I archive this with three tables.
kwargs = {'number': 123}
kwargs['color'] = 'blue'
all_buildings = Building.objects.filter(**kwargs).order_by('-number')
Can you please help me? Do I need write raw SQL queries or can I archive this with the Django model query APIs?
I'm using the latest Django version with PostgreSQL.
No raw sql needed:
room_queryset = Room.objects.filter(assigned_floor__wall_color='blue')
^^
# A double unterscore declares the following attribute to be a field of the object referenced in the foregoing foreign key field.
for room in room_queryset:
print(room.assigned_floor.assigned_building.number)
print(room.assigned_floor.assigned_building.color)
print(room.assigned_floor.assigned_building.name)
print(room.assigned_floor.wall_color)
print(room.last_cleaning)

Django: Are multiple Generic Relations in one Model bad design?

I have a model with multiple Generic Relations that has become very complicated to use in my templates. The model is a 'Gig' or musical event that takes place at a 'Venue' and/or a 'Festival' and has a 'Musician' and/or an 'Ensemble'.
Where it gets complicated is that each 'Gig' has a presenter, promoter and an agent. These are setup as generic relations to other models such as 'PresenterCompany'. A Presenter company could be a promoter, presenter, or agent, or all of them for the same gig. Here are the models (simplified for ref):
class Gig(models.Model):
description = models.CharField(max_length=100, blank=True)
date = models.DateTimeField()
venue = models.ForeignKey(Venue)
festival = models.ForeignKey(Festival, blank = True, null=True)
musician = models.ManyToManyField(Musician, blank=True)
ensembles = models.ManyToManyField(Ensemble, blank = True)
presenter_content_type = models.ForeignKey(ContentType,
limit_choices_to={"model__in": ("Individual", "ArtsOrganization",'Presenter', "BookingAgent","Festival", "OtherOrganization","PresenterCompany", "Venue")}, related_name = "Presenter Type", verbose_name = "Presenter",blank=True, null=True)
presenter_id = models.IntegerField(db_index=True, blank=True, null=True, verbose_name='Presenter ID')
presenter = generic.GenericForeignKey('presenter_content_type','presenter_id')
promoter_content_type = models.ForeignKey(ContentType,
limit_choices_to={"model__in": ("Individual", "ArtsOrganization","BookingAgent","Presenter", "Festival", "OtherOrganization","PresenterCompany", "Venue")}, related_name = "promotor", verbose_name='Promoter Type', blank=True, null=True)
promoter_id = models.IntegerField(db_index=True, blank=True, null=True, verbose_name='Promoter ID')
promoter = generic.GenericForeignKey('promoter_content_type','promoter_id')
agent_content_type = models.ForeignKey(ContentType,
limit_choices_to={"model__in": ("Individual", "BookingAgent")}, related_name="agent", verbose_name='Agent Type', blank=True, null=True)
agent_id = models.IntegerField(db_index=True, blank=True, null=True, verbose_name='Agent ID')
agent = generic.GenericForeignKey('agent_content_type','agent_id')
class PresenterCompany(models.Model):
name = models.CharField(max_length=70)
address =GenericRelation(Address)
presented_gig = GenericRelation('Gig',
content_type_field='presenter_content_type',
object_id_field='presenter_id',
related_name='presenter_presented_gig'
)
promoted_gig = GenericRelation('Gig',
content_type_field='promoter_content_type',
object_id_field='promoter_id',
related_name='presenter_promoted_gig'
)
booked_gig = GenericRelation('Gig',
content_type_field='promoter_content_type',
object_id_field='promoter_id',
related_name='presenter_booked_gig'
)
The main issue is that when I try to get all of the gigs for a presenter company, I have to write three different for loops for each role i.e. {% for gig in presentercompany.presented_gig.all %}, and so on... This seems like redundant code.
Is there a better way to structure this such as using intermediary models for presenter, promoter, and agent? Thanks for your advice!
Generic relationships can definitely be hard to deal with. I would only use them when there is no other option.
In your case, I see a couple other options. You could have a ManyToMany relationship between PresenterCompany and Gig using a through table to specify the type of relationship (https://docs.djangoproject.com/en/2.0/topics/db/models/#extra-fields-on-many-to-many-relationships):
class Gig(models.Model):
description = models.CharField(max_length=100, blank=True)
date = models.DateTimeField()
venue = models.ForeignKey(Venue)
festival = models.ForeignKey(Festival, blank=True, null=True)
musician = models.ManyToManyField(Musician, blank=True)
ensembles = models.ManyToManyField(Ensemble, blank=True)
class PresenterCompanyGigRelationship(models.Model):
gig = models.ForeignKey(Gig, on_delete=models.CASCADE)
presenter_company = models.ForeignKey(
'PresenterCompany', on_delete=models.CASCADE)
relationship = models.CharField(
max_length=10,
choices=(
('presenter', 'Presenter'),
('promoter', 'Promoter'),
('agent', 'Agent'),
))
class PresenterCompany(models.Model):
name = models.CharField(max_length=70)
git = models.ManyToManyField(Gig, through=PresenterCompanyGigRelationship)