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.
Related
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
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!
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.
I'm looking to categorize my entries, the catch is there are multiple levels of categories I want. An example:
css
layout
floats
specificity, selectors
html
html 5
In this example, css and html are parent categories, css has 2 children and layout has a child of floats.
I suppose the schema I would need would be
class Category:
name = models.TextField()
parentId = models.IntegerField(blank=True)
What I'm clueless on is, how would I be able to make a multi-level dropdown in my admin so that when I post entries I could select a category easily?
So to reiterate, how would I be able to generate a multi-level nested dropdown menu so that when I enter stuff in my Entry model, I can select one category per entry?
It seems that your problem is slightly different from what you are stating. The issue here is not that much about how to display the hierarchy, which is simple:
def __unicode__(self):
return self.depth * " "
The bummer is how to capture and display the hierarchy / depth. This is a common problem: storing trees in realational databases. As usual, your solution depends on tradeoffs between write / read heavy and how much to normalize. You could, for example, on the 'save' method of the model to recursively get to the root and from there store a 'depth' attribute on the nodes. My suggestion is to use django mptt . It is pretty solid and solves much of the normal hurdles. As a bonus, you get a good api for common tree tasks.
I'm building a food logging database in Django and I've got a query related problem.
I've set up my models to include (among other things) a Food model connected to the User model through an M2M-field "consumer" via the Consumption model. The Food model describes food dishes and the Consumption model describes a user's consumption of Food (date, amount, etc).
class Food(models.Model):
food_name = models.CharField(max_length=30)
consumer = models.ManyToManyField("User", through=Consumption)
class Consumption(models.Model):
food = models.ForeignKey("Food")
user = models.ForeignKey("User")
I want to create a query that returns all Food objects ordered by the number of times that Food object appears in the Consumption table for that user (the number of times the user has consumed the food).
I'm trying something in the line of:
Food.objects.all().annotate(consumption_times = Count(consumer)).order_by('consumption_times')`
But this will of course count all Consumption objects related to the Food object, not just the ones associated with the user. Do I need to change my models or am I just missing something obvious in the queries?
This is a pretty time-critical operation (among other things, it's used to fill an Autocomplete field in the Frontend) and the Food table has a couple of thousand entries, so I'd rather do the sorting in the database end, rather than doing the brute force method and iterate over the results doing:
Consumption.objects.filter(food=food, user=user).count()
and then using python sort to sort them. I don't think that method would scale very well as the user base increases and I want to design the database as future proof as I can from the start.
Any ideas?
Perhaps something like this?
Food.objects.filter(consumer__user=user)\
.annotate(consumption_times=Count('consumer'))\
.order_by('consumption_times')
I am having a very similar issue. Basically, I know that the SQL query you want is:
SELECT food.*, COUNT(IF(consumption.user_id=123,TRUE,NULL)) AS consumption_times
FROM food LEFT JOIN consumption ON (food.id=consumption.food_id)
ORDER BY consumption_times;
What I wish is that you could mix aggregate functions and F expression, annotate F expressions without an aggregate function, have a richer set of operations/functions for F expressions, and have virtual fields that are basically an automatic F expression annotation. So that you could do:
Food.objects.annotate(consumption_times=Count(If(F('consumer')==user,True,None)))\
.order_by('consumtion_times')
Also, just being able more easily able to add your own complex aggregate functions would be nice, but in the meantime, here's a hack that adds an aggregate function to do this.
from django.db.models import aggregates,sql
class CountIf(sql.aggregates.Count):
sql_template = '%(function)s(IF(%(field)s=%(equals)s,TRUE,NULL))'
sql.aggregates.CountIf = CountIf
consumption_times = aggregates.Count('consumer',equals=user.id)
consumption_times.name = 'CountIf'
rows = Food.objects.annotate(consumption_times=consumption_times)\
.order_by('consumption_times')