2222# Application definition
2323
2424INSTALLED_APPS = [
25- ' django.contrib.admin' ,
26- ' django.contrib.auth' ,
27- ' django.contrib.contenttypes' ,
28- ' django.contrib.sessions' ,
29- ' django.contrib.messages' ,
30- ' django.contrib.staticfiles' ,
25+ " django.contrib.admin" ,
26+ " django.contrib.auth" ,
27+ " django.contrib.contenttypes" ,
28+ " django.contrib.sessions" ,
29+ " django.contrib.messages" ,
30+ " django.contrib.staticfiles" ,
3131 # Third party
32- ' rest_framework' ,
33- ' rest_framework_simplejwt.token_blacklist' ,
32+ " rest_framework" ,
33+ " rest_framework_simplejwt.token_blacklist" ,
3434 # Apps locales
35- ' users' ,
36- ' products' ,
35+ " users" ,
36+ " products" ,
3737]
3838
3939MIDDLEWARE = [
40- ' django.middleware.security.SecurityMiddleware' ,
41- ' django.contrib.sessions.middleware.SessionMiddleware' ,
42- ' django.middleware.common.CommonMiddleware' ,
43- ' django.middleware.csrf.CsrfViewMiddleware' ,
44- ' django.contrib.auth.middleware.AuthenticationMiddleware' ,
45- ' django.contrib.messages.middleware.MessageMiddleware' ,
46- ' django.middleware.clickjacking.XFrameOptionsMiddleware' ,
40+ " django.middleware.security.SecurityMiddleware" ,
41+ " django.contrib.sessions.middleware.SessionMiddleware" ,
42+ " django.middleware.common.CommonMiddleware" ,
43+ " django.middleware.csrf.CsrfViewMiddleware" ,
44+ " django.contrib.auth.middleware.AuthenticationMiddleware" ,
45+ " django.contrib.messages.middleware.MessageMiddleware" ,
46+ " django.middleware.clickjacking.XFrameOptionsMiddleware" ,
4747]
4848MIDDLEWARE .append ("myproject.middleware.RequestLoggingMiddleware" )
4949
50- ROOT_URLCONF = ' myproject.urls'
50+ ROOT_URLCONF = " myproject.urls"
5151
5252TEMPLATES = [
5353 {
54- ' BACKEND' : ' django.template.backends.django.DjangoTemplates' ,
55- ' DIRS' : [],
56- ' APP_DIRS' : True ,
57- ' OPTIONS' : {
58- ' context_processors' : [
59- ' django.template.context_processors.debug' ,
60- ' django.template.context_processors.request' ,
61- ' django.contrib.auth.context_processors.auth' ,
62- ' django.contrib.messages.context_processors.messages' ,
54+ " BACKEND" : " django.template.backends.django.DjangoTemplates" ,
55+ " DIRS" : [],
56+ " APP_DIRS" : True ,
57+ " OPTIONS" : {
58+ " context_processors" : [
59+ " django.template.context_processors.debug" ,
60+ " django.template.context_processors.request" ,
61+ " django.contrib.auth.context_processors.auth" ,
62+ " django.contrib.messages.context_processors.messages" ,
6363 ],
6464 },
6565 },
6666]
6767
68- WSGI_APPLICATION = ' myproject.wsgi.application'
68+ WSGI_APPLICATION = " myproject.wsgi.application"
6969
7070
7171# Database
7272# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
7373
7474DATABASES = {
75- ' default' : {
76- ' ENGINE' : ' django.db.backends.postgresql' ,
77- ' NAME' : os .getenv (' POSTGRES_DB' , ' postgres' ),
78- ' USER' : os .getenv (' POSTGRES_USER' , ' postgres' ),
79- ' PASSWORD' : os .getenv (' POSTGRES_PASSWORD' , ' postgres' ),
80- ' HOST' : os .getenv (' POSTGRES_HOST' , 'db' ),
81- ' PORT' : os .getenv (' POSTGRES_PORT' , ' 5432' ),
75+ " default" : {
76+ " ENGINE" : " django.db.backends.postgresql" ,
77+ " NAME" : os .getenv (" POSTGRES_DB" , " postgres" ),
78+ " USER" : os .getenv (" POSTGRES_USER" , " postgres" ),
79+ " PASSWORD" : os .getenv (" POSTGRES_PASSWORD" , " postgres" ),
80+ " HOST" : os .getenv (" POSTGRES_HOST" , "db" ),
81+ " PORT" : os .getenv (" POSTGRES_PORT" , " 5432" ),
8282 }
8383}
8484
8888
8989AUTH_PASSWORD_VALIDATORS = [
9090 {
91- ' NAME' : ' django.contrib.auth.password_validation.UserAttributeSimilarityValidator' ,
91+ " NAME" : " django.contrib.auth.password_validation.UserAttributeSimilarityValidator" ,
9292 },
9393 {
94- ' NAME' : ' django.contrib.auth.password_validation.MinimumLengthValidator' ,
94+ " NAME" : " django.contrib.auth.password_validation.MinimumLengthValidator" ,
9595 },
9696 {
97- ' NAME' : ' django.contrib.auth.password_validation.CommonPasswordValidator' ,
97+ " NAME" : " django.contrib.auth.password_validation.CommonPasswordValidator" ,
9898 },
9999 {
100- ' NAME' : ' django.contrib.auth.password_validation.NumericPasswordValidator' ,
100+ " NAME" : " django.contrib.auth.password_validation.NumericPasswordValidator" ,
101101 },
102102]
103103
107107
108108
109109# Internacionalización
110- LANGUAGE_CODE = ' es-pe'
111- TIME_ZONE = ' America/Lima'
110+ LANGUAGE_CODE = " es-pe"
111+ TIME_ZONE = " America/Lima"
112112USE_I18N = True
113113USE_TZ = True
114114
117117# https://docs.djangoproject.com/en/4.2/howto/static-files/
118118
119119# Archivos estáticos
120- STATIC_URL = ' static/'
121- STATIC_ROOT = os .path .join (BASE_DIR , ' staticfiles' ) # coincidir con ./staticfiles
120+ STATIC_URL = " static/"
121+ STATIC_ROOT = os .path .join (BASE_DIR , " staticfiles" ) # coincidir con ./staticfiles
122122
123- DEFAULT_AUTO_FIELD = ' django.db.models.BigAutoField'
123+ DEFAULT_AUTO_FIELD = " django.db.models.BigAutoField"
124124
125125# 🔥 MODELO DE USUARIO PERSONALIZADO
126- AUTH_USER_MODEL = ' users.CustomUser'
126+ AUTH_USER_MODEL = " users.CustomUser"
127127
128128# 🔥 CONFIGURACIÓN DE REST FRAMEWORK
129129REST_FRAMEWORK = {
130- ' DEFAULT_AUTHENTICATION_CLASSES' : (
131- ' rest_framework_simplejwt.authentication.JWTAuthentication' ,
130+ " DEFAULT_AUTHENTICATION_CLASSES" : (
131+ " rest_framework_simplejwt.authentication.JWTAuthentication" ,
132132 ),
133- "DEFAULT_THROTTLE_CLASSES" : [
133+ "DEFAULT_THROTTLE_CLASSES" : [
134134 "rest_framework.throttling.AnonRateThrottle" ,
135135 "rest_framework.throttling.UserRateThrottle" ,
136136 ],
137-
138137 "DEFAULT_THROTTLE_RATES" : {
139- "anon" : "20/min" , # 🔒 usuarios no autenticados
138+ "anon" : "20/min" , # 🔒 usuarios no autenticados
140139 "user" : "100/min" , # 🔒 usuarios autenticados
141- ' login' : ' 5/minute' ,
140+ " login" : " 5/minute" ,
142141 },
143142}
144143
145144SIMPLE_JWT = {
146- ' ACCESS_TOKEN_LIFETIME' : timedelta (minutes = 30 ),
147- ' REFRESH_TOKEN_LIFETIME' : timedelta (days = 1 ),
148- ' AUTH_HEADER_TYPES' : (' Bearer' ,),
149- "ROTATE_REFRESH_TOKENS" : True , # ✅ CLAVE
145+ " ACCESS_TOKEN_LIFETIME" : timedelta (minutes = 30 ),
146+ " REFRESH_TOKEN_LIFETIME" : timedelta (days = 1 ),
147+ " AUTH_HEADER_TYPES" : (" Bearer" ,),
148+ "ROTATE_REFRESH_TOKENS" : True , # ✅ CLAVE
150149 "BLACKLIST_AFTER_ROTATION" : True , # ✅ CLAVE
151150 "AUTH_TOKEN_CLASSES" : ("rest_framework_simplejwt.tokens.AccessToken" ,),
152-
153151}
154152
155- LOG_DIR = os .path .join (BASE_DIR , ' logs' )
153+ LOG_DIR = os .path .join (BASE_DIR , " logs" )
156154os .makedirs (LOG_DIR , exist_ok = True )
157155
158156LOGGING = {
159- ' version' : 1 ,
160- ' disable_existing_loggers' : False ,
161- ' formatters' : {
162- ' verbose' : {
163- ' format' : ' [{levelname}] {asctime} {module} {message}' ,
164- ' style' : '{' ,
157+ " version" : 1 ,
158+ " disable_existing_loggers" : False ,
159+ " formatters" : {
160+ " verbose" : {
161+ " format" : " [{levelname}] {asctime} {module} {message}" ,
162+ " style" : "{" ,
165163 },
166164 },
167- ' handlers' : {
168- ' file' : {
169- ' level' : ' INFO' ,
170- ' class' : ' logging.FileHandler' ,
171- ' filename' : os .path .join (LOG_DIR , ' app.log' ),
172- ' formatter' : ' verbose' ,
165+ " handlers" : {
166+ " file" : {
167+ " level" : " INFO" ,
168+ " class" : " logging.FileHandler" ,
169+ " filename" : os .path .join (LOG_DIR , " app.log" ),
170+ " formatter" : " verbose" ,
173171 },
174- ' console' : {
175- ' class' : ' logging.StreamHandler' ,
172+ " console" : {
173+ " class" : " logging.StreamHandler" ,
176174 },
177175 },
178- ' root' : {
179- ' handlers' : [' file' , ' console' ],
180- ' level' : ' INFO' ,
176+ " root" : {
177+ " handlers" : [" file" , " console" ],
178+ " level" : " INFO" ,
181179 },
182180}
183181
184- REST_FRAMEWORK ["DEFAULT_THROTTLE_RATES" ].update ({
185- "login" : "5/min" , # 🔥 solo 5 intentos por minuto por IP
186- })
182+ REST_FRAMEWORK ["DEFAULT_THROTTLE_RATES" ].update (
183+ {
184+ "login" : "5/min" , # 🔥 solo 5 intentos por minuto por IP
185+ }
186+ )
187187
188188if "pytest" in sys .argv [0 ]:
189189 REST_FRAMEWORK ["DEFAULT_THROTTLE_CLASSES" ] = []
190-
190+
191191LOGGING = {
192192 "version" : 1 ,
193193 "disable_existing_loggers" : False ,
194-
195194 "formatters" : {
196195 "verbose" : {
197196 "format" : "[{levelname}] {asctime} {name} | {message}" ,
202201 "style" : "{" ,
203202 },
204203 },
205-
206204 "handlers" : {
207205 "console" : {
208206 "class" : "logging.StreamHandler" ,
209207 "formatter" : "verbose" ,
210208 },
211209 },
212-
213210 "loggers" : {
214211 "django" : {
215212 "handlers" : ["console" ],
222219 },
223220 },
224221}
225-
0 commit comments