In Django, can I have one model field whose value is the highest value in a one-to-many relationship? - django

I have two models. One represents several groups, and the other represents people in those groups with a ranking. I would like to have a field in the groups model that represents the highest ranked person inside that group. Is this possible?
For example:
Groups:
id name highest
1 alpha gold
2 bravo diamond
People:
name group rank
Dave 1 silver
bob 1 gold
dilan 1 silver
arthur 2 gold
mark 2 diamond

I would like to have a field in the groups model that represents the highest ranked person inside that group.
In this case, you might want to add a ForeignKey to your Group model. What a foreign key does is it links one of the fields (which you can name it whatever you want) to another model class, which in your case, will be the User model.
But seeing as you want the highest ranked person, all the above actions will deem unrealistic as every time the leaderboard changes you need to refresh your model, and that's inconvenient.
What I'll suggest, instead of adding another field, is to render all the person objects and pass it as a part of the context. That way, as the user's rank changes, you don't need to refresh your model. Please refer to the doc's detail on passing context to view and a way to sort your data.

Related

One to Many relationship real life example

I am trying to design the schema. I am confused about should I use one-to-many or many-to-one relationships.
My use case is somewhat like customers ordering the food.
There are 2 customers and 5 food items
Customers: [John, Alice]
Food: [Rice, Noodle, Chicken, Beacon, Ice-cream]
Use case: One Customer can order many items, but if first customer orders that item, it can not be ordered by other.
Example:
John orders -> Rice, Noodle, Chicken
Alice orders -> Beacon, Ice-cream
**This is valid, both customers ordered unique food.**
Example:
John orders -> Rice, Noodle, Chicken
Alice orders -> Beacon, Ice-cream, Chicken
**This is invalid, because Chicken is being ordered twice. John Already ordered chicken so Alice can not order it.**
Note: I am trying to this in mongodb documents and trying to establish relationship using Django models.
One way to handle this would be to create a junction table CustomerFood which looks something like this:
CREATE TABLE CustomerFood (
Customer varchar(255) NOT NULL,
Food varchar(255) NOT NULL,
PRIMARY KEY(Customer, Food)
);
The above table definition alone would only ensure that each customer can be related to each food at most once. To enforce the additional restriction that a given food can be associated with only one customer, we can add a unique constraint on the Food column:
ALTER TABLE CustomerFood ADD CONSTRAINT food_unique UNIQUE (Food);
Using Django templates:
You could use many to many in django (less code bit more complex to understand) OR create "table in the
middle approch" (more manual approach that needs more model code).
Django many to many documentation
Secondly you should use Validators to
ensure your logic that one person can only order one dish, and the
dishes will sell out, this is more programming logic and can be part
of a validator. Django validators documentation

Join two records from same model in django queryset

Been searching the web for a couple hours now looking for a solution but nothing quite fits what I am looking for.
I have one model (simplified):
class SimpleModel(Model):
name = CharField('Name', unique=True)
date = DateField()
amount = FloatField()
I have two dates; date_one and date_two.
I would like a single queryset with a row for each name in the Model, with each row showing:
{'name': name, 'date_one': date_one, 'date_two': date_two, 'amount_one': amount_one, 'amount_two': amount_two, 'change': amount_two - amount_one}
Reason being I would like to be able to find the rank of amount_one, amount_two, and change, using sort or filters on that single queryset.
I know I could create a list of dictionaries from two separate querysets then sort on that and get the ranks from the index values ...
but perhaps nievely I feel like there should be a DB solution using one queryset that would be faster.
union seemed promising but you cannot perform some simple operations like filter after that
I think I could perhaps split name into its own Model and generate queryset with related fields, but I'd prefer not to change the schema at this stage. Also, I only have access to sqlite.
appreciate any help!
Your current model forces you to have ONE name associated with ONE date and ONE amount. Because name is unique=True, you literally cannot have two dates associated with the same name
So if you want to be able to have several dates/amounts associated with a name, there are several ways to proceed
Idea 1: If there will only be 2 dates and 2 amounts, simply add a second date field and a second amount field
Idea 2: If there can be an infinite number of days and amounts, you'll have to change your model to reflect it, by having :
A model for your names
A model for your days and amounts, with a foreign key to your names
Idea 3: You could keep the same model and simply remove the unique constraint, but that's a recipe for mistakes
Based on your choice, you'll then have several ways of querying what you need. It depends on your final model structure. The best way to go would be to create custom model methods that query the 2 dates/amount, format an array and return it

