Cansada de ser feliz

Bienvenidos a mi flujo de conciencia

Classic Dutch ladies bicycle for Sale

| Comments

Condition: I bought it on the 11th of November 2015, so it’s almost new (I have an invoice from the shop where I bought it as a proof that it’s not stolen).
Color: Black
Model: Avalon Oma 26 Inch Damesfiets
Speeds: No
Lighting: Front and rear battery lighting
Brakes: Coaster brake
Accessories: Metal basket, chain lock
Price: SOLD

Zuleijá abre los ojos por Guzél Yájina

| Comments

La novela empieza en el año 1930. La protagonista es una mujer tártara de 30 años llamada Zuleijá, que vivía en una aldea apartada con su esposo, que era 30 años mayor que ella, y con la suegra cuyo apodo era Upirija (Vampira). La vida de Zuleijá era muy difícil: ella trabajaba día a día, atendiendo a su esposo Murtazá y a su mamá, pero nunca se había quejado, porque así había sido educada por sus padres: aguantar todas los insultos, las humillaciones y las palizas de su esposo y obedecerle en todo.

En el primer capítulo nos familiarizamos con la vida diaria de Zuleijá: cuáles eran sus deberes de la casa, qué pasaba durante su día habitual, qué pasaba durante su día habitual, qué había pasado en su vida durante sus últimos 15 años de matrimonio. Nosotros conocemos su cosmovisión, sus creencias y supersticiones, que Zuleijá tuvo cuatro hijas, pero todas habían muerto cuando todavía eran bebés. Vemos cómo ella hablaba con los duendes y les llevaba comida.

Pero su vida mesurada se interrumpió cuando los soldados del Ejército Rojo (o de “Horda Roja”, como los llamaban por allá) llegaron a su aldea para realizar la campaña de deskulakización, es decir, quitar los bienes de los campesinos más ricos (kuláks) y deportarles para “desarrollar las tierras lejanas del país”. Murtazá puso resistencia y fue asesinado por el soldado Ignatov. A Zuleijá la enviaron a Siberia a las orillas del río Angará junto con otros campesinos, algunos intelectuales de Leningrado y unos criminales, escoltados por Ignatov.

Durante el viaje Zuleijá se dio cuanta de que había quedado embarazada de su esposo ya hace unos meces, pero a pesar de eso, ella logró soportar la deportación, y al llegar a Siberia dio luz a su hijo Josep.

En Siberia a Ignatov y sus tutelados les dejaron en un área inhabitada del bosque sólo con una escopeta, la bolsa llena de balas y un saco de sal. Así el soldado, Zuleijá, Josep, el pintor Ikonnikov, el doctor Leibe, enloquecido por ver los cambios tan radicales en el país, el pescador Lukká, la anciana intelectual Isabella, que con orgullo llevaba su sombrero de moda y hablaba francés, y los demás compañeros tenían que aprender a construir las casas, armar la estufa y cazar para poder sobrevivir sólos en el bosque. Pero esa experiencia ayudó a Zuleijá a abrir sus ojos verdes y ver el mundo de una forma distinta, le permitió cambiar sus costumbres y creencias (ya no le parecía que Alá la podía ver en un lugar tan lejano), su carácter (porque se convirtió en una mujer fuerte y decidida). Todo lo que entes le parecía imposible o vergonzoso, como sentarse tan cerca a un hombre desconocido en el vagón del tren, ó hacer sus necesidades frente a los demás en el mismo vagón), formó parte de su vida.

La oficina de prensa de Pospechat informó que la novela de Guzél Yájina será traducida a 16 idiomas.


Guezel Yájina nació en Kazán, se graduó del Instituto Pedagógico Estatal de Kazán de la facultad de idiomas extranjeros, y desde el año 1999 vive en Moscú. Ella ha trabajado en el cambo de las relaciones públicas, publicidad y mercadeo. En 2015 Guzel se graduó de la facultad de esritura de guiones de la Escuela de Cine de Moscú. En la revisa “Luces de Siberi” fue publicada su primera novela “Zuleijá abre los ojos”, que ha ganado los premios del “Libro Grande” y “Yasnaya Polyana”.

Enlaces:

Caminata

| Comments

Normalmente cuando me siento mal o muy estresada me pongo a caminar. Cojo ritmo y esto me ayuda a concentrarme en mis pensamientos, cobrar ánimo y relajarme.

…Son la cinco y media de la tarde, salgo del edificio en la 100 con 14 y giro a la derecha. No me gusta mucho ese pedazo porque hay mucha gente caminando al encuentro y formando multitudes. A mi izquierda hay una peluquería donde hay clientes a cualquier hora (¡incluso a las 6 de la mañana!), una cafetería nueva en la que nunca he entrado (pero siempre he querido) y una farmacia donde te dan un caramelo cuando compras algo. Además siempre hay varios carros saliendo de un parqueadero para entrar a la glorieta.

