I have a model named Hobbies that has the hobbies for certain participants (this is a ForeignKey relationship). For each certain participant I wish to have an auto incrementing field named priority that shows which hobby is prioritized. For example: participant 1 has 3 hobbies with priorities going from 1 to 3, participant 2 has 5 hobbies with priorities going from 1 to 5. Is there a way to have an auto incrementing field that depends on the participant, without making another table in my database?
This is the class for Hobbies:
class Hobbies(models.Model):
hobby = models.CharField(max_length=255, verbose_name='Add hobby', help_text=_('Vul hier 1 van je hobbies in.'))
priority = models.IntegerField()
participant = models.ForeignKey(Deelnemer, on_delete=models.CASCADE)
class Meta:
ordering = ['priority']
verbose_name_plural = 'Hobbies'
def __str__(self):
return self.hobby
If you need more information, I'll add it.
Related
I want the days_allocated field to self update back to 30 with respect to time every year.
class Staff profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
days_allocated = models.PositiveIntegerField(default=30)
I am writting an application for a crop warehousing company, which purchases the harvested crop and stores it in one or more warehouses. Till now limitations of Google App Engine/Datastore was not posing problem to me. And I so deep into the project that it's very difficult to return.
I have to establish a many to many relationship between two Kinds which are transactional (means parent/ancestor queries) in nature. I am not sure what is the right approach to do this. This is the business logic:
Warehouse issues a purchase order for a specific quantity (PO). So we create an entity in PO Kind for each purchase order (PO).
Goods are received at the warehouse. So we create an entity in GRN Kind. (GRN=Goods Receiving Notes).
Here is many to many relationship.
One GRN may be required to complete one PO.
One GRN may be required to complete many POs.
Many GRNs may be required to complete one PO.
Many GRNs may be required to complete many POs.
This is a relevent snapshot of the code.
class Warehouse(ndb.Models):
name = ndb.TextProperty()
capacity = ndb.FloatProperty()
current_stock = ndb.FloatProperty()
class PurchaseOrder(ndb.Models):
quantity = ndb.FloatProperty()
remaining = ndb.FloatProperty()
is_complete = ndb.BooleanProperty()
grn = ndb.KeyProprty(repeated=True, kind=GRN)
class GRN(ndb.Models):
quantity = ndb.FloatProperty()
remaining = ndb.FloatProperty()
is_complete = ndb.BooleanProperty()
po = ndb.KeyProprty(repeated=True, kind=PurchaseOrder)
Entity Group Relationships
Warehouse -> GRN
Warehouse -> PO
To establish many - to - many relationship I hold all the related GRN Keys in a PO record and all related PO Keys in a GRN record. This is working fine for me.
But in case I have to edit a GRN or PO in the back date, then I am not able to handle the complication of cascaded changes which may impact other GRNs and POs.
Somewhere I read I should be using a third model to hold the many - to - many relationship, rather than storing the related keys. I am not able to visualize what that third table to should contain. *
I know my problem is very specific and I have not funished all the details. But just help me with the right approach for this kind of problem pattern. I will handle the rest. Or provide any link if this is already documented somewhere.
I would add a many-to-many relationship called GRNinstance that links a single GRN instance with a single PO:
class PurchaseOrder(ndb.Models):
quantity = ndb.FloatProperty()
remaining = ndb.FloatProperty()
is_complete = ndb.BooleanProperty()
class GRN(ndb.Models):
quantity = ndb.FloatProperty()
remaining = ndb.FloatProperty()
is_complete = ndb.BooleanProperty()
class GRNinstance(ndb.Models):
po = ndb.KeyProperty(kind=PurchaseOrder)
grn = ndb.KeyProperty(kind=GRN)
quantity = ndb.FloatProperty()
The sum of GRNinstance.quantity for a particular po should add up to PurchaseOrder.quantity, and the sum of GRNinstance.quantity for a particular grn should add up to GRN.quantity.
In fact, Dmitry's ComputedProperty could replace both PurchaseOrder.quantity and GRN.quantity (but that could be slow). Maybe is_complete could be a simple test:
is_complete = ndb.ComputedProperty(lambda self: self.remaining > 0)
I'm working on a website that sells tickets for events. And I have the following design:
And the (simplified for posting) models:
class Event(models.Model):
name = models.CharField(max_lenght=20)
class Date(models.Model):
event_start = models.DateTimeField()
event = models.ForeignKey(Event)
class Ticket_Class(models.Model):
name = models.CharField(max_lenght=20)
price = models.IntegerField()
event = models.ForeignKey(Event)
How should I add a Ticket model? Because a Ticket is for an Event on a particular Date, so I would need to relate a ticket to the relationship between Event and Date
A Ticket_Class should also have a "max" field where is stored the maximum tickets available to sell for that particular Ticket_Class on a particular Date. E.g.: Event "Metallica" has Ticket_Class "Field" and Ticket_Class "VIP", both on three different dates. How would I access the number of remaining tickets for a Ticket_Class on a particular Date? Maybe counting how many Tickets are in the Ticket table corresponding to that Event on that Date.
I hope I made myself clear, english is not my first language. Feel free to ask any doubts
I think your design should be something like this:
class Event(models.Model):
name = models.CharField(max_lenght=20)
class Date(models.Model):
event_start = models.DateTimeField()
event_end= models.DateTimeField()
class Ticket_Class(models.Model):
name = models.CharField(max_lenght=20)
price = models.IntegerField()
type= models.CharField(max_lenght=20)
class EventTicketSell(models.Model):
event= models.ForeignKey(Event)
date= models.ForeignKey(Date)
ticket= models.ForeignKey(Ticket_Class)
max_sellable_tickets= models.IntegerField()
Reason for this design is that you can add a event to EventTicketSell class, then assign date and ticket with max sellable tickets.
for adding ticket/date/event:
event1= Event(name= "Lion King")
event1.save()
event2= Event(name= "Metallica")
event2.save()
vip_ticket= Ticket_Class(name='VIP', price= 100, type='VIP')
vip_ticket.save()
evening_show= Date(event_start='Date Object', event_end= 'Date Object') # Date Object is like datetime.datetime.now()
evening_show.save()
concert_ticket_sell= EventTicketSell(event=event1, ticket=vip_ticket, date= evening_show, max_sellable_ticket=500)
concert_ticket_sell.save()
movie_ticket_sell= EventTicketSell(event=event2, ticket=vip_ticket, date= evening_show, max_sellable_tickets=500)
movie_ticket_sell.save()
This design will keep objects reusable and flexible to modify. For example, if you want to change max_sellable_ticket then:
movie_ticket_sell= EventTicketSell.objects.filter(event__name='Lion King', date__event_start= datetime.datetime.now(), ticket__type= 'VIP')[0]
movie_ticket_sell.max_sellable_tickets -= form.cleaned_data['ticket_sold'] #for example we get sold count from form
movie_ticket_sell.save()
It seems like the event needs to have a ticket amount field to verify what the max tickets are. Then it should have a foreign key relationship with the ticket_class. In order to make sure you do not exceed the amount of tickets available then you would probably need to use something like the clean method to verify it does not exceed when associating a ticket to an event.
https://docs.djangoproject.com/en/1.5/ref/models/instances/#django.db.models.Model.clean
I'm just looking at this from a high level so maybe I'm missing something. I'm also unclear why you can't just have the date be a field in the event?
I want to understand how to use ReferenceProperty for common usage scenarios.
In a typical application, we always display Referenced Entity's columns.
For example, consider a Purchase Order application.
class POCategory(db.Model):
name = db.StringProperty()
class POSubCategory(db.Model):
category = db.ReferenceProperty(POCategory, collection_name='sub_categories')
name = db.StringProperty()
class PurchaseOrder(db.Model):
total_amount = db.FloatProperty()
class PurchaseOrderLineItem(db.Model):
category = db.ReferenceProperty(POCategory, collection_name='po_line_items')
sub_category = db.ReferenceProperty(POSubCategory, collection_name = 'po_line_items')
amount = db.FloatProperty()
This is what we normally display in typical applications.
+---------------+---------------+--------+
| Category | Sub Category | Amount |
+---------------+---------------+--------+
| Blue Category | Water | $12.00 |
| Red Category | Fire | $20.00 |
+---------------+---------------+--------+
| Purchase Order Total | $22.00 |
+---------------+---------------+--------+
Should I be using ReferenceProperty Pre-fetching for this to avoid N+1 select problem?
or
duplicate the category and sub-category names in my Purchase Order Line Item like below?
class PurchaseOrderLineItem(db.Model):
category = db.ReferenceProperty(POCategory, collection_name='po_line_items')
category_name = db.StringProperty()
sub_category = db.ReferenceProperty(POSubCategory, collection_name = 'po_line_items')
sub_category_name = db.StringProperty()
amount = db.FloatProperty()
Obviously, the names for categories and sub-categories are editable.
So when someone updates the name property, I will have to query and loop over all referenced PurchaseOrderLineItem entities and update my duplicate name properties.
#----------------------------------------
# BAD DESIGN
#----------------------------------------
po_category.name = 'New Category Name'
# build list of line items to be updated
update_list = []
for child_line_item in po_category.po_line_items:
child_line_item.category_name = po_entity.name
update_list.append(child_line_item)
db.put(po_category, update_list)
I know it is NOT a good scalable solution because over time we will have a lot of Line Items to be updated. RDBMS way of thinking is hard to get rid of.
So can anyone please teach me how to think for these kinds of typical scenarios?
Thanks!
As you said, since you can often edit category name, you should not embed it into Line Item.
Instead use NDB (which automatically caches gets) and multi-get (one DB call to get multiple entities) to get categories and sub-categories.
This is my model, Players and Clubs. As a Club can have many players and a player can have many clubs (in its carrer), I used a many-to-many relationship:
class Club(db.Model):
name = db.StringProperty()
link = db.StringProperty()
class Player(db.Model):
name = db.StringProperty()
link = db.LinkProperty()
class ClubHasPlayer(db.Model):
club = db.ReferenceProperty(Club, required=True,
collection_name='club_players')
player = db.ReferenceProperty(Player, required=True,
collection_name='player_clubs')
number = IntegerProperty()
Now, I have a search interface where one can search for all players, and add zero or more restrictions, such as player name, and club where he played. Thus, I have a cascade type of handling this:
players = player.all()
if filter_by_player_name:
players.filter("name =",filter_by_player_name)
Now, I want to do this:
if filter_by_club_name:
players.filter(????)
I still think in terms of SQL, and it should be something like a nested clause :
select * from player where player.name='x' and player.id in (select club_has_player.player_id from club_has_player, club where club_has_player.club_id = club.id and club_name = "Y")
How to do it?
I know I could go from the club, that is:
club = Club.filter("name =",filter_by_club_name).get()
club.club_players
but this style discards a previous filter, that could be player names...
Can anybody help me here? Thanks.
One common advice in the GAE community is to denormalize your models. This can be useful in this specific situation. You can store the club name in every player entity as a string, in addition to the reference property to the club:
class Player(db.Model):
name = db.StringProperty()
link = db.LinkProperty()
club = db.ReferenceProperty(club)
club_name = db.StringProperty()
This would allow you to easily filter Players by club name.
Obviously, this makes changing club names harder. But the probability of having to change a club name is low.