Can you suggest better Django model design? (I'm django beginner)

I'm designing a simple Django model called Clothes. Basically it retrieves what kinds of clothes the user have. I categorized clothes as more than 20 types (such as hoodies, jean, pants) and as big three types: "top", "bottom", "shoes".
In ClothesView, I want to show first 5 clothes for each "top", "bottom", "shoes". And it will retrieve 5 more for individual category if user clicks more (So if user click 'more top', it will return 5 more clothes of 'top' type.
For your better understanding, I wrote the Clothes model conceptually.
class Clothes(models.Model):
id
type = # hoodie, shirts, pants, jean, coat, and so on (more than 20)
big_type = # top, bottom and shoes
owner = ForeignField # some one who post
Expected output (this is just my guess!)
Retrieve 5 clothes for each parent_types ("top", "bottom", "shoes")
user.clothes_set.filter(big_type="top")[:5]
user.clothes_set.filter(big_type="bottom")[:5]
user.clothes_set.filter(big_type="shoes")[:5]
Retrieved 5 more clothes for "top"
user.clothes_set.filter(big_type="top)[5:10]
Retrieve all "hoodies" from my clothes <- this looks ok
user.clothes_set.filter(type="hoodies")
Can you suggest better of efficient model? I may add new Type class and put "through" ... (I'm not sure)
I think you are doing it right. Read here, limiting-queryset.
If you want to query the database in this way. This is the good option instead of retrieving the whole queryset and then slicing it. Through this, the LIMIT for slicing will be issued to the database so, slicing will be done in the database.
On the second opinion, I would advise you to create a new model for Types with the fields type and id.
Then, map it using ManyToMany Relation, if you are not in the case.
For that querying may look like this,
type = Type.objects.get(type="Top").id
clothes = Clothes.objects.filter(type=type)[:5]
Having a different model for Type will help you at the client side rendering.

Django ForeignKey and associated values in initial model

First off, sorry for this somewhat crappy title: I wasn't able to find a short and explicaive title for this one .
I'm currently trying to create an app where there will be players and each will have an inventory.
The inventory consists of a ManyToManyField of Items.
class Item(models.Model):
name = models.CharField(_('Name'), max_length=67)
flavor_text = models.TextField(_('Flavor text'))
class Inventory(models.Model):
items = models.ManyToManyField(Item, verbose_name=_('Items'))
I'm trying to implement a system where a player can, for example, have 3 bananas, 1 screwdriver and 17 loafs in his inventory.
As I'm very lazy, I don't want to enter manually 3 "banana" items in my inventory.
However, putting a quantity field in the Item model would be counter-productive, as I would need to create an Item named "3 bananas", another "2 bananas", again and again.
I also tought of creating Alice's Bananas, Bob's Bananas, and change the quantity, but still, that's creating too much banana items : especially if I need to add more players.
So, here is my question: How can I associate a value (here, a quantity) to a ForeignKey, but inside the model declaring the ForeignKey?
Thanks for reading!

How to model lending items between a group of companies

I have a group of related companies that share items they own with one-another. Each item has a company that owns it and a company that has possession of it. Obviously, the company that owns the item can also have possession of it. Also, companies sometimes permanently transfer ownership of items instead of just lending it, so I have to allow for that as well.
I'm trying to decide how to model ownership and possession of the items. I have a Company table and an Item table.
Here are the options as I see them:
Inventory table with entries for each Item - Company relationship. Has a company field pointing to a Company and has Boolean fields is_owner and has_possession.
Inventory table with entries for each Item. Has an owner_company field and a possessing_company field that each point to a Company.
Two separate tables: ItemOwner and ItemHolder**.
So far I'm leaning towards option three, but the tables are so similar it feels like duplication. Option two would have only one row per item (cleaner than option one in this regard), but having two fields on one table that both reference the Company table doesn't smell right (and it's messy to draw in an ER diagram!).
Database design is not my specialty (I've mostly used non-relational databases), so I don't know what the best practice would be in this situation. Additionally, I'm brand new to Python and Django, so there might be an obvious idiom or pattern I'm missing out on.
What is the best way to model this without Company and Item being polluted by knowledge of ownership and possession? Or am I missing the point by wanting to keep my models so segregated? What is the Pythonic way?
Update
I've realized I'm focusing too much on database design. Would it be wise to just write good OO code and let Django's ORM do it's thing?
Is there a reason why you don't want your item to contain the relationship information? It feels like the owner and possessor are attributes of the item.
class Company(models.Model):
pass
class Item(models.Model):
...
owner = models.ForeignKey(Company, related_name='owned_items')
holder = models.ForeignKey(Company, related_name='held_items')
Some examples:
company_a = Company.objects.get(pk=1)
company_a.owned_items.all()
company_a.held_items.all()
items_owned_and_held_by_a=Items.objects.filter(owner=company_a, holder=company_a)
items_on_loan_by_a=Items.objects.filter(owner=company_a).exclude(holder=company_a)
#or
items_on_loan_by_a=company_a.owned_items.exclude(holder=company_a)
items_a_is_borrowing=Items.objects.exclude(owner=company_a).filter(holder=company_a)
#or
items_a_is_borrowing=company_a.held_items.exclude(owner=company_a)
company_b = Company.objects.get(pk=2)
items_owned_by_a_held_by_b=Items.objects.filter(owner=company_a, holder=company_b)
#or
items_owned_by_a_held_by_b=company_a.owned_items.filter(holder=company_b)
#or
items_owned_by_a_held_by_b=company_b.held_items.filter(owner=company_a)
I think if your items are only owned by a single company and held by a single company, a separate table shouldn't be needed. If the items can have multiple ownership or multiple holders, a m2m table through an inventory table would make more sense.
class Inventory(models.Model):
REL = (('O','Owns'),('P','Possesses'))
item = models.ForeignKey(Item)
company = models.ForeignKey(Company)
relation = models.CharField(max_length=1,choices=REL)
Could be one implementation, instead of using booleans. So I'd go for the first. This could even serve as an intermediate table if you ever decide to use a 'through' to relate items to company like this:
Company:
items = models.ManyToManyField(Item, through=Inventory)
Option #1 is probably the cleanest choice. An Item has only one owner company and is possessed by only one possessing company.
Put two FK to Company in Item, and remember to explicitly define the related_name of the two inverses to be different each other.
As you want to avoid touching the Item model, either add the FKs from outside, like in field.contribute_to_class(), or put a new model with a one-to-one rel to Item, plus the foreign keys.
The second method is easier to implement but the first will be more natural to use once implemented.