Llego al semáforo en la 100 con 15, que nunca me sale en verde, y espero un rato mientras pasan los colectivos y buses del SITP. Luego cruzo rápido, porque el verde no dura mucho, y paso por un pedazo con el asfalto todo roto y variso vendedores callejeros. Paso frente un tipo curioso que tiene rastas y vende cactuses pequeños o jugos naturales por las mañanas, y miro hacía la izquierda porque por allá siempre salen las motos y camiones de la novena y no hay un semáforo que les detenga. Si sobrevivo ese pedazo, enfrento mi siguiente reto: cruzar el otro carril de la novena, y tomo a la izquierda para seguir por el barrio y evitar la muchedumbre de la 100.

Paso por un sendero en el pasto cubierto de unos bloques cuadrados de cemento, y llego al puente peatonal. Este puente me parece muy chistoso. Primero, tiene sólo una caneca con un aviso encima diciendo que a la basura hay que separarla en tres canecas diferentes. Segundo, tiene unas señales interesantes diciendo que está prohibido subir el puente con armas y también detenerse en el puente. Y tercero, en unos de postes del puente hay una silla amarrada y colgada de un gancho.

Después del puente paso por Carulla, intento de resistir la tentación de entrar y comprar un paquete de rosquitas o maizitos y entro a una plaza con una iglesia a mi izquierda ya mi derecha una sala donde, como me lo dijeron, toman tinto con los muertos. Siempre me sorprende la escultura de Jesús en una de las paredes de la iglesia: en Rusia a Jesús o a los santos siempre les pintan muy flacos y con la cara de infelicidad y sufrimiento.

Luego cruzo la 19 y voy por una calle con edificios bonitos y llego hasta el puente de Transmilenio de la autopista. Me acuerdo del señor con la cara del presidente de Colombia de mis fantasías que vende sánduches por las mañanas. Cruzo el puente y trato de no entrar en pánico por la vibración que hace tanta gente caminando al tiempo.

Me meto otra vez en los barrios y ya de forma automática busco la casa con el loro para mirar si salió a gritar o no.

Después de cruzar varias calles de forma salvaje (o #comonosgusta) me acerco a la panadería con roscones y siento cómo mi solitaria se despierta, pero tomo la decisión de comprar uno en otra ocasión, cuando esté con compañía, porque sólo de esta forma realmente puedo disfrutar de un roscón.

El siguiente paso es tratar de meterse en un bus de Transmilenio en la estación “Calle 100” y durante 15 minutos reflexionar acerca del sistema de transporte y la urbanística en general: los pensamientos que me llegan en los momentos cuando me aprietan por todos lados y además tratan de sacarme en una estación que no me sirve. Luego, después de acomodarme bien entre las rodillas y codos de los otros pasajeros, miro por la ventana y veo las montañas tan majestuosas y tan bellas, y así, al llegar a Suba pasa todo: el estrés, el mal genio y otras tonterías.

Pruebas para formularios en Django

| Comments

En esta entrada de blog quiero compartir la forma en la que escribo ruebas para formularios en un proyecto de Django.

Primero vamos a instalar los paquetes necesarios:

1
2
$ pip install django-webtest
$ pip install factory-boy

WebTest es una biblioteca que nos ayuda a escribir pruebas para las aplicaciones wsgi. Es mucho más poderosa comparando con django.test.Client que viene con Django.

En el archivo de configuración especificamos que vamos a usar la base de datos SQLite para correr nuestras pruebas:

test_settings.py
1
2
3
4
5
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
    }
}

Suponemos que queremos escribir una prueba unitaria para una vista que crea un objeto del modelo Event:

models.py
1
2
3
4
5
6
7
8
class Event(models.Model):
    title = models.CharField(max_length=500)
    start_date = models.DateTimeField()
    end_date = models.DateTimeField(blank=True, null=True)
    people = models.ManyToManyField('history.Person', blank=True, related_name='events')

class Person(models.Model):
    name = models.CharField(max_length=255)

Aquí está la vista que maneja el formulario para crear un evento:

views.py
1
2
3
4
class EventCreateView(LoginRequiredMixin, CreateView):
    model = Event
    form_class = EventForm
    success_url = reverse_lazy('history:timeline')

Ahora escribimos nuestra prueba. Vamos a extender la clase django_webtest.WebTest, que en su lugar extiende django.test.TestCase de Django, y crear a un usuario:

tests.py
1
2
3
4
5
6
7
8
9
10
11
12
13
from django_webtest import WebTest

class HistoryViewsTests(WebTest):
    def setUp(self):
        self.superuser = get_user_model().objects.create_superuser(
            email='superuser@example.com',
            username='superuser',
            password='secret',
        )
        super(HistoryViewsTests, self).setUp()

    def test_create_event(self):
        # código para nuestra prueba

Ahora podemos probar que cuando un usuario trata de acceder nuestra página, se redirige al formulario de acceso (el códigos de estado HTTP es 302):

1
2
url = reverse('history:event_create')
self.app.get(url, status=302)

Ahora vamos a acceder la vista como superusuario:

