Toms Code
Toms Code

Reputation: 1689

I would like to only allow one entry for a row in a model in Django, is this possible?

Im building an inventory management web app (stock room manager).

I have a model class:

class location(models.Model):
    loc_room = models.CharField(max_length=20, blank=True, null=True)
    loc_section = models.IntegerField(blank=True, null=True)
    loc_shelf = models.CharField(max_length=4, blank=True, null=True)

And a model class:

class box(models.Model):    
    box_contents = models.CharField(max_length=300, blank=True, null=True) 
    location_id = models.ForeignKey('location', null=True)

Is there a way that I could limit the number of boxes per location to only one entry? Its for a store room that only has one box per 'location'.

E.g What I would like: At location Room: A, Section 1, Shelf 2 there should only ever be 1 x box with contents: 'Screwdriver, drill, shampoo'.

E.g What is currently the case: At location Room: A, Section 1, Shelf 2 = 1 x box with contents: 'Screwdriver, drill, shampoo' ALSO 1 x box wiith contents: 'Towel rack, cups'

At the moment, employees can add as many boxes per location as they like but I would like to limit this to one box as each location can physically only contain one box.

Upvotes: 0

Views: 781

Answers (2)

bruno desthuilliers
bruno desthuilliers

Reputation: 77912

According to the relational model normalisation rules, if you can only have one single instance of B for a given instance of A and all A have one instance of B (1 to 1 relationship), then A and B are really the same entity, so you should then move box_contents to Location and remove the Box model.

If A can have 0 or 1 B (and B only belong to a single A), you can either do as above but allow null for box_contents, in which case null means there's no box for this location while the empty string means "there's a box but it's empty" or - if you find it impractical or have other reasons to want to keep a distinct Box model - put a unique contraint on Box.location - and since you're using django, use a models.OneToOneField instead of a ForeignKey field.

As a side note :

1/ the convention is to use CamelCase for class names (Location' andBox, notlocationandbox) - this makes life easier when it comes to naming aLocation` instance

2/ the ForeignKey (or OneToOneField) in Box should really be named location - because when using box.location, you will get a Location object, not the underlying location_id.

Upvotes: 1

Daniel Roseman
Daniel Roseman

Reputation: 599628

Since a box can only be in one location and a location can only have one box, you should have a OneToOneField rather than a ForeignKey.

(Note also, you shouldn't use the suffix _id for your field names; the Django field refers to the entire related object.)

class box(models.Model):    
    box_contents = models.CharField(max_length=300, blank=True, null=True) 
    location = models.OneToOneField('location', null=True)

Upvotes: 0

Related Questions