I've got two entities, Item and City. How can I model like a one-to-many relation so that it represents that an item can "have" many cities? I'd like to do it with ReferenceProperty but it seems that it would be a list and there is no property for lists of keys AFAIK. Can you tell me how I should model in order to represent the relation?
When creating new objects it is possible to make something like a one-to-many if you are creating new objects with referenceproperty that is a collection:
class ItemLocation(db.Model):
reference = db.ReferenceProperty(Item,
collection_name='matched_cities', verbose_name='Cities')
But this is not exactly what I want. I want a convenient modelling where I can iterate over the cities for a given item i.e.
{% for city in item.matched_cities %}
Can you tell me how I should do this?
Thank you
You can absolutely have a list of keys. Add this to your Item model:
cities = db.ListProperty(db.Key)
Then, you can retrieve those cities from the datastore with
itemsCities = ItemLocation.get(item.cities)
Related
I am pulling some data from an API and I want to store it in my Django model. The data is a baseball inning and then runs scored that inning and comes to me like this...
"innings":[
0:0
1:3
2:0
3:0
4:1
5:2
6:0
7:0
8:4
]
I access each individual value like...
for game in games:
first_inning = game['scoreboard']['score']['innings'][0]
second_inning = game['scoreboard']['score']['innings'][1]
etc...
But if I wanted to save all the data as it is and start the innings at 1 instead of 0, which type of field would I use and how would I do that? Would it be an ArrayField?
I really appreciate your help.
There are some ways depending on your problem.
you can store your data in ArrayField. but ArrayField is only spcific to PostgreSQL database.(more information here)
you can convert your data to JSON and store it in JSONField(more information about JSONField is here).
My suggestion is solution number 2 because you are reading serialized data from API.
I hope it could help you.
One option is an ArrayField, it's 0-indexed as any python list and you cannot change that.
Another option is to model your Inning as a separate model, in case you want to perform queries like "average score on the 3rd inning" etc. You will be able to adjust inning numbers however you want them.
class Inning(models.Model):
game = models.ForeignKey('game.Game', on_delete=models.CASCADE)
number = models.PositiveIntegerField()
score = models.PositiveIntegerField()
class Meta:
unique_together = [('game', 'number')]
You could use the JSONField. The benefit of it is that you can format it however you want to store your data according to what you are getting from the API. In your model, you can define the field like this:
class SomeModel(models.Model):
....
innings_score = models.JSONField(default=dict)
Here I would advise you to use a default because of what is mentioned in the offical docs:
If you give the field a default, ensure it’s an immutable object, such
as a str, or a callable object that returns a fresh mutable object
each time, such as dict or a function. Providing a mutable default
object like default={} or default=[] shares the one object between all
model instances.
Then you can use save your data as a normal dictionary in the model:
SomeModel.objects.create(...., innings_score={0:0,
1:3,
2:0,
3:0,
4:1,
5:2,
6:0,
7:0,
8:4})
Since this is a dictionary, you can start your data from 1 by naming your key 1 instead of 0 (i.e skip the first value), and so on.
I want to create a database of dislike items, but depending on the category of item, it has different columns I'd like to show when all you're looking at is cars. In fact, I'd like the columns to be dynamic based on the category so we can easily an additional property to cars in the future, and have that column show up now too.
For example:
But when you filter on car or person, additional rows show up for filtering.
All the examples that I can find about using django models aren't giving me a very clear picture on how I might accomplish this behavior in a clean, simple web interface.
I would probably go for a model describing a "dislike criterion":
class DislikeElement(models.Model):
item = models.ForeignKey(Item) # Item is the model corresponding to your first table
field_name = models.CharField() # e.g. "Model", "Year born"...
value = models.CharField() # e.g. "Mustang", "1960"...
You would have quite a lot of flexibility in what data you can retrieve. For example, to get for a given item all the dislike elements, you would just have to do something like item.dislikeelements_set.all().
The only problem with this solution is that you would to store in value numbers, strings, dates... under the same data type. But maybe that's not an issue for you.
I have a model that looks something like this:
class Item(models.Model):
name = models.CharField()
type = models.CharField()
tags = models.models.ManyToManyField(Tags)
In order to render a given view, I have a view that presents a list of Items based on type. So in my view, there's a query like:
items = Item.objects.filter(type='type_a')
So that's easy and straight forward. Now I have an additional requirement for the view. In order to fulfill that requirement, I need to build a dictionary that relates Tags to Items. So the output i am looking for would be something like:
{
'tag1': [item1, item2, item5],
'tag2': [item1, item4],
'tag3': [item3, item5]
}
What would be the most efficient way to do this? Is there any way to do this without going to the database with a new query for each tag?
You can check prefetch_related it might help you:
This has a similar purpose to select_related, in that both are designed to stop the deluge of database queries that is caused by accessing related objects, but the strategy is quite different... prefetch_related, on the other hand, does a separate lookup for each relationship, and does the ‘joining’ in Python. This allows it to prefetch many-to-many and many-to-one objects, which cannot be done using select_related...
So in the end you will either do multiple queries or use prefetch_related and it will do some Python joins on the objects.
You might do something like this:
# This should require two database queries, one for the items
# and one for all the associated tags.
items = Item.objects.filter(type='type_a').prefetch_related('tags')
# Now massage the data into your desired data structure.
from collections import defaultdict
tag_dict = defaultdict(list)
for item in items:
# Thanks to prefetch_related this will not hit the database.
for tag in item.tags.all():
tag_dict[tag].append(item)
I have a simple to-do list with activities that can be ordered by the user. I use the model List, with a many-to-many field to the model Activities.
Now I need a way to store the user defined ordering of the activities on the list. Should I go with an extra field in my List model to store the order of my activity primary keys like this:
class List(models.Model):
activities = models.ManyToManyField(Activity)
order = models.CommaSeperatedIntegerField(max_length=250)
Or should I go with a solution in the Activity model, like described here:
https://djangosnippets.org/snippets/998/
What method can be considered as best practice?
you can create your own ManyToMany Model defining the extra field order
https://docs.djangoproject.com/en/dev/topics/db/models/#extra-fields-on-many-to-many-relationships
something like:
class ActivityList(models.Model):
activity = models.ForeignKey(Activity)
list = models.ForeignKey(List)
order = models.IntegerField()
class List(models.Model)
activities = models.ManyToManyField(Activity, through='ActivityList')
Now I need a way to store the user defined ordering of the activities on the list.
Specifying and order field allows you to give each activity an order.
specifying a comma seperated string, is 100% not the way to go, IN fact it is one of the biggest anti patterns in relational databases, Is storing a delimited list in a database column really that bad?
Using a through model lets you query for the order when presenting your todo list to the user
for activity in your_list.activities.all().order_by('order'):
# display activity to user
I've a queryset result, say, animals, which has a list of animals. There are sub categories of animals and I want to get all the subcategories. i.e.
for single animal, I can use animal.categories which works. Now, I want to somehow do this:
categories = animals.categories
where animals is queryset. How can I achieve this?
There is no way without iterating over the query set, but you can use prefetch_related to speed things up:
all_animals = Animals.objects.prefetch_related('categories')
categories = [animal.categories.all() for animal in all_animals]
There are 2 options:
1) Following your question exactly, you can only do:
categories=[]
for aninmal in animals:
categories.extend(animal.categories.all())
2) However, I would run a new query with categories like that (I do not know your exact data model and wording, but I think you get the idea)
categories=Category.filter(animals__in=animals).all()
( Base: if animals.categories is giving a queryset that means categories has a many-to-one with animal. and default name (category_set) is changed with categories)
It seems to me like your main query should be a Category query instead of animals. Lets say you get animals like:
Animals.objects.filter(name__startswith='A')
You could get categories of this animals with following query
Category.objects.filter(animal__name__startswith='A')
You can also get animals with this query
Category.objects.filter(animal__name__startswith='A').select_related('category')
But I recommend to use seperate queries for categories and animals (will be more memmory efficent but will do two queries).
Note:If you are really using one-to-many You should consider changing it to many-to-many.