1
response = self.app.get(url, user=self.superuser, status=200)

Como tenemos solo un formulario en la página, podemos obtenerlo por una de tres formas: por el atributo .form: response.form, por índice response.forms[0] o por id del formulario (artibuto HTML)response.forms['event_form'].

Para facilitar la depuración de nuestras pruebas, podemos pedir a mostrar el response en navegador predeterminado:

1
response.showbrowser()

Ahora podemos diligenciar nuestro formulario con los datos de prueba:

tests.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class HistoryViewsTests(WebTest):
    # ...

    def test_create_event(self):
        person1, person2, person3 = PersonFactory.create_batch(3)
        response = self.app.get(url, user=self.superuser, status=200)

        self.assertFalse(Event.objects.exists())

        form = response.forms['event_form']
        form['title'] = u'Título del evento'
        form['start_date'] = datetime.datetime.now()
        form['people'] = [person1.id, person2.id]
        form.submit().follow()

        self.assertEqual(Event.objects.count(), 1)

        event = Event.objects.first()
        self.assertEqual(event.title, u'Título del evento')

        people = event.people.all()
        self.assertIn(person1, people)
        self.assertIn(person2, people)
        self.assertNotIn(person3, people)

Para generar objetos del modelo Person usamos la biblioteca Factory Boy:

factories.py
1
2
3
4
5
6
7
8
9
10
from ..models import Person

import factory
import factory.fuzzy

class PersonFactory(factory.django.DjangoModelFactory):
    name = factory.fuzzy.FuzzyText(length=50)

    class Meta:
        model = Person

Así podemos acceder los opciones de una selección o selección múltiple:

1
2
3
4
5
>>> print form['people'].options
[(u'1', False, u'GLUZLvZfyjdZEmjNtnAJvsIVljodQjZpzLRDKrqJtYGiDLmSrN'), (u'2', False, u'vOxDBbmLaUXxJkJzcqYgLQpBieSoLtXJcpHCEPUpYUIzybhsAh'), (u'3', False, u'tfXSXCTIQICDwVPYvxZGSXgclFTnHbeYSQaMntxJNcgUJjzAwX')]
>>> form['people'] = [person1.id, person2.id]
>>> print form['people'].value
[u'1', u'2']

Ahora corremos nuestras pruebas y voilà:

1
2
3
4
5
6
7
8
$ ./manage.py test
Creating test database for alias 'default'...
..
----------------------------------------------------------------------
Ran 1 test in 0.463s

OK
Destroying test database for alias 'default'...

Enlaces:

Cómo configurar PyCharm para compilar los archivos SASS

| Comments

Suponemos que tenemos un proyecto con las siguientes carpetas:

app/
   static/
        css/
        sass/
            main.sass
            home.sass
            variables.sass

y queremos que cada vez cuando editemos alguno de los archivos .sass, PyCharm lo compile y ponga en la carpeta app/static/css/:

app/
   static/
        css/
            main.css
            home.css
        sass/
            main.sass
            home.sass
            variables.sass

Para esto debemos ir a File -> Settings -> File Watchers y agregar un nuevo watcher, escogiendo la opción SASS

y editar las configuraciones:

How to raise a form invalid event inside form_valid method of a FormView

| Comments

How to raise form invalid inside form_valid method of a FormView (CreateView/UpdateView) and add an error message to non_field_errors:

How to show a BooleanField of a ModelForm as radio select (yes/no) in Django

| Comments

Let’s suppose that we have a field is_active in our model. It is a boolean field, but in a template we want to show it as a radio select.

In this case we just need to add choices attribute for the model field and then change a widget of the corresponding form:

forms.py
1
2
3
4
5
6
class MyForm(forms.ModelForm):
    class Meta:
        model = MyModel
        widgets = {
            'is_active': forms.RadioSelect
        }
forms.py
1
2
3
4
5
6
7
8
9
10
11
12
from django.db import models

class MyModel(models.Model):
    STATE_CHOICES = (
        (True, u'Yes'),
        (False, u'No'),
    )
    is_active = models.BooleanField(
        verbose_name=u'Is it active?',
        default=False,
        choices=STATE_CHOICES,
    )

UPDATE:

For Django forms.

forms.py
1
2
3
4
5
6
7
8
from django import forms

class MyForm(forms.Form):
    is_active = forms.TypedChoiceField(
        coerce=lambda x: bool(int(x)),
        choices=((0, 'No'), (1, 'Yes')),
        widget=forms.RadioSelect
    )

How to send request to AJAX view in Django tests

| Comments

If you have a view that requires an AJAX request, in other words, checks if request.is_ajax(), here is a way you can write a unit test for this view:

¿Cómo concatenar querysets del mismo modelo en Django?

| Comments

Modo #1:

Podemos usar itertools.chain para unir dos o más querysets:

1
2
3
from itertools import chain
for item in chain(qs1, qs2, qs3):
    # ...

Modo #2:

Podemos usar el operador lógico OR:

1
2
res = qs1 | qs2 | qs3
res = res.distinct()