I see, I think you'll need to wrap the inner Q in an ExpressionWrapper[0]

That would be

CheckConstraint(check=Q(is_on_sale=ExpressionWrapper(Q(price__lt=F('full_price')),
 
output_field=models.BooleanField())))

That involves a lot of boilerplate though and it ought to work without all 
of it so I'd submit an optimization ticket
to allow direct usage of Q objects for boolean field lookup right hand sides

Cheers,
Simon

https://docs.djangoproject.com/en/3.0/ref/models/expressions/#django.db.models.ExpressionWrapper

Le lundi 27 janvier 2020 14:32:24 UTC-5, Peter Law a écrit :
>
> Hi Simon,
>
> Thanks for your response.
>
> I did try that, however unfortunately I get an error when running the 
> migration:
>
> django.core.exceptions.ValidationError: ["'(AND: 
> <django.db.models.lookups.LessThan object at 0x7fcc49998a20>)' value must 
> be either True or False."]
>
> I'm using Django 2.2 LTS though testing this in 3.0 unfortunately errors 
> in the same way.
>
> I think the issue with this spelling is that a `models.Q` isn't expecting 
> to be passed another `models.Q` as a value. I think ideally it would want 
> an expression there, which a `models.F` is closest to, however using a 
> `models.F` relation there also doesn't work (see my response to Stephen's 
> suggestion).
>
> Thanks,
> Peter
>
> On Monday, 27 January 2020 18:23:28 UTC, Simon Charette wrote:
>>
>> Did you try
>>
>> class Item(Model):
>>     price = DecimalField()
>>     full_price = DecimalField()
>>     is_on_sale = BooleanField()
>>
>>     class Meta:
>>         constraints = [
>>             
>> CheckConstraint(check=Q(is_on_sale=Q(price__lt=F('full_price'))))
>>         ]
>>
>> I haven't tried it myself but I would expect it to work on Django 3.0.
>>
>> Cheers,
>> Simon
>>
>> Le lundi 27 janvier 2020 12:47:37 UTC-5, Peter Law a écrit :
>>>
>>> Hi, 
>>>
>>> Thanks for adding support for check constraints in Django 2.2, it's 
>>> great to be able to move constraints into the model definitions. 
>>>
>>> I've been trying to work out how to express a constraint which 
>>> validates that the value of one field expresses a relation between two 
>>> other fields, but can't find a nice way to do so. 
>>>
>>> I've read through the docs and also found 
>>> https://groups.google.com/d/topic/django-users/6Olh5V1b7Us/discussion, 
>>> but haven't found a concise spelling. 
>>>
>>> I've got a model like: 
>>>
>>> ``` 
>>> class Item(Model): 
>>>     price = DecimalField() 
>>>     full_price = DecimalField() 
>>>     is_on_sale = BooleanField() 
>>> ``` 
>>>
>>> I'd like to be able to express neatly that the `is_on_sale` boolean be 
>>> true only when `price < full_price`. 
>>> In Postgres I can express this as: 
>>>
>>> ``` 
>>> ALTER TABLE item 
>>> ADD CONSTRAINT is_on_sale_check 
>>> CHECK (is_on_sale = (price < full_price)) 
>>> ``` 
>>>
>>> However in Django I can't find a way to express this directly. 
>>>
>>> I did find a long spelling which essentially checks the True case and 
>>> the False case explicitly and then ORs them together, however it's 
>>> several lines of `models.Q` combinations and not at all clear about 
>>> what the code is trying to achieve. 
>>>
>>> Is there a concise way to do this sort of constraint? If not, would it 
>>> be possible for Django to add support for it? 
>>>
>>> Thanks, 
>>> Peter 
>>>
>>

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/5d9488a8-7e6d-4a96-b009-fd94feb9df86%40googlegroups.com.

Reply via email to