python이 아닌 데이터베이스에서 필드값을 update하면 F() 는 race condition을 피할 수 있다.
예시)
만약 2개의 python threads가 코들르 실행한다면, 다른 한 thread가 데이터 베이스로부터 field 값을 조회 한 후, 다른 하나의 thread는 field 값을 조회, 증가, 그리고 저장 할 수 있습니다. 다른 하나의 thread가 기존의 값을 바탕으로 한 저장한 값; 첫번째 thread 작업은 손실 될것이다.
만약 그 데이터 베이스가 그 field값을 책을 진다면, 그 process는 더욱 강력합니다. save(), update() 함수를 실행할때, 데이터 베이스에 그 field 값을 기반으로 한 그 field만 항상 update 것 입니다. 인스턴스가 조회 되었을때 값을 기반으로 하지 않습니다.(인스턴스에 캐쉬된 값을 기반으로 하지 않는다는 것 같다)
F() 모델 fields에 할당된 objects는 model instance를 저장한 후에 지속된다 그리고 각각 save() 함수에 적용 될 것이다.
reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed = F('stories_filed') + 1
reporter.save()
reporter.name = 'Tintin Jr.'
reporter.save()
stories_field는 이러한 경우에 두번 update 될것이다. 처음 1이었다면 마지막 값은 3일 것이다.
이러한 persistence는 그것을 저장한 후에 model objects를 reloading 함으로써 피할수 있다.
refresh_from_db() 사용함으로써
F()는 QuerySet에 유용하다, Python 값이 아닌 그들의 field 값에 기반한 기준에 따른 a set of objects를 filter 할 수 있다.
F()는 다른 필드들과 산술하여 결합함으로써 model 에 동적 필드를 생성되어 질수 있다.
company = Company.objects.annotate(
chairs_needed=F('num_employees') - F('num_chairs'))
만약 다른 유형들을 결합한 그 fields는 Django에게 어떤 종류의 필드가 반환 될것인지 말할 필요가 있다.
F()는 output_field를 직접적으로 지원하지 않으므로 당신은 ExpressionWrapper로 expression을 감쌀 필요가 있다.
from django.db.models import DateTimeField, ExpressionWrapper, F
Ticket.objects.annotate(
expires=ExpressionWrapper(
F('active_at') + F('duration'), output_field=DateTimeField()
)
)
ForeignKey와 같은 관계 fieldsfmf 참조 할때, F()는 model instance보다 primary key를 반환한다.
>> car = Company.objects.annotate(built_by=F('manufacturer'))[0]
>> car.manufacturer
<Manufacturer: Toyota>
# id 값을 반환함
>> car.built_by
3
a field's null values 의 순서를 조정하기 위해서 Expression.asc() or desc() 에 nulls_first or nulls_last키워드 인수 그리고 F()를 사용해라.
예시, nulls_last=True 인 값 반대로? (?????????? 직접 봐야 알것 같음
from django.db.models import F
Company.objects.order_by(F('last_contaced').desc(nulls_last=True))
Func() expressions는 데이터베이스 functions를 포함시킨 모든 expressions의 기본 type 이다.
from djnaog.db.models import F, Func
queryset.annotate(field_lower=Func(F('field'), function='LOWER'))
or Func() expressions( like COALESCE, LOWER)는 데이터 베이스 functions의 라이브러리를 build하는데 이용되고 있다.
class Lower(Func):
function = 'LOWER'
queryset.annotate(field_lower=Lower=('field'))
그러나 두 경우 모두 각 모델은 다음에 오는 SQL문으로부터 생상된 추가 속성 field_lower로 annotated 된 하나의 queryset으로 결과가 나타날 것이다.
내장 데이터베이스 함수들의 목록에 대해 Database Functions를 보라
The Func API는 다음과 같습니다.
class Func(*expressions, **extra)
function
class 속성, 문자 형식(characterfield 의미하는거 같음), this function을 생성되어진 SQL을 설명하는. 기본은 '%(function)s(%(expressions)s)'.
???????????????????????????????
만약 당신이 strftime('%W', 'date') 과 같은 SQL을 구성한다면 그리고 쿼리의 리터럴 % 문자를 필요로 한다면, template 속성에서 4배 (%%%%) 이다 그 문자는 두배 보관되어지기 때문이다. as_sql()에서 ?template보관 동안에 한번 그리고 데이터베이스 커서에서 쿼리 파라미터를 가진 SQL 보관 에서 한번
arg_joiner
expressions 리트스를 join하는데 사용되는 문자열을 나타내는 하나의 클래스 속성. 기본값은 ','입니다.
arity
the function이 수락하는 인수의 숫자를 나타내는 하나의 클래스 속성. 만약 이 속성이 set 이고 the function이 다른 수의 expressions으로 호출되어진다면, TypeError는 발생할것이다 기본갑슨 None
as_sql(compiler, connection, cuntion=None, template=None, arg_joiner=None, **extra_context)
데이터베이스 function에 대한 SQL fragment를 생성시켜라. 나타낸다 (sql, params) 튜플, sql이 SQL string, 그리고 params 쿼리 파라미터 튜플 혹은 리스트 이다.
The as_vendor() methods는 function, template, arg_joiner, 그리고 다른 **extra_context 필요에 따라 customize 하기 위한 parameters(매개변수)를 사용한다.
class ConcatPair(Func):
...
function = 'CONCAT'
...
def as_mysql(self, compiler, connection, **extra_context):
return super().as_sql(
compiler, connection,
function='CONCAT_WS',
template="%(function)s('', %(expressions)s)",
**extra_context
)
SQL injection 취약성을 피하기 위해 extra_context는 신뢰되지 않는 user 입력을 포함해서는 안됩니다 rather than 데이터메이스 driver가 이것들을 빠져나가는 쿼리 매개변수로써 전달 되어진기 보다 이러한 값들은 SQL string에 보관되어 진다.
The *expressions 인수는 그 함수가 적용되어질 예정인 expressions list 위치인자 이다.
The expressions는 arg_joiner와 함께 결합된 문자열로 변환 됩니다. 그리고 expresions 자리표시자로써 template에 보관 됩니다.
위치인자들은 python 값들 혹은 expressions 될수 있다. 문자열은 column 참조로 추정되고 F() expressions로 감싸질것이다. 다른 값들이 Value() expressions에 감싸지는 반면에.
the **extra kwargs는 template 속성에 보관되어진 key=value 이다.
the function, template, and arg_joiner 키워드들은 같은 이름의 속성들을 대체될 수 있다 your 자신의 class 정의 없이.
output_field는 예상되는 반환되는 type을 정의하는데 사용 할수 있다.
aggregate expression은 GROUP BY 절이 필요로 하는 the query를 알려주는 Func() expression 의 특별한 case이다. 모든 aggregate functions, SUM() and Count(), Aggregate()로 부터 상속받은.
Aggregates는 expressions 그리고 expressions을 감싸함으로 you는 몇몇 복잡한 계산을 나타낼 수 있다.
from django.db.models import Count
Company.objects.annotate(
managers_required=(Count('num_employees') / 4) + Count('num_managers'))
the Aggregate API 는 필요에 따라:
class Aggregate(*expressions, output_field=None, distinct=False, filter=None, default=None, **extra)
function
생성되는 aggregate function을 설명하는 a class 속성, the function은 the function placeholder로써 보관 되어 질것이다 template 안에. function=None(Default)
window_compatible
window_compatible=True(Default), 대부분 aggregate functions는 source expressions으로 사용할 수 있습니다.
allow_distinct
하나의 클래스 속성은 고유한 키워드 인수를 전달하는 것이 허용 가능한지 여부를 결정한다.
만약 allow_distinct=False(default), TypeError가 발생된다 만약 distinct=True가 전달 된다면.
empty_result_set_value
empty_result_set_value=None(Default), 대부분 aggregate functions는 null를 결과로 나타낸다. empty 결과값을 에 적용 될때.
The expressions 위치 인자들은 model field의 변형 혹은 model fiels의 이름들은 expressions를 포함시킬수 있다. 그들은 strin으로 변환될 것이다 그리고 expressions placeholder로써 사용될 것이다. template 안에서.
The output_field 인자는 IntegerField() or BooleanField(0와 같은 model field instance를 필요로 하며, Django는 데이터 베이스로 부터 조회한 후에 값을 불러온 후, 이 인스턴스에 값을 로드합니다. 보통 arguments는 필요하지 않습니다 데이터 유효성 검사와 관련된 인수로 모델 필드를 인스턴스화 할때,
Django가 어떤 필드 타입 결과가 되어야만 하는지를 결정할수 있을때, Note that output_field만 요구 되어 진다. 복잡한 expressions는 mix field 유형은 원하는 output_field를 정의 해야만한다. 예를들어, IntegerField() 와 FloatField()는 함께 추가하면 output_field=FloatField()가 정의 되어 있어야만 합니다.
고유의 인자는 aggregate function가 각각 expressions의 고유 값을 호출 해야하는지 여부를 결정한다.인자는 allow_distinct=True 설정을 가진 aggregate에서만 지원 받는다.
filter 인자는 집계 되는 row를 filter하는데 사용되는 Q object를 취한다. 조건 집계 와 annotaions 필터 예시 사용
기본 인자는 통합에 집계와 함께 Coalesce에 전달될 값을 사용합니다. 이것은 queryset이 아무 항목이 포함되지 않았을때 None이외의 값을 반환하도록 지정하는데 유용하다.