Django Query across multiple models - django

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

Related

Django QuerySets - Related Models

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

How to print foreignkey Model relation?

If in My model, Moneybook have a many moneylogs.
so, I design a model
Moneybook/models.py
name = models.CharField(max_length=30, default="행복한 여행!")
owner = models.ForeignKey(
user_models.User, on_delete=models.CASCADE, related_name="owner")
companion = models.ManyToManyField(
user_models.User, related_name="companion", blank=True)
country = CountryField()
location = models.CharField(max_length=50, blank=True)
start_date = models.DateTimeField(default=NOW)
end_date = models.DateTimeField(default=NOW)
Moneylog/models.py
moneybook = models.ForeignKey(
moneybook_models.Moneybook, on_delete=models.CASCADE, related_name="moneybooks")
payer = models.ForeignKey(
user_models.User, on_delete=models.CASCADE, related_name="payer")
dutch_payer = models.ManyToManyField(
user_models.User, related_name="dutch_payer")
price = models.IntegerField()
category = models.CharField(max_length=10)
memo = models.TextField()
If i want to load all the moneylogs in the each belonging moneybook. how can i load it?
I guess...
def moneybook_detail(request, pk):
moneylogs=moneylog.filter(moneylog.moneybook.id=request.moneybook.id)
return render(request, "moneybooks/detail.html")
but error occured.
moneylogs = moneylog.filter(request.moneybook.id=request.moneybook.id)
SyntaxError: keyword can't be an expression
You can either query the Moneylog table with the following query by using the double underscore __ to filter based on referenced object fields.
moneylogs = MoneyLog.filter(moneybook__id=<<<MoneyBookID_GOES_HERE>>>)
Or by using the internal ReverseManyToOneManager in Django
just by using
moneybook = MoneyBook.objects.get(pk=<<<<MoneyBookID_GOES_HERE>>>>)
moneylogs = moneybook.moneylog_set.all() # all() to get all money logs
# You can do filter(...) on it too to filter the moneylogs too.
this will return all money logs related to the money book.
In general, you have to use double underscore __ to reference foreign key columns in filters:
def moneybook_detail(request, pk):
moneylogs=moneylog.filter(moneybook__id=request.moneybook.id)
return render(request, "moneybooks/detail.html")

Multiple default values specified for column "id" of table in Django 2.1.1

So I keep getting this error saying that there's multiple specified ID values for the device table, but I don't have a clue where I've specified any kind of default ID. I've tried setting a field as primary_key=True but that didn't solve the problem either.
EDIT: Traceback
class Campus(models.Model):
name = models.CharField(max_length=20)
address = models.CharField(max_length=40)
def __str__(self):
return self.name
class Meta:
verbose_name_plural = "Campuses"
class Teacher(models.Model):
name = models.CharField(max_length=20)
phone = models.CharField(max_length=11)
department = models.CharField(max_length=20)
campus = models.OneToOneField(Campus, on_delete=models.CASCADE, default="Not Assigned")
#devices = self.Device.objects.all()
def __str__(self):
return self.name
class Device(models.Model):
inUse = 'IU'
inStock = 'IS'
inMaintenance = 'IM'
damaged = 'DM'
statusChoices = (
(inUse, 'In Use'),
(inStock, 'In Stock'),
(inMaintenance, 'In Maintenance'),
(damaged, 'Damaged'),
)
name = models.CharField(max_length=20)
brand = models.CharField(max_length=20)
status = models.CharField(max_length=2, choices=statusChoices, default=inStock)
#user = models.ForeignKey(Teacher, on_delete=models.CASCADE, default=0)
def __str__(self):
return self.name
After navigating to my PostgreSQL instance I deleted all Django-related data and remade migrations and things are in working order again.
For future users: I recommend deleting your past migrations table in your database.

Storing data in different tables or using bool fields

