Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django - Use model fields part in a create or update query

Given the following models in a Django 2.2 app:

class ShelfPosition(models.Model):
    shelf_code = models.CharField(max_length=10)
    row = models.IntegerField()
    column = models.IntegerField()

    class Meta:
        constraints = [
            models.UniqueConstraint(fields=["shelf_number", "row", "column"], name="shelfpos_unique")
        ]

class Item(models.Model):
    name = models.CharField(max_length=255)
    position = models.OneToOneField(to=ShelfPosition, on_delete=models.SET_NULL, primary_key=True)

I rely on Django's lookup feature to filter on Item objects depending on some ShelfPosition fields: Item.objects.filter(position__shelf_code="BF4")

Is there any way I could implement a similar lookup functionality such as described above when using get_or_create or update_or_create?

item, created = Item.objects.get_or_create(
    position__shelf_code="BF6",
    position__row=88,
    position__column=1,
    defaults={……}
)

I find it less verbose than the following, even if with this example it's not really relevant:

item, created = Item.objects.get_or_create(
    position = Position.objects.get_or_create(
        shelf_code="BF6",
        row=88,
        column=1
    ),
    defaults={……}
)
like image 684
Spacebrain Avatar asked Apr 01 '20 09:04

Spacebrain


People also ask

How do I update model fields in Django?

Method 2: Using F Expression You can also use the F expression to do the same job. Note: You have to import the F expression before using it. Basically, these are the two methods you can use to update field in Django model.

What is __ str __ in Django?

The __str__ method in Python represents the class objects as a string – it can be used for classes. The __str__ method should be defined in a way that is easy to read and outputs all the members of the class. This method is also used as a debugging tool when the members of a class need to be checked.

How do you add a new field to a model with new Django migrations?

To answer your question, with the new migration introduced in Django 1.7, in order to add a new field to a model you can simply add that field to your model and initialize migrations with ./manage.py makemigrations and then run ./manage.py migrate and the new field will be added to your DB. Save this answer.

How Django knows to update VS insert?

The doc says: If the object's primary key attribute is set to a value that evaluates to True (i.e. a value other than None or the empty string), Django executes an UPDATE. If the object's primary key attribute is not set or if the UPDATE didn't update anything, Django executes an INSERT link.


1 Answers

Not sure this is what you are looking for but if you used multi-table inheritance you could achieve the following

class ShelfPosition(models.Model):
    shelf_code = models.CharField(max_length=10)
    row = models.IntegerField()
    column = models.IntegerField()

    class Meta:
        unique_together = ("shelf_code", "row", "column")

class Item(ShelfPosition):
    name = models.CharField(max_length=255)

item, created = Item.objects.get_or_create(
    shelf_code="BF6",
    row=88,
    column=1,
    defaults={
       "name": "Spam",
    }
)

You'd just have to make sure to pass keep_parents=True when calling item.delete() if you want to preserve the ShelfPosition row as the default MTI behavior is to delete the whole ancestor chain.

like image 60
Simon Charette Avatar answered Oct 15 '22 06:10

Simon Charette