I have two Django models, and I want to have same-value field in both of them. Basically, when CarModification.engine_status
is 'inactive'
or 'active'
, I want to have the same field in Car set to the latest CarModification
's field value.
class CarManager(models.Manager):
def get_queryset(self):
# Select engine_status from the latest
# carmodification. If there are no modifications,
# use default 'inactive'
return super(CarManager, self).get_queryset().extra(
select={
'engine_status': "SELECT COALESCE ( "
" (SELECT engine_status "
" FROM carmodifications "
" WHERE cars.id = carmodifications.car_id "
" ORDER BY carmodifications.created_at DESC "
" LIMIT 1), 'inactive')"
)
class Car(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = CarManager()
class CarModification(models.Model):
CHOICES = (
('active', 'Active')
('inactive', 'Inactive')
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
comment = models.CharField()
engine_status = models.CharField(default='inactive', choices=CHOICES)
car = models.ForeignKey(Car, related_name='modifications')
This works fine, but I also want an ability to filter Car objects by this extra field. Which is possible with more SQL queries, but it gets (and I think it already is) pretty ugly. Is there a way to accomplish the same, but cleaner way using Django ORM?
I think you can try to solve this with annotations rather than with extra. Annotations will allow you to use the new created field for filtering. More info: https://docs.djangoproject.com/en/1.8/topics/db/aggregation/ .
Btw, since it seems you always need the engine_status
on your Car. Why don't you just create a field on your Car model and set its status with signals every time there is a CarModification creation?
I prefer use signal
in this situation:
class Car(models.Model):
engine_status = models.CharField(max_length=256, default='inactive')
class CarModification(models.Model):
CHOICES = (
('active', 'Active'),
('inactive', 'Inactive')
)
engine_status = models.CharField(max_length=256, default='inactive', choices=CHOICES)
car = models.ForeignKey(Car, related_name='modifications')
@receiver(post_save, sender=CarModification)
def pre_save_handler(sender, **kwargs):
"""after saving CarModification, change car's engine_status"""
instance = kwargs.get('instance')
if instance.car_id:
current_car = Car.objects.filter(id=instance.car_id)[0]
current_car.engine_status = instance.engine_status
current_car.save()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.