I have an Article table
class Article(models.Model):
"""
Model to keep articles
"""
ext_id = models.UUIDField(primary_key=True, db_index=True, default=uuid.uuid4, editable=False)
title = models.CharField(max_length=255, unique=True, db_index=True)
content = models.TextField()
summary = models.TextField()
img_url = models.URLField(max_length=200)
author = models.CharField(max_length=50, blank=True, null=True)
sport = models.ForeignKey('Sport')
posted_on= models.DateTimeField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def __unicode__(self):
return "%s by %s" % (self.title, self.author)
A table where I store articles liked by a user :
class LikedArticle(models.Model):
"""
Articles that a user wants to read
"""
ext_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
article = models.ForeignKey(Article)
profile = models.ForeignKey(Profile)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
and unliked :
class UnlikedLikedArticle(models.Model):
"""
Articles that a user does not want to read
"""
ext_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
article = models.ForeignKey(Article)
profile = models.ForeignKey(Profile)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
Now here, both the tables liked and unliked, are structurally the same.
I find it better to store it like this instead of storing say a bool field called is_liked because I exactly know what data I am storing. So I don't have to query a huge set of articles when I know that I am only interested in LikedArticle.
Is this the correct approach ? I am only confused because structurally they look the same and something doesn't feel right about this design.
the best approach that i recommend is to use one table and add is_liked field. (and add index to this field, so you get high performance queries)
but if still you want to use your approach with 2 table, then you need to fix your design.
use one abstract model that has all fields, and the Like and Unlike tables inherit from the abstract model
class ActionOnArticle(Model):
your fields here..
class Meta:
abstract = True
class LikedArticle(ActionOnArticle):
class UnLikedArticle(ActionOnArticle):
I think is_liked is not a good option if you want to save other information per profile, like that: who liked what and when and so on. If you want to lose those info so my suggestion is to use many to many relationship and the article model will be something like that:
class Article(models.Model):
"""
Model to keep articles
"""
ext_id = models.UUIDField(primary_key=True, db_index=True, default=uuid.uuid4, editable=False)
title = models.CharField(max_length=255, unique=True, db_index=True)
content = models.TextField()
summary = models.TextField()
img_url = models.URLField(max_length=200)
author = models.CharField(max_length=50, blank=True, null=True)
sport = models.ForeignKey('Sport')
posted_on= models.DateTimeField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
likes = models.ManyToManyField(Profile)
unlikes = models.ManyToManyField(Profile)
def __unicode__(self):
return "%s by %s" % (self.title, self.author)
https://docs.djangoproject.com/en/1.8/topics/db/examples/many_to_many/
While if you want to save the info mentioned at the beginning of my reply, I think #Eyal answer is fine
I'd use the "is_liked" BooleanField and filter on it to just get the liked or disliked articles. Filtering on a BooleanField (add db_index=True on the field options) will be extremely fast with any decent database so you are very unlikely to get a noticable performance increase using separate tables even if they were huge.

Django - Filter based on model method

I have a model, defined like this :
class Item(models.Model):
name = models.CharField(max_length=200, null=True, default='', blank=True)
creation_date = models.DateTimeField('date created', default=timezone.now())
def was_published_today(self):
today = timezone.now() - datetime.timedelta(days=1)
return self.creation_date >= today
I would like to filter a set of Item like this :
items = Item.objects.filter(was_published_today=True)
But I run into a FieldError which makes sense as it seems that filter is not made to filter a set of objects based on a method. Detailed error :
Cannot resolve keyword 'was_published_today' into field. Choices are : creation_date, name
What is the correct way to do this ? I know I can compare creation_date with today's date but that's what was_published_today does and I would like to keep it DRY.
Here you can use django Managers.
Custom Manager:
class GetPublishedToday(models.Manager):
def get_query_set(self):
return super(GetPublishedToday, self).get_query_set().filter(creation_date= timezone.now() - datetime.timedelta(days=1))
in Models:
class Item(models.Model):
name = models.CharField(max_length=200, null=True, default='', blank=True)
creation_date = models.DateTimeField('date created', default=timezone.now())
was_published_today= GetPublishedToday()
in views:
items = Item.was_published_today.all() # or .filter(name= "foobar")
'''PS: Its an untested code.'''
F expressions is a correct way, I think. Example from documentation:
from datetime import timedelta
Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))