diff --git a/.travis.yml b/.travis.yml
index 14e57a2065..04fc23c2e8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,10 +7,7 @@ python:
- 2.7
env:
- - TEST_APP="-e back_mysql zds.tutorial"
- CFLAGS="-O0"
- - TEST_APP="-e back_mysql zds.article zds.forum zds.member zds.utils zds.gallery zds.mp zds.pages"
- CFLAGS="-O0"
+ - TEST_APP="-e back_mysql"
- TEST_APP="-e front"
notifications:
@@ -25,6 +22,13 @@ cache:
- apt
before_script:
+ # configure mysql
+ - mysql -e "SET GLOBAL sql_mode = 'NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES'" # Travis default
+ # try to avoid mysql has gone away errors
+ - mysql -e "SET GLOBAL wait_timeout = 36000;"
+ - mysql -e "SET GLOBAL max_allowed_packet = 134209536;"
+ - mysql -e "SHOW VARIABLES LIKE 'max_allowed_packet';"
+ - mysql -e "SHOW VARIABLES LIKE 'wait_timeout';"
# database services
- mysql -e 'create database zds_test;'
- sudo mv zds/settings_test.py zds/settings_prod.py
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 517b862a71..cddb208324 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -17,12 +17,12 @@ Les contributions externes sont les bienvenues !
4. Assurez-vous que l'intégralité des tests passent : `python manage.py test`
5. Assurez-vous que le code suit la [PEP-8](http://legacy.python.org/dev/peps/pep-0008/) : `tox -e flake8`
6. Si vous avez fait des modifications du _front_, jouez les tests associés : `npm test`
-7. Si vous modifiez le modèle (les fichiers models.py), n'oubliez pas de créer les fichiers de migration : `python manage.py schemamigration app_name --auto`
+7. Si vous modifiez le modèle (les fichiers models.py), n'oubliez pas de créer les fichiers de migration : `python manage.py makemigrations`
8. Si votre travail nécessite des actions spécifiques lors du déploiement, précisez-les dans le fichier [update.md](update.md).
9. Poussez votre travail et faites une _pull request_
# Quelques bonnes pratiques
-* Respectez [les conventions de code de Django](https://docs.djangoproject.com/en/1.6/internals/contributing/writing-code/coding-style/), ce qui inclut la [PEP 8 de Python](http://legacy.python.org/dev/peps/pep-0008/)
+* Respectez [les conventions de code de Django](https://docs.djangoproject.com/en/1.7/internals/contributing/writing-code/coding-style/), ce qui inclut la [PEP 8 de Python](http://legacy.python.org/dev/peps/pep-0008/)
* Le code et les commentaires sont en anglais
* Le _workflow_ Git utilisé est le [Git flow](http://nvie.com/posts/a-successful-git-branching-model/). En détail :
* Les arrivées fonctionnalités et corrections de gros bugs hors release se font via des PR.
@@ -42,11 +42,11 @@ Tous les détails sur le workflow se trouvent [sur la page dédiée](http://zds-
* Lors de l'ouverture d'une PR, respectez le template suivant :
```markdown
- | Q | R
- | ------------------------- | -------------------------------------------
- | Correction de bugs ? | [oui|non]
- | Nouvelle Fonctionnalité ? | [oui|non]
- | Tickets (_issues_) concernés | [Liste de tickets séparés par des virgules]
+ | Q | R
+ | ----------------------------- | -------------------------------------------
+ | Correction de bugs ? | [oui|non]
+ | Nouvelle Fonctionnalité ? | [oui|non]
+ | Tickets (_issues_) concernés | [Liste de tickets séparés par des virgules]
```
* Ajoutez des notes de QA (Quality Assurance). Ces notes doivent permettent à un testeur de comprendre ce que vous avez modifié, ce qu'il faut tester en priorité et les pièges auxquels il doit s'attendre et donc sur lesquels porter une attention particulière. Précisez tout particulièrement s'il est nécessaire d'effectuer une action de gestion préalable, comme `python manage.py migrate`, `python manage.py loaddata fixture/*.yaml` ou `npm run gulp -- build`.
diff --git a/README.md b/README.md
index 5588349e1a..dca1b60393 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@
# Zeste de Savoir
-Site internet communautaire codé à l'aide du framework [Django](https://www.djangoproject.com/) 1.6 et de [Python](https://www.python.org/) 2.7.
+Site internet communautaire codé à l'aide du framework [Django](https://www.djangoproject.com/) 1.7 et de [Python](https://www.python.org/) 2.7.
[Voir l'instance en ligne](https://zestedesavoir.com).
diff --git a/doc/source/back-end-code.rst b/doc/source/back-end-code.rst
new file mode 100644
index 0000000000..ea499e8eac
--- /dev/null
+++ b/doc/source/back-end-code.rst
@@ -0,0 +1,13 @@
+=====================================
+Documentation technique du *back-end*
+=====================================
+
+Cette documentation est générée à partir des commentaires laissés dans le `code source de Zeste de Savoir `__ au format *docstring*, et qui sont, pour des raisons d'internationalisation, rédigés en anglais.
+
+Vous pouvez également retrouver la `documentation fonctionnelle des modules ici `__.
+
+.. toctree::
+ :maxdepth: 2
+ :glob:
+
+ back-end-code/*
\ No newline at end of file
diff --git a/doc/source/back-end-code/arborescence-back.rst b/doc/source/back-end-code/arborescence-back.rst
new file mode 100644
index 0000000000..bc2b1e567e
--- /dev/null
+++ b/doc/source/back-end-code/arborescence-back.rst
@@ -0,0 +1,123 @@
+==========================
+Arborescence du *back-end*
+==========================
+
+Le *back-end* est divisé en différents modules qui assurent chacun une tâche du site. Ceux-ci sont intégralement localisés dans le dossier ``zds/``.
+
+Arborescence générale de ``zds/``
+=================================
+
+On retrouve un dossier pour chaque module du site :
+
+.. sourcecode:: bash
+
+ zds/
+ ├── article/ # module des articles
+ │ └── ...
+ ├── forum/ # module des forums
+ │ └── ...
+ ├── gallery/ # module des galleries
+ │ └── ...
+ ├── member/ # module des membres
+ │ └── ...
+ ├── mp/ # module des messages privés
+ │ └── ...
+ ├── munin/ # module de Munin, utilisé pour le monitoring
+ │ └── ...
+ ├── pages/ # module pour les autres pages, telles que la page d'accueil, ...
+ │ └── ...
+ ├── search/ # module de recherche
+ │ └── ...
+ ├── tutorial/ # module des tutoriels
+ │ └── ...
+ ├── utils/ # fonctions utiles à chaque module
+ │ └── ...
+ ├── middlewares/ # codes provenant de sources externes
+ │ └── ...
+
+On retrouve également dans ce dossier les quelques fichiers suivants, nécessaires à la configuration et au fonctionnement de Django :
+
+.. sourcecode:: bash
+
+ zds/
+ ├── urls.py # définition générale des URLs du site, inclus celle de chacun des modules
+ ├── settings.py # paramètres du site
+ ├── settings_test.py # paramètres spécifiques aux tests
+ └── wsgi.py
+
+Contenu d'un module
+===================
+
+Chacun des modules possède dans son dossier une arborescence fort semblable, et dans laquelle il est possible de trouver:
+
+.. sourcecode:: bash
+
+ module/
+ ├── migrations/
+ │ └── ...
+ ├── api/
+ │ └── ...
+ ├── tests/
+ │ ├── tests.py
+ │ └── ...
+ ├── admin.py
+ ├── commons.py
+ ├── factories.py
+ ├── feeds.py
+ ├── forms.py
+ ├── managers.py
+ ├── models.py
+ ├── search_indexes.py
+ ├── urls.py
+ └── views.py
+
+Fichiers principaux
+-------------------
+
+Django étant basé sur une architecture de type Modèle-Vue-Template, on retrouve les modèles dans le fichier ``models.py`` et les contrôles associés à celles-ci dans ``views.py``. Ces dernières peuvent employer des classes formulaires qui sont définis dans ``forms.py``. Les URLs associées au module et permetant d'accéder aux vues sont définies dans ``urls.py``. On retrouve finalement des vues spécifiques associées aux fils RSS et Atom dans ``feeds.py``.
+
+On retrouve également des validateurs dans le fichier ``commons.py`` (voir à ce sujet `la documentation de Django `__).
+
+Tests unitaires
+---------------
+
+Une partie importante du développement est basée sur les tests unitaires : afin d'éviter qu'un dévellopement futur ne brise une fonctionnalité, une série de test associé à chaque module est écrite dans des fichiers situés dans le dossier ``tests/`` de chaque module. Cette série de test peut être lancée en utilisant la commande suivante :
+
+.. sourcecode:: bash
+
+ python manage.py test zds.module
+
+où il est nécéssaire de remplacer ``module`` par le nom du module associé. Ces tests utilisent des données de tests générées par des *factories* (usines) qui sont définies dans ``factories.py``.
+
+Gestion de la base de données
+-----------------------------
+
+Le dossier ``migrations/`` permet à Django de consigner les changements effectués à des modèles qui modifient également la structure de la base de donnée. Son contenu ne devrait pas être modifié manuelement, il l'est cependant de manière automatique lorsque la commande suivante est utilisée :
+
+.. sourcecode:: bash
+
+ python manage.py makemigrations
+
+Celle-ci doit être utilisée lorsqu'une variable d'un modèle (dans ``models.py``) est modifiée, ajoutée ou supprimée. Si tel est le cas, n'oubliez pas d'inclure le fichier résultant (de la forme ``xxxx_auto_yyy.py``) dans votre prochain *commit* !
+
+Cela permettra aux autres développeurs de répercuter les modifications en utilisant:
+
+.. sourcecode:: bash
+
+ python manage.py migrate
+
+
+API
+---
+
+Une description fonctionnelle de l'API est faite `sur la page correspondante <../api.html>`__.
+
+Les fichiers correspondants à une API du module (si elle existe) se situent dans le dossier ``api/``. Dans celui-ci, se trouvent principalement de nouvelles vues (``api/views.py``), URLs (``api/urls.py``) et tests (``api/tests.py``). On retrouve également des *serializers* dans ``api/serializers.py``, nécessaires à la création de l'API (voir à ce sujet `la documentation du REST framework (en) `__).
+
+
+Autres
+------
+
+Le fichier ``search_index.py`` est utilisé par Django pour générer les *index* de recherche pour `Solr <../install/install-solr.html>`__.
+
+Le fichier ``admin.py`` est quand à lui employé par Django pour la partie administration (accessible en local via ``/admin/``).
diff --git a/doc/source/back-end-code/article.rst b/doc/source/back-end-code/article.rst
new file mode 100644
index 0000000000..acd20ce348
--- /dev/null
+++ b/doc/source/back-end-code/article.rst
@@ -0,0 +1,19 @@
+===========================
+Les articles (``article/``)
+===========================
+
+Module situé dans ``zds/article/``.
+
+.. contents:: Fichiers documentés :
+
+Modèles (``models.py``)
+=======================
+
+.. automodule:: zds.article.models
+ :members:
+
+Vues (``views.py``)
+===================
+
+.. automodule:: zds.article.views
+ :members:
\ No newline at end of file
diff --git a/doc/source/back-end-code/forum.rst b/doc/source/back-end-code/forum.rst
new file mode 100644
index 0000000000..e1aa57beef
--- /dev/null
+++ b/doc/source/back-end-code/forum.rst
@@ -0,0 +1,20 @@
+=======================
+Les forums (``forum/``)
+=======================
+
+Module situé dans ``zds/forum/``.
+
+.. contents:: Fichiers documentés :
+
+
+Modèles (``models.py``)
+=======================
+
+.. automodule:: zds.forum.models
+ :members:
+
+Vues (``views.py``)
+===================
+
+.. automodule:: zds.forum.views
+ :members:
\ No newline at end of file
diff --git a/doc/source/back-end-code/gallery.rst b/doc/source/back-end-code/gallery.rst
new file mode 100644
index 0000000000..e075f6d1fe
--- /dev/null
+++ b/doc/source/back-end-code/gallery.rst
@@ -0,0 +1,20 @@
+============================
+Les galleries (``gallery/``)
+============================
+
+Module situé dans ``zds/gallery/``.
+
+
+.. contents:: Fichiers documentés :
+
+Modèles (``models.py``)
+=======================
+
+.. automodule:: zds.gallery.models
+ :members:
+
+Vues (``views.py``)
+===================
+
+.. automodule:: zds.gallery.views
+ :members:
\ No newline at end of file
diff --git a/doc/source/back-end-code/member.rst b/doc/source/back-end-code/member.rst
new file mode 100644
index 0000000000..7c992bf729
--- /dev/null
+++ b/doc/source/back-end-code/member.rst
@@ -0,0 +1,19 @@
+=========================
+Les membres (``member/``)
+=========================
+
+Module situé dans ``zds/member/``.
+
+.. contents:: Fichiers documentés :
+
+Modèles (``models.py``)
+=======================
+
+.. automodule:: zds.member.models
+ :members:
+
+Vues (``views.py``)
+===================
+
+.. automodule:: zds.member.views
+ :members:
\ No newline at end of file
diff --git a/doc/source/back-end-code/pages.rst b/doc/source/back-end-code/pages.rst
new file mode 100644
index 0000000000..30d85eb8ba
--- /dev/null
+++ b/doc/source/back-end-code/pages.rst
@@ -0,0 +1,13 @@
+======================
+Les pages (``pages/``)
+======================
+
+Module situé dans ``zds/pages/``.
+
+.. contents:: Fichiers documentés :
+
+Vues (``views.py``)
+===================
+
+.. automodule:: zds.pages.views
+ :members:
\ No newline at end of file
diff --git a/doc/source/back-end-code/private-message.rst b/doc/source/back-end-code/private-message.rst
new file mode 100644
index 0000000000..6e48722838
--- /dev/null
+++ b/doc/source/back-end-code/private-message.rst
@@ -0,0 +1,19 @@
+=============================
+Les messages privés (``mp/``)
+=============================
+
+Module situé dans ``zds/mp/``.
+
+.. contents:: Fichiers documentés :
+
+Modèles (``models.py``)
+=======================
+
+.. automodule:: zds.mp.models
+ :members:
+
+Vues (``views.py``)
+===================
+
+.. automodule:: zds.mp.views
+ :members:
\ No newline at end of file
diff --git a/doc/source/back-end-code/tutorial.rst b/doc/source/back-end-code/tutorial.rst
new file mode 100644
index 0000000000..505775e4f8
--- /dev/null
+++ b/doc/source/back-end-code/tutorial.rst
@@ -0,0 +1,19 @@
+=============================
+Les tutoriels (``tutorial/``)
+=============================
+
+Module situé dans ``zds/tutorial/``.
+
+.. contents:: Fichiers documentés :
+
+Modèles (``models.py``)
+=======================
+
+.. automodule:: zds.tutorial.models
+ :members:
+
+Vues (``views.py``)
+===================
+
+.. automodule:: zds.tutorial.views
+ :members:
\ No newline at end of file
diff --git a/doc/source/back-end-code/utils.rst b/doc/source/back-end-code/utils.rst
new file mode 100644
index 0000000000..d65ccc4744
--- /dev/null
+++ b/doc/source/back-end-code/utils.rst
@@ -0,0 +1,59 @@
+============================
+Les utilitaires (``utils/``)
+============================
+
+Module situé dans ``zds/utils/``. Il regroupe certaines fonctions et objets utiles à tout les autres modules.
+
+.. contents:: Fichiers documentés :
+
+Modèles (``models.py``)
+=======================
+
+.. automodule:: zds.utils.models
+ :members:
+
+Articles (``articles.py``)
+==========================
+
+.. automodule:: zds.utils.articles
+ :members:
+
+Forums (``forums.py``)
+======================
+
+.. automodule:: zds.utils.forums
+ :members:
+
+Messages privés (``mps.py``)
+============================
+
+.. automodule:: zds.utils.mps
+ :members:
+
+Tutoriels (``tutorials.py``)
+============================
+
+.. automodule:: zds.utils.tutorials
+ :members:
+
+Les processeurs de contexte (``context_processor.py``)
+======================================================
+
+La doc de Django explique le principe des *context_processors* comme suit :
+
+| Un processeur de contexte possède une interface très simple : ce n’est qu’une fonction Python acceptant un paramètre, un objet HttpRequest, et renvoyant un dictionnaire qui est ensuite ajouté au contexte de gabarit. Chaque processeur de contexte doit renvoyer un dictionnaire.
+|
+| Les processeurs de contexte personnalisés peuvent se trouver n’importe où dans le code. Tout ce que Django demande, c’est que le réglage ``TEMPLATE_CONTEXT_PROCESSORS`` contienne le chemin vers le processeur personnalisé.
+|
+
+(pour plus de détails, `voir la documenation de Django à ce sujet `__)
+
+.. automodule:: zds.utils.context_processor
+ :members:
+
+Autres (``misc.py``)
+====================
+
+.. automodule:: zds.utils.misc
+ :members:
+
diff --git a/doc/source/back-end.rst b/doc/source/back-end.rst
new file mode 100644
index 0000000000..b1c5b7d3b7
--- /dev/null
+++ b/doc/source/back-end.rst
@@ -0,0 +1,13 @@
+=============
+Le *back-end*
+=============
+
+Le terme *back-end* désigne la partie du code associée à Django et écrite en python. Le but du *back-end* est de récupérer, générer et combiner les différentes données du site afin de les envoyer au `font-end `__.
+
+Vous trouverez dans les liens ci-dessous une documentation spécifique à chacun d'entre eux. Vous pouvez également retrouver la `documentation technique des modules ici `__.
+
+.. toctree::
+ :maxdepth: 2
+ :glob:
+
+ back-end/*
\ No newline at end of file
diff --git a/doc/source/article.rst b/doc/source/back-end/article.rst
similarity index 100%
rename from doc/source/article.rst
rename to doc/source/back-end/article.rst
diff --git a/doc/source/forum.rst b/doc/source/back-end/forum.rst
similarity index 93%
rename from doc/source/forum.rst
rename to doc/source/back-end/forum.rst
index 2fd1ec45c5..9ca0877c3f 100644
--- a/doc/source/forum.rst
+++ b/doc/source/back-end/forum.rst
@@ -18,24 +18,24 @@ La modération des sujets
Tout d'abord, il y a une posibilité de faire de la modération par sujet. Ici, cette modération s'effectue grâce aux liens se trouvant dans *sidebar* (zone se trouvant sur le côté gauche de la page).
- .. figure:: images/forum/modo_forum_sujet.png
+ .. figure:: ../images/forum/modo_forum_sujet.png
:align: center
Nous retrouvons ici, trois items :
- **Fermer le sujet** : ici, le but est de fermer le sujet. Ce qui empêchera quiconque de poster dedans. Un cadena, apparaîtra aussi à côté du sujet sur la liste des sujets de la catégorie, et, l'encart suivant fera alors son apparition sur le sujet en lui-même :
- .. figure:: images/forum/sujet_ferme.png
+ .. figure:: ../images/forum/sujet_ferme.png
:align: center
- **Marquer en post-it** : le sujet sera mis en post-it sur la catégorie dans laquelle il se trouve. Ce qui fait qu'il surpassera tout les autres sujets et cela, même si une réponse plus récente vient d'être posté dans un autre sujet. Il ne **pourra jamais se retrouver en-dessous des autres**. Lors de la mise en post-it, une épingle apparaît à côté du sujet dans la catégorie où il se trouve.
- .. figure:: images/forum/post_it.png
+ .. figure:: ../images/forum/post_it.png
:align: center
- **Déplacer le sujet** : cet item permet de faire un déplacement de sujet, au cas-où un membre se serait trompé en postant. Cela évite qu'il ait à recréer un sujet et donc un doublon de celui-ci. Le déplacement, se fait via une modale :
- .. figure:: images/forum/deplacement.png
+ .. figure:: ../images/forum/deplacement.png
:align: center
La modération des messages
@@ -43,19 +43,19 @@ La modération des messages
Il est aussi possible d'effectuer la modération plus finement, en ciblant des messages en particulier dans des sujets. Cela se fait grâce aux différents liens qui se trouvent sur les messages :
- .. figure:: images/forum/modo_message.png
+ .. figure:: ../images/forum/modo_message.png
:align: center
Ici, les différents choses que vous pouvez faire, sont :
- **Masquer** : cela, rend la lecture du message impossible par les autres membres. Mais l'emplacement du message reste présent, comme le montre la capture ci-dessous. Vous pouvez également contaster sur cette capture, que vous avez, avec un certain rang, la possibilité de démasquer le message. Avec ce dernier, vous avez la possiblité de masquer tout les messages des forums. Mais un membre, peut masquer de lui-même, ces propres messages.
- .. figure:: images/forum/message_masque.png
+ .. figure:: ../images/forum/message_masque.png
:align: center
- **Éditer** : en cliquant ici, vous accèderez à l'interface d'édition des messages. En tant que modérateur, vous pouvez éditer tout les messages des forums, dès lors, cette encart apparaît :
- .. figure:: images/forum/edit_modo.png
+ .. figure:: ../images/forum/edit_modo.png
:align: center
- **Signaler** : cela permet d'envoyer une demande d'intervention à l'équipe modératrice du site. Ce bouton, n'est pas un résultant de votr rang, tout les membres le possèdes.
diff --git a/doc/source/gallery.rst b/doc/source/back-end/gallery.rst
similarity index 93%
rename from doc/source/gallery.rst
rename to doc/source/back-end/gallery.rst
index 421b459079..84e536f023 100644
--- a/doc/source/gallery.rst
+++ b/doc/source/back-end/gallery.rst
@@ -19,14 +19,14 @@ On peut créer une nouvelle galerie via l'url ``/galerie/nouveau/``, où il est
Il est ensuite possible d'uploader des images via le menu de gauche :
- .. figure:: images/gallery/menu-gauche.png
+ .. figure:: ../images/gallery/menu-gauche.png
:align: center
Liens permettant d'uploader des images
Via celui-ci, on peut importer des archives contenant des images (au format ZIP) ou des images seules. Dans ce dernier cas, le formulaire d'*upload* est le suivant :
- .. figure:: images/gallery/nouvelle-image.png
+ .. figure:: ../images/gallery/nouvelle-image.png
:align: center
Formulaire d'upload de nouvelles images
@@ -35,7 +35,7 @@ Comme on peut le voir, chaque image doit posséder au minimum un titre et peut p
Une fois l'image uploadée, il est possible d'effectuer différentes actions sur celle-ci sur la page spécifique à celle-ci :
- .. figure:: images/gallery/gestion-image.png
+ .. figure:: ../images/gallery/gestion-image.png
:align: center
Gestion d'une image
@@ -53,14 +53,14 @@ Les utilisateurs et leurs droits
Le créateur de la galerie possède un droit d'écriture, mais peut rajouter à tout moment des utilisateurs dans celle-ci :
- .. figure:: images/gallery/gestion-auteurs.png
+ .. figure:: ../images/gallery/gestion-auteurs.png
:align: center
Ajout d'un nouvel utilisateur
Lors d'un clic sur "Ajouter un utilisateur", une fenêtre modale s'ouvre :
- .. figure:: images/gallery/gestion-auteurs2.png
+ .. figure:: ../images/gallery/gestion-auteurs2.png
:align: center
Choix de l'utilisateur et sélection de ces droits
@@ -79,7 +79,7 @@ La suppression
Une image peut être supprimée à tout moment en la sélectionnant sur la page de la galerie et en cliquant sur le bouton suivant :
- .. figure:: images/gallery/sup-image.png
+ .. figure:: ../images/gallery/sup-image.png
:align: center
Suppression d'une ou plusieurs image(s)
@@ -88,14 +88,14 @@ Attention qu'aucune confirmation n'est demandée pour la suppression d'une image
Une galerie peut être quant à elle supprimée via la page de gestion des galeries (``/galerie/``) en cochant la case de celle-ci et en cliquant sur "supprimer les galeries sélectionnées" dans le menu de gauche :
- .. figure:: images/gallery/sup-galerie.png
+ .. figure:: ../images/gallery/sup-galerie.png
:align: center
Suppression d'une galerie
Une modale s'ouvre ensuite, demandant de confirmer le choix :
- .. figure:: images/gallery/sup-galerie2.png
+ .. figure:: ../images/gallery/sup-galerie2.png
:align: center
Confirmation
diff --git a/doc/source/member.rst b/doc/source/back-end/member.rst
similarity index 96%
rename from doc/source/member.rst
rename to doc/source/back-end/member.rst
index 84c39bf258..45ca4a737b 100644
--- a/doc/source/member.rst
+++ b/doc/source/back-end/member.rst
@@ -24,14 +24,14 @@ L'inscription se fait via l'interface utilisateur.
- Le lien de désinscription est accessible via paramètres (``/membres/parametres/profil/``) puis “Se désinscrire” dans la barre
latérale (``/membres/desinscrire/avertissement/``) :
- .. figure:: images/member/desinscription-1.png
+ .. figure:: ../images/member/desinscription-1.png
:align: center
Position du lien de désinscription dans les paramètres du membre (``/membres/parametres/profil/``)
- Le lien mène alors vers une page expliquant les conséquences de sa désinscription. Il peut alors poursuivre via un bouton en bas de celle-ci :
- .. figure:: images/member/desinscription-2.png
+ .. figure:: ../images/member/desinscription-2.png
:align: center
Bouton de confirmation
@@ -39,7 +39,7 @@ L'inscription se fait via l'interface utilisateur.
- Le clic sur le bouton rouge ouvre une boite modale qui constitue le dernier avertissement avant le déclenchement du processus de désinscription :
- .. figure:: images/member/desinscription-3.png
+ .. figure:: ../images/member/desinscription-3.png
:align: center
La dernière étape
@@ -133,14 +133,14 @@ L'interface de réinitialisation de mot de passe
Quand le membre du site oublie son mot de passe, il peut le réinitialiser. L'ancien mot de passe est supprimé et l'utilisateur peut en choisir un nouveau.
Pour cela, il se rend sur la page de réinitialisation de mot de passe (``membres/reinitialisation/``) à partir de la page de connexion.
- .. figure:: images/member/reinitialisation-mot-de-passe-1.png
+ .. figure:: ../images/member/reinitialisation-mot-de-passe-1.png
Sur cette page l'utilisateur, doit rentrer son nom d'utilisateur ou son adresse de courriel. Pour cela, il clique sur le lien pour que le formullaire apparaisse.
Quand l'utilisateur clique sur le bouton de validation, un jeton est généré aléatoirement et est stocké dans une base de données.
Un message est envoyé à l'adresse de courriel de l'utilisateur. Ce courriel contient un lien de réinitialisation. Ce lien contient un paramètre, le jeton de réinitialisation et dirige l'utilisateur vers l'adresse ``membres/new_password/``.
- .. figure:: images/member/reinitialisation-mot-de-passe-2.png
+ .. figure:: ../images/member/reinitialisation-mot-de-passe-2.png
Cette page permet de changer le mot de passe de l'utilisateur. L'utilisateur remplit le formulaire et clique sur le bouton de validation.
Si le mot de passe et le champ confirmation correspondent et que le mot de passe respecte les règles métiers, le mot de passe est changé.
diff --git a/doc/source/private-message.rst b/doc/source/back-end/private-message.rst
similarity index 90%
rename from doc/source/private-message.rst
rename to doc/source/back-end/private-message.rst
index 29c18d6bb3..36d0eda72d 100644
--- a/doc/source/private-message.rst
+++ b/doc/source/back-end/private-message.rst
@@ -9,14 +9,14 @@ ZDS fournit un module de messagerie privée qui vous permet de communiquer avec
Vous pouvez accéder au module de message privé à tout moment en cliquant sur l'icône :
- .. figure:: images/private_message/icone-mp.png
+ .. figure:: ../images//private_message/icone-mp.png
:align: center
Icône d'accès au module de message privé
Lors de l'envoi du message privé, vous avez accès à cette interface :
- .. figure:: images/private_message/interface-mp.png
+ .. figure:: ../images//private_message/interface-mp.png
:align: center
Interface de rédaction d'un message privé
@@ -33,7 +33,7 @@ Une fois le message envoyé, tous les destinataires reçoivent un mail. Aucun au
Tout participant à la discussion verra l'icône du module notifier l'arrivée d'un message privé :
- .. figure:: images/private_message/icone-mp-new.png
+ .. figure:: ../images//private_message/icone-mp-new.png
:align: center
Un nouveau message privé est arrivé
diff --git a/doc/source/tutorial.rst b/doc/source/back-end/tutorial.rst
similarity index 98%
rename from doc/source/tutorial.rst
rename to doc/source/back-end/tutorial.rst
index 8e1654879c..8456f81af9 100644
--- a/doc/source/tutorial.rst
+++ b/doc/source/back-end/tutorial.rst
@@ -176,7 +176,7 @@ Les archives zip
Si vous avez commencé a rédiger un tutoriel via l'éditeur en ligne de Zeste de Savoir, vous avez téléchargé l'archive correspondante et vous avez fait des modifications sur les fichiers en hors-ligne, et vous souhaitez maintenant importer ces modifications sur le site. Il suffit de faire une archive zip du répertoire dans lequel se trouvent les fichiers de votre tutoriel et de renseigner les deux champs relatifs à l'import d'une archive, puis de cliquer sur importer.
-.. figure:: images/tutorial/import-archive.png
+.. figure:: ../images/tutorial/import-archive.png
:align: center
.. attention::
@@ -194,7 +194,7 @@ Vous aurez aussi besoin du pack d'images (au format zip) qui sont utilisés dans
Il ne vous restera plus qu'à renseigner les champs relatifs à l'import de ``.tuto`` pour importer le vôtre.
-.. figure:: images/tutorial/import-tuto.png
+.. figure:: ../images/tutorial/import-tuto.png
:align: center
.. attention::
@@ -231,7 +231,7 @@ en bêta, en postant le lien vers la version bêta du tutoriel.
.. attention::
- Le lien de la bêta, peut être trouvé via votre profil utilisateur, vous devez recopier tout le lien avec la partie ``?version=blablabla``. Et pensez bien à modifier ce lien lorsque vous mettez à jour votre version bêta.
+ Le lien de la bêta, peut être trouvé via votre profil utilisateur, et est sous la forme ``/tutoriels/beta//``. Le lien est aussi disponible via ``/tutoriel/off///?version=sha``. Seule la première forme doit etre donnée au public.
En fait lorsqu'un tutoriel est en mode bêta, il s'agit d'une version précise qui est mise
dans ce mode. On peut continuer à mettre à jour la version brouillon pour rajouter de nouveaux chapitres
@@ -290,14 +290,14 @@ L'ensemble des tutoriels à la recherche d'aide est visible via la page "/tutori
Il est également possible **pour tout membre qui n'est pas auteur du tutoriel consulté** de signaler une erreur, en employant le bouton prévu à cet effet et situé en bas d'une page du tutoriel (il est également présent en bas d'un chapitre, s'il s'agit d'un big-tutoriel).
- .. figure:: images/tutorial/warn-typo-button.png
+ .. figure:: ../images/tutorial/warn-typo-button.png
:align: center
Bouton permentant de signaler une erreur
Ce bouton est disponible sur la version publiée ou en bêta d'un tutoriel. Cliquer sur celui-ci ouvre une boite de dialogue :
- .. figure:: images/tutorial/warn-typo-dial.png
+ .. figure:: ../images/tutorial/warn-typo-dial.png
:align: center
Boite de dialogue permetant de signaler à l'auteur une erreur qu'il aurait commise
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 84253107fc..0c1a3619b4 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -27,6 +27,9 @@
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
+sys.path.insert(0, os.path.abspath('../../')) # add modules to python search path
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'zds.settings') # Django should use OUR settings also with SPHINX
+
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
diff --git a/doc/source/front-end.rst b/doc/source/front-end.rst
new file mode 100644
index 0000000000..f70b6f17bc
--- /dev/null
+++ b/doc/source/front-end.rst
@@ -0,0 +1,19 @@
+==============
+Le *front-end*
+==============
+
+Le terme *front-end* désigne la partie du code associée à l'affichage des données issues du `back-end `__.
+
+Il s'agit donc de la partie du code définissant le design et l'affichage, mais aussi de l'ergonomie, la réactivité et l'expérience utilisateur. Sa mise en place est basée sur trois langages :
+
++ Le HTML, aidé du `langage de gabarit de Django `__ ;
++ `SASS (en) `__ pour les feuilles de style ;
++ Javascript pour les interactions.
+
+`NodeJS (en) `__, `NPM (en) `__ (gestionaire de paquet pour NodeJS) et `Gulp (en) `__ sont utilisés pour générer le code final minifié et cohérent. Le développement du *front-end* requiert donc des outils spécifiques dont l'installation `est expliquée ici `__.
+
+.. toctree::
+ :maxdepth: 2
+ :glob:
+
+ front-end/*
diff --git a/doc/source/design.rst b/doc/source/front-end/design.rst
similarity index 93%
rename from doc/source/design.rst
rename to doc/source/front-end/design.rst
index 5cdf375f79..a99e6dc50b 100644
--- a/doc/source/design.rst
+++ b/doc/source/front-end/design.rst
@@ -10,7 +10,7 @@ Le site est composé de plusieurs grandes parties.
L'en-tête
---------
-.. figure:: images/design/en-tete.png
+.. figure:: ../images/design/en-tete.png
:align: center
On peut découper l'en-tête du site en quatre.
@@ -25,7 +25,7 @@ Le menu
Le menu est composé soit d'un lien, soit d'un menu déroulant. Ces derniers contiennent des listes de liens.
-.. figure:: images/design/en-tete_menu.png
+.. figure:: ../images/design/en-tete_menu.png
:align: center
La *logbox*
@@ -37,7 +37,7 @@ La *logbox* contient trois menus déroulants :
- le deuxième affiche les notifications ;
- et le dernier contient des liens vers les zones réservées à l'utilisateur.
-.. figure:: images/design/en-tete_logbox.png
+.. figure:: ../images/design/en-tete_logbox.png
:align: center
Le fil d'ariane
@@ -53,7 +53,7 @@ La barre latérale
La barre latérale contient des listes de liens, boutons ou formulaires permettant à l'utilisateur d'effectuer des actions.
-.. figure:: images/design/barre-laterale.png
+.. figure:: ../images/design/barre-laterale.png
:align: center
Barre latérale de la page d'un profil
@@ -72,7 +72,7 @@ Le bas de page est sûrement la partie la plus simple du site. Il contient trois
- celui du milieu contient les liens vers les comptes des réseaux sociaux du site ;
- celui de droite contient des liens vers les pages annexes du site, tel que les CGUs par exemple.
-.. figure:: images/design/bas-de-page.png
+.. figure:: ../images/design/bas-de-page.png
:align: center
Le menu pour mobile
@@ -80,7 +80,7 @@ Le menu pour mobile
Le menu pour mobile est généré en javascript à partir de l'en-tête et de la barre latérale. `Le code est disponible sur Github. `_
-.. figure:: images/design/menu-mobile.png
+.. figure:: ../images/design/menu-mobile.png
:align: center
Quelques éléments propres au site
@@ -91,13 +91,13 @@ Les boîtes modales
Une boîte modale est une pseudo-fenêtre qui s'affiche au clique de certains boutons. Elle a pour but de faire confirmer un choix à l'utilisateur ou de permettre à celui-ci de remplir un formulaire.
-.. figure:: images/design/boite-modale_mp.png
+.. figure:: ../images/design/boite-modale_mp.png
:align: center
La boîte modale pour ajouter un participant à un message privé
-.. figure:: images/design/boite-modale_desinscription.png
+.. figure:: ../images/design/boite-modale_desinscription.png
:align: center
La boîte modale pour confirmer sa désinscription
@@ -107,13 +107,13 @@ La lecture zen
La lecture zen est un mode d'affichage des tutoriels et des articles permettant à l'utilisateur de se concentrer sur sa lecture. Elle cache l'en-tête et la barre latérale de la page pour ne laisser que le contenu principal. Techniquement, c'est un mélange de javascript et de (S)CSS.
-.. figure:: images/design/lecture-zen_off.png
+.. figure:: ../images/design/lecture-zen_off.png
:align: center
Un tutoriel sans lecture zen
-.. figure:: images/design/lecture-zen_on.png
+.. figure:: ../images/design/lecture-zen_on.png
:align: center
Ce même tutoriel avec lecture zen
diff --git a/doc/source/utils/templatetags.rst b/doc/source/front-end/template-tags.rst
similarity index 90%
rename from doc/source/utils/templatetags.rst
rename to doc/source/front-end/template-tags.rst
index d941513746..f5bc625ab9 100644
--- a/doc/source/utils/templatetags.rst
+++ b/doc/source/front-end/template-tags.rst
@@ -14,6 +14,8 @@ append_to_get
L'élément ``append_to_get`` permet de rajouter des paramètres à la requête ``GET`` courante. Par exemple, sur une page
``module/toto``, le code de template suivant :
+.. sourcecode:: html
+
{% load append_to_get %}
Mon lien
@@ -31,6 +33,8 @@ captureas
L'élément ``captureas`` permet de demander d'effectuer le rendu d'un bloc de template et de stocker son contenu dans
une variable. Ainsi le code suivant :
+.. sourcecode:: html
+
{% load captureas %}
{% captureas var2 %}
{% for i in 'xxxxxxxxxx' %}
@@ -51,6 +55,8 @@ format_date
Ce filtre formate une date au format ``DateTime`` destiné à être affiché sur le site :
+.. sourcecode:: html
+
{% load date %}
{{ date | format_date}}
@@ -64,11 +70,15 @@ humane_time
Formate une date au format *Nombre de seconde depuis Epoch* en un élément lisible. Ainsi :
+.. sourcecode:: html
+
{% load date %}
{{ date_epoch | humane_time}}
sera rendu :
+.. sourcecode:: html
+
01 Jan 1970, 01:00:42
Si le contenu de ``date_epoch`` etait de ``42``.
@@ -98,34 +108,43 @@ génération des fichiers PDF et EPUB des tutos :
email_obfuscator
-----------------
+================
Ces templatetags sont principalement fondés sur https://github.com/morninj/django-email-obfuscator.
obfuscate
-+++++++++
+---------
L'email va être encodé avec des caractères ASCII pour le protéger des bots :
+
+.. sourcecode:: html
+
{% load email_obfuscator %}
{{ 'your@email.com'|obfuscate }}
obfuscate_mailto
-++++++++++++++++
+----------------
Ce templatetag ajoute en plus un ``mailto``. Il prend un paramètre optionnel qui permet d'avoir un text personnalisé dans
la balise :
+.. sourcecode:: html
+
{% load email_obfuscator %}
{{ 'your@email.com'|obfuscate_mailto:"my custom text" }}
- #returns ' my custom text ' as an encoded string like
- #my custom text
+
+Ce qui donnera :
+
+.. sourcecode:: html
+
+ my custom text
obfuscate_mailto_top_subject
-++++++++++++++++++++++++++++
+----------------------------
Identique sur le fonctionnement à ``obfuscate_mailto``, ce templatetag ajoute en plus un sujet (qui remplace le champ
pouvant être inséré entre les balises ```` et `` ``) ainsi que ``target="_top"``.
@@ -134,11 +153,8 @@ Il est utilisé sur la page « Contact ».
Exemple :
+.. sourcecode:: html
+
{% load email_obfuscator %}
{{ 'association@zestedesavoir.com'|obfuscate_mailto_top_subject:"Contact communication" }}
-
-autres
-======
-
-**TODO**
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 66d2907bb9..da772c16b5 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -2,7 +2,7 @@
Documentation de Zeste De Savoir
================================
-Zeste de Savoir est un site internet communautaire codé à l'aide du framework Django 1.6 et de Python 2.7
+Zeste de Savoir est un site internet communautaire codé à l'aide du framework Django 1.7 et de Python 2.7
`Voir l'instance en ligne `_
@@ -16,12 +16,8 @@ Sommaire
install
workflow
- tutorial
- member
- private-message
- forum
- gallery
- article
+ back-end
+ back-end-code
+ front-end
api
utils
- design
diff --git a/doc/source/install/backend-linux-install.rst b/doc/source/install/backend-linux-install.rst
index 4faef2f092..83ba09562e 100644
--- a/doc/source/install/backend-linux-install.rst
+++ b/doc/source/install/backend-linux-install.rst
@@ -5,7 +5,7 @@ Installation du backend sous Linux
Pour installer une version locale de ZdS sur GNU/Linux, veuillez suivre les instructions suivantes.
Si une commande ne passe pas, essayez de savoir pourquoi avant de continuer.
-Les commandes suivantes sont génériques et indépendantes de la distribution que vous utilisez.
+Certaines des commandes d'installation (débutant par ``apt-get``) sont données ici pour Debian et ses dérivés, pour lesquels il est sûr qu'elles fonctionnent. Néanmoins, si vous utilisez une distribution différente, le nom des paquets à installer devrait être fort semblable, n'hésitez dès lors pas à employer la fonction "recherche" de votre gestionnaire de paquet préféré. Les autres commandes sont génériques et indépendantes de la distribution utilisée.
**NB** : il est impératif que la locale fr_FR.UTF-8 soit installée sur votre distribution.
@@ -17,6 +17,8 @@ Assurez vous que les dépendances suivantes soient résolues :
- easy_install : ``apt-get install python-setuptools``
- pip : ``easy_install pip``
- tox : ``pip install tox``
+- geoip : ``apt-get install geoip`` (peut s'appeler ``geoip-bin`` sur certaines distributions telles que Debian)
+- libgeoip-dev : ``apt-get install libgeoip-dev``
- libxml2-dev : ``apt-get install libxml2-dev``
- python-lxml : ``apt-get install python-lxml``
- libxlst-dev (peut être appelée libxlst1-dev sur certains OS comme ubuntu
@@ -28,7 +30,7 @@ Ou, en une ligne,
.. sourcecode:: bash
- apt-get install git python-dev python-setuptools libxml2-dev python-lxml libxslt-dev libz-dev python-sqlparse libjpeg8 libjpeg8-dev libfreetype6 libfreetype6-dev
+ apt-get install git python-dev python-setuptools '^geoip(-bin)?$' libgeoip-dev libxml2-dev python-lxml libxslt-dev libz-dev python-sqlparse libjpeg8 libjpeg8-dev libfreetype6 libfreetype6-dev
easy_install pip tox
Installation et configuration de `virtualenv`
@@ -66,7 +68,6 @@ Une fois dans votre environnement python (``source ../bin/activate`` si vous uti
.. sourcecode:: bash
pip install --upgrade -r requirements.txt -r requirements-dev.txt
- python manage.py syncdb
python manage.py migrate
python manage.py runserver
@@ -86,7 +87,4 @@ Ce qui revient à lancer les commmandes suivantes :
cabal update
cabal install pandoc
-Ajouter un hook de pre-commit a git pour tester flake
------------------------------------------------------
-
-.. include:: includes/git-pre-hook.rst
+Vous pouvez également `indiquer à Git de ne pas effectuer de commit s'il y a des erreurs de formatage dans le code <../utils/git-pre-hook.html>`__.
diff --git a/doc/source/install/backend-os-x-install.rst b/doc/source/install/backend-os-x-install.rst
index 92d129a79e..e184a3f4b9 100644
--- a/doc/source/install/backend-os-x-install.rst
+++ b/doc/source/install/backend-os-x-install.rst
@@ -13,6 +13,7 @@ Avant de vous lancez dans l'installation de l'environnement de zds, il faut quel
- Installer pip
- Installer git
- Installer `gettext `_
+- Installer GeoIP (``brew install geoip``)
Une fois les pré-requis terminés, vous pouvez vous lancer dans l'installaton de l'environnement de zds.
@@ -88,7 +89,5 @@ Pour faire fonctionner ZdS dans son ensemble vous devez installer les outils Lat
sudo port install pandoc
-Ajouter un hook de pre-commit a git pour tester flake
------------------------------------------------------
-.. include:: includes/git-pre-hook.rst
+Vous pouvez également `indiquer à Git de ne pas effectuer de commit s'il y a des erreurs de formatage dans le code `__.
diff --git a/doc/source/install/backend-windows-install.rst b/doc/source/install/backend-windows-install.rst
index 170557ab7b..b775f875b7 100644
--- a/doc/source/install/backend-windows-install.rst
+++ b/doc/source/install/backend-windows-install.rst
@@ -39,7 +39,6 @@ Suite de l'installation
- Dans la console PowerShell via l'environnement zdsenv installez les dépendances.
- ``easy_install lxml``
- ``pip install -r requirements.txt -r requirements-dev.txt``
- - ``python manage.py syncdb``
- ``python manage.py migrate``
- ``python manage.py runserver``
- Pour redémarrer virtualenv les fois suivantes : ``~\.virtualenvs\zdsenv\Scripts\activate.ps1``
diff --git a/doc/source/install/frontend-install.rst b/doc/source/install/frontend-install.rst
index 77cec91f20..497427c258 100644
--- a/doc/source/install/frontend-install.rst
+++ b/doc/source/install/frontend-install.rst
@@ -135,7 +135,7 @@ Gulp est un outil permettant d'automatiser les tâches liées au front. Dans not
.. note::
Vous voulez en savoir plus ?
- Venez `ici <../design.html>`_ ! ;)
+ Venez `ici <../front-end/design.html>`_ ! ;)
Utilisation de Gulp
-------------------
diff --git a/doc/source/utils.rst b/doc/source/utils.rst
index c25fcbea81..44f831b287 100644
--- a/doc/source/utils.rst
+++ b/doc/source/utils.rst
@@ -2,7 +2,7 @@
Autres outils
=============
-Le package ``zds/utils`` contient un certains nombres d'outils transverses.
+Vous retrouverez ici quelques éléments utiles.
.. toctree::
:maxdepth: 2
diff --git a/doc/source/utils/context-processors.rst b/doc/source/utils/context-processors.rst
deleted file mode 100644
index 2b05ac70e2..0000000000
--- a/doc/source/utils/context-processors.rst
+++ /dev/null
@@ -1,19 +0,0 @@
-================================================
-Les context_processors (processeurs de contexte)
-================================================
-
-La doc de Django explique le principe des context_processors comme ceci :
-
- Un processeur de contexte possède une interface très simple : ce n’est qu’une fonction Python acceptant un paramètre, un objet HttpRequest, et renvoyant un dictionnaire qui est ensuite ajouté au contexte de gabarit. Chaque processeur de contexte doit renvoyer un dictionnaire.
-
- Les processeurs de contexte personnalisés peuvent se trouver n’importe où dans le code. Tout ce que Django demande, c’est que le réglage TEMPLATE_CONTEXT_PROCESSORS contienne le chemin vers le processeur personnalisé.
-
-git_version
-===========
-
-``git_version`` permet d'ajouter les informations sur la branche et le commit de la version actuelle.
-
-app_settings
-============
-
-``app_settings`` permet d'accéder aux variables de ``ZDS_APP`` qui se trouve dans ``settings.py``.
diff --git a/doc/source/install/includes/git-pre-hook.rst b/doc/source/utils/git-pre-hook.rst
similarity index 86%
rename from doc/source/install/includes/git-pre-hook.rst
rename to doc/source/utils/git-pre-hook.rst
index 2ecc0efb0d..6674e553fe 100644
--- a/doc/source/install/includes/git-pre-hook.rst
+++ b/doc/source/utils/git-pre-hook.rst
@@ -1,3 +1,7 @@
+===================================================
+Détection automatique des erreurs *flake8* avec Git
+===================================================
+
Afin de s'assurer qu'aucune erreur de mise en forme ne passe les commits,
il peut être utile de rajouter un hook de pre-commit à git. Un hook est un petit
programme qui sera exécuté avant une action particulière de git. En l'occurence nous
diff --git a/geodata/GeoIP.dat b/geodata/GeoIP.dat
index 98642c7a72..bbfb95d1e6 100644
Binary files a/geodata/GeoIP.dat and b/geodata/GeoIP.dat differ
diff --git a/geodata/GeoIPASNum.dat b/geodata/GeoIPASNum.dat
new file mode 100644
index 0000000000..07585e36a4
Binary files /dev/null and b/geodata/GeoIPASNum.dat differ
diff --git a/geodata/GeoIPASNumv6.dat b/geodata/GeoIPASNumv6.dat
new file mode 100644
index 0000000000..ed9202b1f4
Binary files /dev/null and b/geodata/GeoIPASNumv6.dat differ
diff --git a/geodata/GeoIPv6.dat b/geodata/GeoIPv6.dat
index 7e543bdebc..c2f3f11bfc 100644
Binary files a/geodata/GeoIPv6.dat and b/geodata/GeoIPv6.dat differ
diff --git a/geodata/GeoLiteCity.dat b/geodata/GeoLiteCity.dat
index ab41d5d497..af176bf3a9 100644
Binary files a/geodata/GeoLiteCity.dat and b/geodata/GeoLiteCity.dat differ
diff --git a/geodata/GeoLiteCityv6.dat b/geodata/GeoLiteCityv6.dat
index 21fb871007..1309800dcd 100644
Binary files a/geodata/GeoLiteCityv6.dat and b/geodata/GeoLiteCityv6.dat differ
diff --git a/package.json b/package.json
index e443fb91a0..b6f7e7dc51 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "zds-site",
"version": "0.2.0",
- "description": "Site internet communautaire codé à l'aide du Framework Django 1.6",
+ "description": "Site internet communautaire codé à l'aide du Framework Django 1.7",
"directories": {
"doc": "doc"
},
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 1616797cd1..285f73f49c 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -1,7 +1,7 @@
PyYAML==3.11
django-debug-toolbar==1.2.2
flake8==2.3.0
-autopep8==1.0.4
+autopep8==1.1.1
sphinx==1.2.3
sphinx_rtd_theme==0.1.6
-fake-factory==0.4.2
+fake-factory==0.5.0
diff --git a/requirements.txt b/requirements.txt
index 2421b74358..a93985d886 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,30 +1,29 @@
# Implicit dependencies (optional dependencies of dependencies)
-pysolr==3.2.0
-pygments==2.0.1
-python-social-auth==0.1.26
+pysolr==3.3.0
+pygments==2.0.2
+python-social-auth==0.2.2
# Explicit dependencies (references in code)
-django==1.6.11
+django==1.7.7
coverage==3.7.1
-south==1.0.1
django-crispy-forms==1.4.0
django-haystack==2.3.1
django-model-utils==2.2
django-munin==0.1.5
python-memcached==1.53
-lxml==3.4.0
+lxml==3.4.2
factory-boy==2.4.1
pygeoip==0.3.2
pillow==2.7.0
-gitpython==0.3.5
+gitpython==0.3.6
https://github.com/zestedesavoir/Python-ZMarkdown/archive/2.6.0-zds.7.zip
easy-thumbnails==2.2
# Api dependencies
djangorestframework==3.1.1
djangorestframework-xml==1.0.1
-django-filter==0.8
+django-filter==0.9.2
django-oauth-toolkit==0.7.2
-drf-extensions==0.2.6
+drf-extensions==0.2.7
django-rest-swagger==0.2.9
django-cors-headers==1.0.0
diff --git a/robots.txt b/robots.txt
index 0119839971..d5680ad2c2 100644
--- a/robots.txt
+++ b/robots.txt
@@ -5,4 +5,5 @@ Sitemap: http://zestedesavoir.com/sitemap.xml
User-agent: *
Disallow: /mp/
Disallow: /tutoriels/off/
+Disallow: /tutoriels/beta/
Disallow: /articles/off/
diff --git a/server/deploy.sh b/server/deploy.sh
index 2c63fd9f1e..d15eb40e8e 100644
--- a/server/deploy.sh
+++ b/server/deploy.sh
@@ -18,7 +18,7 @@ if [ "$#" -ne 1 ]; then
exit 1
fi
-read -p "Did you run specific tasks for this version as described in update.md? " -r
+read -p "Did you run specific tasks for this version as described in update.md? [y/N] " -r
echo # move to a new line
if [[ ! $REPLY =~ ^[Yy]$ ]]
then
@@ -75,4 +75,4 @@ sudo service nginx reload
# Display current branch and commit
git status
-echo "Commit deployé : `git rev-parse HEAD`"
+echo "Deployed commit: `git rev-parse HEAD`"
diff --git a/setup.py b/setup.py
index 6b5c2db586..25fbc1be16 100644
--- a/setup.py
+++ b/setup.py
@@ -17,7 +17,7 @@
setup(
name='zds',
- version='1.6',
+ version='1.7',
packages=['zds'],
include_package_data=True,
license='GPLv3',
diff --git a/templates/base.html b/templates/base.html
index 14a15b77dc..b39563cd41 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -441,7 +441,7 @@
{% trans "Mes articles" %}
- {% trans "Galeries d'images" %}
+ {% trans "Galeries d'images" %}
{% trans "Paramètres" %}
diff --git a/templates/gallery/base.html b/templates/gallery/base.html
index 5ef14a1d2e..72bb92be34 100755
--- a/templates/gallery/base.html
+++ b/templates/gallery/base.html
@@ -10,19 +10,37 @@
{% block breadcrumb_base %}
- {% trans "Galeries" %}
+ {% trans "Galeries" %}
{% endblock %}
{% block sidebar %}
{% endblock %}
\ No newline at end of file
diff --git a/templates/gallery/gallery/details.html b/templates/gallery/gallery/details.html
index 92e968f553..15ebbb4e33 100644
--- a/templates/gallery/gallery/details.html
+++ b/templates/gallery/gallery/details.html
@@ -47,7 +47,7 @@
{% endfor %}
- {% if gallery_mode.is_write %}
+ {% if gallery_mode.can_write %}
{% trans "Ajouter un utilisateur" %}
@@ -58,12 +58,12 @@
-
{% endblock %}
-
-
-{% block sidebar %}
- {% if gallery_mode.is_write %}
-
{% endif %}
{% endblock %}
diff --git a/templates/gallery/gallery/edit.html b/templates/gallery/gallery/edit.html
new file mode 100644
index 0000000000..a6f4309c30
--- /dev/null
+++ b/templates/gallery/gallery/edit.html
@@ -0,0 +1,28 @@
+{% extends "gallery/base.html" %}
+{% load crispy_forms_tags %}
+{% load i18n %}
+
+
+
+{% block title %}
+ {{ gallery.title }}
+{% endblock %}
+
+
+
+{% block breadcrumb %}
+ {{ gallery.title }}
+ {% trans "Éditer" %}
+{% endblock %}
+
+
+
+{% block headline %}
+ {{ gallery.title }}
+{% endblock %}
+
+
+
+{% block content %}
+ {% crispy form %}
+{% endblock %}
\ No newline at end of file
diff --git a/templates/gallery/gallery/list.html b/templates/gallery/gallery/list.html
index 26aa662a5a..0153539955 100755
--- a/templates/gallery/gallery/list.html
+++ b/templates/gallery/gallery/list.html
@@ -28,7 +28,7 @@
{% trans "Vous n'avez pas encore de galerie" %}.
- {% trans "Créer une galerie" %} .
+ {% trans "Créer une galerie" %} .
{% endif %}
{% endblock %}
diff --git a/templates/gallery/gallery/new.html b/templates/gallery/gallery/new.html
index 2fb7411012..b5dc85b9cb 100644
--- a/templates/gallery/gallery/new.html
+++ b/templates/gallery/gallery/new.html
@@ -23,5 +23,5 @@
{% block content %}
- {% crispy form %}
+ {% crispy form %}
{% endblock %}
diff --git a/templates/gallery/image/edit.html b/templates/gallery/image/edit.html
index 397e1a6a24..6eb7fe30fe 100644
--- a/templates/gallery/image/edit.html
+++ b/templates/gallery/image/edit.html
@@ -38,7 +38,7 @@
- {% if gallery_mode.is_write %}
+ {% if gallery_mode.can_write %}
{% crispy form %}
{% endif %}
@@ -59,25 +59,3 @@
{% crispy as_avatar_form %}
{% endblock %}
-
-
-
-{% block sidebar_actions %}
- {% if gallery_mode.is_write %}
-
- {% endif %}
-{% endblock %}
diff --git a/templates/gallery/image/import.html b/templates/gallery/image/import.html
new file mode 100644
index 0000000000..d1807f3cc7
--- /dev/null
+++ b/templates/gallery/image/import.html
@@ -0,0 +1,28 @@
+{% extends "gallery/base.html" %}
+{% load crispy_forms_tags %}
+{% load i18n %}
+
+
+
+{% block title %}
+ {% trans "Importer une archive" %}
+{% endblock %}
+
+
+
+{% block breadcrumb %}
+
+ {% trans "Données GeoLite créées par MaxMind, disponibles sous licence CC-BY-SA 3.0 unported" %}.
+
+
diff --git a/templates/pages/association.html b/templates/pages/association.html
index 0b315cbe33..eef4d82e8b 100644
--- a/templates/pages/association.html
+++ b/templates/pages/association.html
@@ -50,7 +50,7 @@
{% trans "L'association et le site" %}
{% endblocktrans %}
- {% trans "De même, toutes les fonctionnalités du site sont disponibles à tous : aucune n'est conditionné à l'adhésion à l'association" %}.
+ {% trans "De même, toutes les fonctionnalités du site sont disponibles à tous : aucune n'est conditionnée à l'adhésion à l'association" %}.
{% trans "Notez que vous devez être inscrit pour pouvoir adhérer" %}.
diff --git a/templates/pages/cookies.html b/templates/pages/cookies.html
index afaad5ec55..f2806880b4 100644
--- a/templates/pages/cookies.html
+++ b/templates/pages/cookies.html
@@ -110,30 +110,31 @@
{% trans "Licence de cette page" %}
{% trans "Une recette de cookies" %}
{% trans "Puisque vous avez réussi à trouver cette page et que vous avez eu le courage de lire jusqu'ici, vous avez bien droit à une récompense : une recette de cookies" %} !
{% trans "Ingrédients" %}
-
{% trans "Pour 30 cookies environ (parce que c'est bon, on va en faire plein" %} !) :
+
{% trans "Pour beaucoup de cookies (parce que le nombre dépend de leur taille) :" %}
{% trans "500 g de farine" %}
- {% trans "250 g de beurre" %}
- {% trans "300 g de chocolat à pâtisser" %}
+ {% trans "500 g de chocolat à pâtisser" %}
+ {% trans "250 g de beurre à température ambiante" %}
{% trans "200 g de cassonade, ou à défaut de sucre roux" %}
- {% trans "2œufs" %}
- {% trans "2 sachets de sucre vanillé" %}
+ {% trans "2 œufs" %}
+ {% trans "2 cuillers à café de vanille liquide ou à défaut 2 sachets de sucre vanillé" %}
{% trans "1 pincée de sel" %}
{% trans "1 sachet de levure" %}
-
{% trans "Préparation : 10 minutes" %}
-
{% trans "Cuisson : 10 minutes" %}
+
{% trans "Préparation : 10 minutes + 15 minutes pour couper le chocolat" %}
+
{% blocktrans %}Cuisson : 10 minutes par fournée {% endblocktrans %}
{% trans "Préparation" %}
-
{% trans "Avec un grand couteau bien aiguisé, découpez le chocolat en petits morceaux" %}.
-
{% trans "Dans un grand saladier, mélangez la farine, la cassonade, le sucre vanillé, la levure et le sel" %}.
-
{% trans "Faites fondre le beurre, ajoutez-y les œufs. Incorporez le tout à la préparation" %}.
+
{% trans "Avec un grand couteau solide et bien aiguisé, découpez le chocolat en petits morceaux" %}.
+
{% trans "Mélangez en crème le beurre ramolli et le sucre. Incorporez les œufs et la vanille liquide (ou le sucre vanillé)." %}
+
{% trans "Ajoutez la farine et la levure. Mélangez bien." %}
{% trans "Ajoutez les morceaux de chocolat et mélangez avec soin" %}.
{% trans "Cuisson" %}
-
{% trans "Préchauffez votre four à 220°C (200°C en chaleur tournante) / thermostat 7-8, grille en position basse" %}.
-
{% trans "Façonnez des cookies d'environ 10 cm de côté sur la plaque recouverte de papier sulfurisé. Attention, espacez-les parce qu'ils s'étalent à la cuisson" %}.
+
{% trans "Préchauffez votre four à 200°C / thermostat 6-7 (un peu moins si vous utilisez la chaleur tournante), grille en position basse" %}.
+
{% trans "Façonnez des cookies pas trop épais par petite cuillerées sur une plaque de cuisson recouverte de papier sulfurisé. Espacez-les parce qu'ils s'étalent à la cuisson." %}
{% trans "Enfournez-les environ 10 minutes, ils sont cuits lorsqu'ils prennent une belle couleur dorée" %} !
{% trans "Conseils divers" %}
{% trans "Si vous avez la flemme de découper le chocolat, vous pouvez utiliser des pépites de chocolat mais en général c'est moins bon. Surtout pas de chocolat à déguster : ces chocolats manquent de sucre pour la patisserie" %} !
-
{% trans "La cuisson parfaite se joue à quelques secondes près (sérieusement), alors surveillez-les bien ! Un SMS de trop, et vous obtenez des cookies en béton. Ce qui serait dommage" %} !
-
{% blocktrans %} On peut faire des cookies à beaucoup de parfums, mais le must reste le cookie au chocolat". Bien qu'avec un peu de noix de coco ça ne se refuse pas !{% endblocktrans %}
+
{% trans "Pour découper le chocolat, vous aurez besoin d'un grand couteau solide (donc pas un couteau céramique) et très bien aiguisé. Non, le vôtre n'est pas assez aiguisé. Attaquez la plaque de chocolat côté lisse (carrés sur le dessous), c'est plus simple." %}
+
{% trans "La cuisson parfaite se joue à quelques secondes près (sérieusement), alors surveillez-les bien ! Un SMS de trop, et vous obtenez des cookies en béton. Ce qui serait dommage. Les cookies sont assez mous en sortie de four, c'est normal : ils durcissent en refroidissant." %} !
+
{% blocktrans %} On peut faire des cookies à beaucoup de parfums, mais le must reste le cookie au chocolat{% endblocktrans %}.
{% endblock %}
diff --git a/templates/tutorial/base.html b/templates/tutorial/base.html
index 7993a5432b..4f94369ce0 100644
--- a/templates/tutorial/base.html
+++ b/templates/tutorial/base.html
@@ -53,13 +53,14 @@
{% trans "Actions" %}
{% endif %}
{% block sidebar_blocks %}{% endblock %}
+
{% if tutorial %}
- {% if tutorial.on_line or tutorial.in_beta and user in tutorial.authors.all or perms.tutorial.change_tutorial %}
+ {% if tutorial.on_line or user in tutorial.authors.all or perms.tutorial.change_tutorial %}
{% endif %}
- {% include "tutorial/includes/summary.part.html" with online=True parts=tutorial.parts %}
+ {% include "tutorial/includes/summary.part.html" with online=True tutorial=tutorial parts=tutorial.parts %}
{% include "misc/social_buttons.part.html" with link=part.tutorial.get_absolute_url_online text=part.tutorial.title %}
{% endblock %}
diff --git a/update.md b/update.md
index b0c0abe013..b8a7d9f554 100644
--- a/update.md
+++ b/update.md
@@ -120,7 +120,6 @@ Lancer la commande `npm -v` et voir le résultat. Si le résultat est 1.x.x, lan
Faire pointer nginx sur `static/` au lieu de `dist/`.
-
Actions à faire pour mettre en prod la version : v1.6
=====================================================
@@ -143,10 +142,74 @@ Issue #2058
Rajouter ces lignes dans le `settings_prod.py` :
```python
-ZDS_SITE['site']['googleAnalyticsID'] = 'UA-27730868-1'
-ZDS_SITE['site']['googleTagManagerID'] = 'GTM-WH7642'
+ZDS_APP['site']['googleAnalyticsID'] = 'UA-27730868-1'
+ZDS_APP['site']['googleTagManagerID'] = 'GTM-WH7642'
```
-Actions à faire pour mettre en prod la version : v1.6
+
+Vérifier que `EMAIL_BACKEND` est bien définit dans le `settings_prod.py` car il a maintenant une valeur par défaut. La configuration par défaut sur la prod devrait être `EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'`.
+
+Actions à faire pour mettre en prod la version : v1.8
=====================================================
-Vérifier que `EMAIL_BACKEND` est bien définit dans le `settings_prod.py` car il a maintenant une valeur par défaut. La configuration par défaut sur la prod devrait être `EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'`.
\ No newline at end of file
+Issue #1455 Django 1.7
+----------------------
+
+**Avant** de lancer la migration de la base, prévenir Django que `easy_thumbnail` est déjà OK :
+
+
+```
+python manage.py migrate --fake easy_thumbnails
+```
+
+Le reste l'est aussi mais Django est incapable de le détecter tout seul pour cette app.
+
+**Attention** : il est possible que Django perde l'information du "migrate fake" pendant la migration et donc plante sur cette étape pendant le déploiement. Si c'est le cas, pas de panique, il suffit de releancer les migrations à la main et de redémarrer l'application :
+
+```
+cd /opt/zdsenv/ZesteDeSavoir/
+source ../bin/activate
+python manage.py migrate --fake easy_thumbnails
+python manage.py migrate
+deactivate
+sudo supervisorctl restart zds
+```
+
+Désinstaller south: `pip uninstall south`. La MAJ de Django de la 1.6 à la 1.7 sera faite par le script (via la mise à jour des _requirements_).
+
+Déploiement de Django 1.7
+-------------------------
+
+_(A priori spécifique à zestedesavoir.com, mais ça peut aider selon l'installation qui est faite du site)_
+
+1. Le fichier `unicorn_start` est inutile et peut être supprimé.
+2. La conf `gunicorn_config.py` peut être pas mal simplifiée. Fichier utilisé en **bêta**, quelques adaptations peuvent être nécessaires pour la production :
+
+```python
+command = '/opt/zdsenv/bin/gunicorn'
+pythonpath = '/opt/zdsenv/ZesteDeSavoir'
+bind = 'unix:/opt/zdsenv/bin/gunicorn.sock'
+workers = 7
+user = 'zds'
+group = 'zds'
+errorlog = '/opt/zdsenv/logs/gunicorn_error.log'
+loglevel = 'info'
+
+```
+
+3. Mettre à jour la configuration supervisor pour utiliser la bonne manière de lancer Gunicorn. Fichier utilisé en **bêta**, quelques adaptations peuvent être nécessaires pour la production :
+
+```
+[program:zds]
+directory = /opt/zdsenv/
+command = /opt/zdsenv/bin/gunicorn -c /opt/zdsenv/gunicorn_config.py zds.wsgi
+stdout_logfile = /opt/zdsenv/logs/supervisor_stdout.log
+stderr_logfile = /opt/zdsenv/logs/supervisor_stderr.log
+
+```
+
+4. Redémarrer Supervisor pour prendre en compte les modifications : `sudo service supervisor restart`
+
+Issue #2520
+-----------
+
+Vérifier que le paquet `libgoip-dev`, devenu nécessaire pour employer GeoIP, est installé : `sudo apt-get install libgeoip-dev`
diff --git a/zds/article/factories.py b/zds/article/factories.py
index 600874e8b4..91cc874cca 100644
--- a/zds/article/factories.py
+++ b/zds/article/factories.py
@@ -16,9 +16,8 @@
class ArticleFactory(factory.DjangoModelFactory):
FACTORY_FOR = Article
- title = factory.Sequence(lambda n: 'Mon Article No{0}'.format(n))
- description = factory.Sequence(
- lambda n: 'Description de l\'article No{0}'.format(n))
+ title = factory.Sequence('Mon Article No{0}'.format)
+ description = factory.Sequence('Description de l\'article No{0}'.format)
text = 'text.md'
create_at = datetime.now()
@@ -95,6 +94,6 @@ def _prepare(cls, create, **kwargs):
class SubCategoryFactory(factory.DjangoModelFactory):
FACTORY_FOR = SubCategory
- title = factory.Sequence(lambda n: 'Sous-Categorie {0} pour l\'article'.format(n))
- subtitle = factory.Sequence(lambda n: 'Sous titre de Sous-Categorie {0} pour l\'article'.format(n))
- slug = factory.Sequence(lambda n: 'sous-categorie-{0}'.format(n))
+ title = factory.Sequence('Sous-Categorie {0} pour l\'article'.format)
+ subtitle = factory.Sequence('Sous titre de Sous-Categorie {0} pour l\'article'.format)
+ slug = factory.Sequence('sous-categorie-{0}'.format)
diff --git a/zds/article/migrations/0001_initial.py b/zds/article/migrations/0001_initial.py
index 58a98dd36d..288ac60035 100644
--- a/zds/article/migrations/0001_initial.py
+++ b/zds/article/migrations/0001_initial.py
@@ -1,316 +1,116 @@
# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding model 'Article'
- db.create_table(
- u'article_article', ((u'id', self.gf('django.db.models.fields.AutoField')(
- primary_key=True)), ('title', self.gf('django.db.models.fields.CharField')(
- max_length=80)), ('description', self.gf('django.db.models.fields.CharField')(
- max_length=200)), ('slug', self.gf('django.db.models.fields.SlugField')(
- max_length=80)), ('create_at', self.gf('django.db.models.fields.DateTimeField')()), ('pubdate', self.gf('django.db.models.fields.DateTimeField')(
- null=True, blank=True)), ('update', self.gf('django.db.models.fields.DateTimeField')(
- null=True, blank=True)), ('image', self.gf('django.db.models.fields.files.ImageField')(
- max_length=100, null=True, blank=True)), ('thumbnail', self.gf('django.db.models.fields.files.ImageField')(
- max_length=100, null=True, blank=True)), ('is_visible', self.gf('django.db.models.fields.BooleanField')(
- default=False)), ('sha_public', self.gf('django.db.models.fields.CharField')(
- max_length=80, null=True, blank=True)), ('sha_validation', self.gf('django.db.models.fields.CharField')(
- max_length=80, null=True, blank=True)), ('sha_draft', self.gf('django.db.models.fields.CharField')(
- max_length=80, null=True, blank=True)), ('text', self.gf('django.db.models.fields.CharField')(
- max_length=200, null=True, blank=True)), ('last_reaction', self.gf('django.db.models.fields.related.ForeignKey')(
- blank=True, related_name='last_reaction', null=True, to=orm['article.Reaction'])), ('is_locked', self.gf('django.db.models.fields.BooleanField')(
- default=False)), ))
- db.send_create_signal(u'article', ['Article'])
-
- # Adding M2M table for field authors on 'Article'
- m2m_table_name = db.shorten_name(u'article_article_authors')
- db.create_table(
- m2m_table_name, (('id', models.AutoField(
- verbose_name='ID', primary_key=True, auto_created=True)), ('article', models.ForeignKey(
- orm[u'article.article'], null=False)), ('user', models.ForeignKey(
- orm[u'auth.user'], null=False))))
- db.create_unique(m2m_table_name, ['article_id', 'user_id'])
-
- # Adding M2M table for field subcategory on 'Article'
- m2m_table_name = db.shorten_name(u'article_article_subcategory')
- db.create_table(
- m2m_table_name, (('id', models.AutoField(
- verbose_name='ID', primary_key=True, auto_created=True)), ('article', models.ForeignKey(
- orm[u'article.article'], null=False)), ('subcategory', models.ForeignKey(
- orm[u'utils.subcategory'], null=False))))
- db.create_unique(m2m_table_name, ['article_id', 'subcategory_id'])
-
- # Adding model 'Reaction'
- db.create_table(
- u'article_reaction',
- ((u'comment_ptr',
- self.gf('django.db.models.fields.related.OneToOneField')(
- to=orm['utils.Comment'],
- unique=True,
- primary_key=True)),
- ('article',
- self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['article.Article'])),
- ))
- db.send_create_signal(u'article', ['Reaction'])
-
- # Adding model 'ArticleRead'
- db.create_table(
- u'article_articleread', ((u'id', self.gf('django.db.models.fields.AutoField')(
- primary_key=True)), ('article', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['article.Article'])), ('reaction', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['article.Reaction'])), ('user', self.gf('django.db.models.fields.related.ForeignKey')(
- related_name='reactions_read', to=orm['auth.User'])), ))
- db.send_create_signal(u'article', ['ArticleRead'])
-
- # Adding model 'Validation'
- db.create_table(
- u'article_validation',
- ((u'id',
- self.gf('django.db.models.fields.AutoField')(
- primary_key=True)),
- ('article',
- self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['article.Article'],
- null=True,
- blank=True)),
- ('version',
- self.gf('django.db.models.fields.CharField')(
- max_length=80,
- null=True,
- blank=True)),
- ('date_proposition',
- self.gf('django.db.models.fields.DateTimeField')()),
- ('comment_authors',
- self.gf('django.db.models.fields.TextField')()),
- ('validator',
- self.gf('django.db.models.fields.related.ForeignKey')(
- blank=True,
- related_name='articles_author_validations',
- null=True,
- to=orm['auth.User'])),
- ('date_reserve',
- self.gf('django.db.models.fields.DateTimeField')(
- null=True,
- blank=True)),
- ('date_validation',
- self.gf('django.db.models.fields.DateTimeField')(
- null=True,
- blank=True)),
- ('comment_validator',
- self.gf('django.db.models.fields.TextField')(
- null=True,
- blank=True)),
- ('status',
- self.gf('django.db.models.fields.CharField')(
- default='PENDING',
- max_length=10)),
- ))
- db.send_create_signal(u'article', ['Validation'])
-
- def backwards(self, orm):
- # Deleting model 'Article'
- db.delete_table(u'article_article')
-
- # Removing M2M table for field authors on 'Article'
- db.delete_table(db.shorten_name(u'article_article_authors'))
-
- # Removing M2M table for field subcategory on 'Article'
- db.delete_table(db.shorten_name(u'article_article_subcategory'))
-
- # Deleting model 'Reaction'
- db.delete_table(u'article_reaction')
-
- # Deleting model 'ArticleRead'
- db.delete_table(u'article_articleread')
-
- # Deleting model 'Validation'
- db.delete_table(u'article_validation')
-
- models = {
- u'article.article': {
- 'Meta': {
- 'object_name': 'Article'}, 'authors': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'to': u"orm['auth.User']", 'symmetrical': 'False'}), 'create_at': (
- 'django.db.models.fields.DateTimeField', [], {}), 'description': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'image': (
- 'django.db.models.fields.files.ImageField', [], {
- 'max_length': '100', 'null': 'True', 'blank': 'True'}), 'is_locked': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'is_visible': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'last_reaction': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'blank': 'True', 'related_name': "'last_reaction'", 'null': 'True', 'to': u"orm['article.Reaction']"}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'sha_draft': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80', 'null': 'True', 'blank': 'True'}), 'sha_public': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80', 'null': 'True', 'blank': 'True'}), 'sha_validation': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80', 'null': 'True', 'blank': 'True'}), 'slug': (
- 'django.db.models.fields.SlugField', [], {
- 'max_length': '80'}), 'subcategory': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'to': u"orm['utils.SubCategory']", 'null': 'True', 'blank': 'True'}), 'text': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200', 'null': 'True', 'blank': 'True'}), 'thumbnail': (
- 'django.db.models.fields.files.ImageField', [], {
- 'max_length': '100', 'null': 'True', 'blank': 'True'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'}), 'update': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'})}, u'article.articleread': {
- 'Meta': {
- 'object_name': 'ArticleRead'}, 'article': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['article.Article']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'reaction': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['article.Reaction']"}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'reactions_read'", 'to': u"orm['auth.User']"})}, u'article.reaction': {
- 'Meta': {
- 'object_name': 'Reaction', '_ormbases': [u'utils.Comment']}, 'article': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['article.Article']"}), u'comment_ptr': (
- 'django.db.models.fields.related.OneToOneField', [], {
- 'to': u"orm['utils.Comment']", 'unique': 'True', 'primary_key': 'True'})}, u'article.validation': {
- 'Meta': {
- 'object_name': 'Validation'}, 'article': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['article.Article']", 'null': 'True', 'blank': 'True'}), 'comment_authors': (
- 'django.db.models.fields.TextField', [], {}), 'comment_validator': (
- 'django.db.models.fields.TextField', [], {
- 'null': 'True', 'blank': 'True'}), 'date_proposition': (
- 'django.db.models.fields.DateTimeField', [], {}), 'date_reserve': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'date_validation': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'status': (
- 'django.db.models.fields.CharField', [], {
- 'default': "'PENDING'", 'max_length': '10'}), 'validator': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'blank': 'True', 'related_name': "'articles_author_validations'", 'null': 'True', 'to': u"orm['auth.User']"}), 'version': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80', 'null': 'True', 'blank': 'True'})}, u'auth.group': {
- 'Meta': {
- 'object_name': 'Group'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '80'}), 'permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})}, u'auth.permission': {
- 'Meta': {
- 'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, 'codename': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'content_type': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['contenttypes.ContentType']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '50'})}, u'auth.user': {
- 'Meta': {
- 'object_name': 'User'}, 'date_joined': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'email': (
- 'django.db.models.fields.EmailField', [], {
- 'max_length': '75', 'blank': 'True'}), 'first_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'groups': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'is_active': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'is_staff': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'is_superuser': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'last_login': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'last_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'password': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128'}), 'user_permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), 'username': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '30'})}, u'contenttypes.contenttype': {
- 'Meta': {
- 'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'model': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'})}, u'utils.alert': {
- 'Meta': {
- 'object_name': 'Alert'}, 'author': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'alerts'", 'to': u"orm['auth.User']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'text': (
- 'django.db.models.fields.TextField', [], {})}, u'utils.comment': {
- 'Meta': {
- 'object_name': 'Comment'}, 'alerts': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'to': u"orm['utils.Alert']", 'null': 'True', 'blank': 'True'}), 'author': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'comments'", 'to': u"orm['auth.User']"}), 'dislike': (
- 'django.db.models.fields.IntegerField', [], {
- 'default': '0'}), 'editor': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'blank': 'True', 'related_name': "'comments-editor'", 'null': 'True', 'to': u"orm['auth.User']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'ip_address': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '15'}), 'is_visible': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'like': (
- 'django.db.models.fields.IntegerField', [], {
- 'default': '0'}), 'position': (
- 'django.db.models.fields.IntegerField', [], {}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'auto_now_add': 'True', 'blank': 'True'}), 'text': (
- 'django.db.models.fields.TextField', [], {}), 'text_hidden': (
- 'django.db.models.fields.CharField', [], {
- 'default': "''", 'max_length': '80'}), 'text_html': (
- 'django.db.models.fields.TextField', [], {}), 'update': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'})}, u'utils.subcategory': {
- 'Meta': {
- 'object_name': 'SubCategory'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'image': (
- 'django.db.models.fields.files.ImageField', [], {
- 'max_length': '100', 'null': 'True', 'blank': 'True'}), 'slug': (
- 'django.db.models.fields.SlugField', [], {
- 'max_length': '80'}), 'subtitle': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'})}}
-
- complete_apps = ['article']
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+import zds.article.models
+import easy_thumbnails.fields
+from django.conf import settings
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('utils', '0001_initial'),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Article',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('title', models.CharField(max_length=80, verbose_name=b'Titre')),
+ ('description', models.CharField(max_length=200, verbose_name=b'Description')),
+ ('slug', models.SlugField(max_length=80)),
+ ('create_at', models.DateTimeField(verbose_name=b'Date de cr\xc3\xa9ation')),
+ ('pubdate', models.DateTimeField(db_index=True, null=True, verbose_name=b'Date de publication', blank=True)),
+ ('update', models.DateTimeField(null=True, verbose_name=b'Date de mise \xc3\xa0 jour', blank=True)),
+ ('image', easy_thumbnails.fields.ThumbnailerImageField(null=True, upload_to=zds.article.models.image_path, blank=True)),
+ ('is_visible', models.BooleanField(default=False, db_index=True, verbose_name=b'Visible en r\xc3\xa9daction')),
+ ('sha_public', models.CharField(db_index=True, max_length=80, null=True, verbose_name=b'Sha1 de la version publique', blank=True)),
+ ('sha_validation', models.CharField(db_index=True, max_length=80, null=True, verbose_name=b'Sha1 de la version en validation', blank=True)),
+ ('sha_draft', models.CharField(db_index=True, max_length=80, null=True, verbose_name=b'Sha1 de la version de r\xc3\xa9daction', blank=True)),
+ ('text', models.CharField(max_length=200, null=True, verbose_name=b'chemin relatif du texte', blank=True)),
+ ('is_locked', models.BooleanField(default=False, verbose_name=b'Est verrouill\xc3\xa9')),
+ ('js_support', models.BooleanField(default=False, verbose_name=b'Support du Javascript')),
+ ('authors', models.ManyToManyField(to=settings.AUTH_USER_MODEL, verbose_name=b'Auteurs', db_index=True)),
+ ],
+ options={
+ 'verbose_name': 'Article',
+ 'verbose_name_plural': 'Articles',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='ArticleRead',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('article', models.ForeignKey(to='article.Article')),
+ ],
+ options={
+ 'verbose_name': 'Article lu',
+ 'verbose_name_plural': 'Articles lus',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='Reaction',
+ fields=[
+ ('comment_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='utils.Comment')),
+ ('article', models.ForeignKey(verbose_name=b'Article', to='article.Article')),
+ ],
+ options={
+ },
+ bases=('utils.comment',),
+ ),
+ migrations.CreateModel(
+ name='Validation',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('version', models.CharField(db_index=True, max_length=80, null=True, verbose_name=b'Sha1 de la version', blank=True)),
+ ('date_proposition', models.DateTimeField(verbose_name=b'Date de proposition', db_index=True)),
+ ('comment_authors', models.TextField(verbose_name=b"Commentaire de l'auteur")),
+ ('date_reserve', models.DateTimeField(null=True, verbose_name=b'Date de r\xc3\xa9servation', blank=True)),
+ ('date_validation', models.DateTimeField(null=True, verbose_name=b'Date de validation', blank=True)),
+ ('comment_validator', models.TextField(null=True, verbose_name=b'Commentaire du validateur', blank=True)),
+ ('status', models.CharField(default=b'PENDING', max_length=10, choices=[(b'PENDING', b"En attente d'un validateur"), (b'RESERVED', b'En cours de validation'), (b'PUBLISHED', b'Publi\xc3\xa9'), (b'REJECTED', b'Rejet\xc3\xa9')])),
+ ('article', models.ForeignKey(verbose_name=b'Article propos\xc3\xa9', blank=True, to='article.Article', null=True)),
+ ('validator', models.ForeignKey(related_name='articles_author_validations', verbose_name=b'Validateur', blank=True, to=settings.AUTH_USER_MODEL, null=True)),
+ ],
+ options={
+ 'verbose_name': 'Validation',
+ 'verbose_name_plural': 'Validations',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.AddField(
+ model_name='articleread',
+ name='reaction',
+ field=models.ForeignKey(to='article.Reaction'),
+ preserve_default=True,
+ ),
+ migrations.AddField(
+ model_name='articleread',
+ name='user',
+ field=models.ForeignKey(related_name='reactions_read', to=settings.AUTH_USER_MODEL),
+ preserve_default=True,
+ ),
+ migrations.AddField(
+ model_name='article',
+ name='last_reaction',
+ field=models.ForeignKey(related_name='last_reaction', verbose_name=b'Derniere r\xc3\xa9action', blank=True, to='article.Reaction', null=True),
+ preserve_default=True,
+ ),
+ migrations.AddField(
+ model_name='article',
+ name='licence',
+ field=models.ForeignKey(verbose_name=b'Licence', blank=True, to='utils.Licence', null=True),
+ preserve_default=True,
+ ),
+ migrations.AddField(
+ model_name='article',
+ name='subcategory',
+ field=models.ManyToManyField(db_index=True, to='utils.SubCategory', null=True, verbose_name=b'Sous-Cat\xc3\xa9gorie', blank=True),
+ preserve_default=True,
+ ),
+ ]
diff --git a/zds/article/migrations/0002_auto__add_index_article_is_visible__add_index_article_sha_draft__add_i.py b/zds/article/migrations/0002_auto__add_index_article_is_visible__add_index_article_sha_draft__add_i.py
deleted file mode 100644
index eecedbb418..0000000000
--- a/zds/article/migrations/0002_auto__add_index_article_is_visible__add_index_article_sha_draft__add_i.py
+++ /dev/null
@@ -1,165 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding index on 'Article', fields ['is_visible']
- db.create_index(u'article_article', ['is_visible'])
-
- # Adding index on 'Article', fields ['sha_draft']
- db.create_index(u'article_article', ['sha_draft'])
-
- # Adding index on 'Article', fields ['pubdate']
- db.create_index(u'article_article', ['pubdate'])
-
- # Adding index on 'Article', fields ['sha_validation']
- db.create_index(u'article_article', ['sha_validation'])
-
- # Adding index on 'Article', fields ['sha_public']
- db.create_index(u'article_article', ['sha_public'])
-
- # Adding index on 'Validation', fields ['version']
- db.create_index(u'article_validation', ['version'])
-
- # Adding index on 'Validation', fields ['date_proposition']
- db.create_index(u'article_validation', ['date_proposition'])
-
-
- def backwards(self, orm):
- # Removing index on 'Validation', fields ['date_proposition']
- db.delete_index(u'article_validation', ['date_proposition'])
-
- # Removing index on 'Validation', fields ['version']
- db.delete_index(u'article_validation', ['version'])
-
- # Removing index on 'Article', fields ['sha_public']
- db.delete_index(u'article_article', ['sha_public'])
-
- # Removing index on 'Article', fields ['sha_validation']
- db.delete_index(u'article_article', ['sha_validation'])
-
- # Removing index on 'Article', fields ['pubdate']
- db.delete_index(u'article_article', ['pubdate'])
-
- # Removing index on 'Article', fields ['sha_draft']
- db.delete_index(u'article_article', ['sha_draft'])
-
- # Removing index on 'Article', fields ['is_visible']
- db.delete_index(u'article_article', ['is_visible'])
-
-
- models = {
- u'article.article': {
- 'Meta': {'object_name': 'Article'},
- 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.User']", 'db_index': 'True', 'symmetrical': 'False'}),
- 'create_at': ('django.db.models.fields.DateTimeField', [], {}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
- 'is_locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_visible': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
- 'last_reaction': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_reaction'", 'null': 'True', 'to': u"orm['article.Reaction']"}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
- 'sha_draft': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'sha_public': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'sha_validation': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'subcategory': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['utils.SubCategory']", 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'thumbnail': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'article.articleread': {
- 'Meta': {'object_name': 'ArticleRead'},
- 'article': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['article.Article']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'reaction': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['article.Reaction']"}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reactions_read'", 'to': u"orm['auth.User']"})
- },
- u'article.reaction': {
- 'Meta': {'object_name': 'Reaction', '_ormbases': [u'utils.Comment']},
- 'article': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['article.Article']"}),
- u'comment_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['utils.Comment']", 'unique': 'True', 'primary_key': 'True'})
- },
- u'article.validation': {
- 'Meta': {'object_name': 'Validation'},
- 'article': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['article.Article']", 'null': 'True', 'blank': 'True'}),
- 'comment_authors': ('django.db.models.fields.TextField', [], {}),
- 'comment_validator': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
- 'date_proposition': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
- 'date_reserve': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'date_validation': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'status': ('django.db.models.fields.CharField', [], {'default': "'PENDING'", 'max_length': '10'}),
- 'validator': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'articles_author_validations'", 'null': 'True', 'to': u"orm['auth.User']"}),
- 'version': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'})
- },
- u'auth.group': {
- 'Meta': {'object_name': 'Group'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'auth.permission': {
- 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'utils.comment': {
- 'Meta': {'object_name': 'Comment'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': u"orm['auth.User']"}),
- 'dislike': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'editor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments-editor'", 'null': 'True', 'to': u"orm['auth.User']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'ip_address': ('django.db.models.fields.CharField', [], {'max_length': '39'}),
- 'is_visible': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'like': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'position': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {}),
- 'text_hidden': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '80'}),
- 'text_html': ('django.db.models.fields.TextField', [], {}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'utils.subcategory': {
- 'Meta': {'object_name': 'SubCategory'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- }
- }
-
- complete_apps = ['article']
\ No newline at end of file
diff --git a/zds/article/migrations/0003_auto__del_field_article_thumbnail__add_field_article_licence.py b/zds/article/migrations/0003_auto__del_field_article_thumbnail__add_field_article_licence.py
deleted file mode 100644
index 277510012a..0000000000
--- a/zds/article/migrations/0003_auto__del_field_article_thumbnail__add_field_article_licence.py
+++ /dev/null
@@ -1,146 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Deleting field 'Article.thumbnail'
- db.delete_column(u'article_article', 'thumbnail')
-
- # Adding field 'Article.licence'
- db.add_column(u'article_article', 'licence',
- self.gf('django.db.models.fields.related.ForeignKey')(to=orm['utils.Licence'], null=True, blank=True),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Adding field 'Article.thumbnail'
- db.add_column(u'article_article', 'thumbnail',
- self.gf('django.db.models.fields.files.ImageField')(max_length=100, null=True, blank=True),
- keep_default=False)
-
- # Deleting field 'Article.licence'
- db.delete_column(u'article_article', 'licence_id')
-
-
- models = {
- u'article.article': {
- 'Meta': {'object_name': 'Article'},
- 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.User']", 'db_index': 'True', 'symmetrical': 'False'}),
- 'create_at': ('django.db.models.fields.DateTimeField', [], {}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
- 'is_locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_visible': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
- 'last_reaction': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_reaction'", 'null': 'True', 'to': u"orm['article.Reaction']"}),
- 'licence': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['utils.Licence']", 'null': 'True', 'blank': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
- 'sha_draft': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'sha_public': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'sha_validation': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'subcategory': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['utils.SubCategory']", 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'article.articleread': {
- 'Meta': {'object_name': 'ArticleRead'},
- 'article': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['article.Article']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'reaction': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['article.Reaction']"}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reactions_read'", 'to': u"orm['auth.User']"})
- },
- u'article.reaction': {
- 'Meta': {'object_name': 'Reaction', '_ormbases': [u'utils.Comment']},
- 'article': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['article.Article']"}),
- u'comment_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['utils.Comment']", 'unique': 'True', 'primary_key': 'True'})
- },
- u'article.validation': {
- 'Meta': {'object_name': 'Validation'},
- 'article': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['article.Article']", 'null': 'True', 'blank': 'True'}),
- 'comment_authors': ('django.db.models.fields.TextField', [], {}),
- 'comment_validator': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
- 'date_proposition': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
- 'date_reserve': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'date_validation': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'status': ('django.db.models.fields.CharField', [], {'default': "'PENDING'", 'max_length': '10'}),
- 'validator': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'articles_author_validations'", 'null': 'True', 'to': u"orm['auth.User']"}),
- 'version': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'})
- },
- u'auth.group': {
- 'Meta': {'object_name': 'Group'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'auth.permission': {
- 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'utils.comment': {
- 'Meta': {'object_name': 'Comment'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': u"orm['auth.User']"}),
- 'dislike': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'editor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments-editor'", 'null': 'True', 'to': u"orm['auth.User']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'ip_address': ('django.db.models.fields.CharField', [], {'max_length': '39'}),
- 'is_visible': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'like': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'position': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {}),
- 'text_hidden': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '80'}),
- 'text_html': ('django.db.models.fields.TextField', [], {}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'utils.licence': {
- 'Meta': {'object_name': 'Licence'},
- 'code': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
- 'description': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'utils.subcategory': {
- 'Meta': {'object_name': 'SubCategory'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- }
- }
-
- complete_apps = ['article']
\ No newline at end of file
diff --git a/zds/article/migrations/0004_auto__add_field_article_js_support.py b/zds/article/migrations/0004_auto__add_field_article_js_support.py
deleted file mode 100644
index 0f8d0b7c21..0000000000
--- a/zds/article/migrations/0004_auto__add_field_article_js_support.py
+++ /dev/null
@@ -1,139 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'Article.js_support'
- db.add_column(u'article_article', 'js_support',
- self.gf('django.db.models.fields.BooleanField')(default=False),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'Article.js_support'
- db.delete_column(u'article_article', 'js_support')
-
-
- models = {
- u'article.article': {
- 'Meta': {'object_name': 'Article'},
- 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.User']", 'db_index': 'True', 'symmetrical': 'False'}),
- 'create_at': ('django.db.models.fields.DateTimeField', [], {}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
- 'is_locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_visible': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
- 'js_support': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_reaction': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_reaction'", 'null': 'True', 'to': u"orm['article.Reaction']"}),
- 'licence': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['utils.Licence']", 'null': 'True', 'blank': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
- 'sha_draft': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'sha_public': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'sha_validation': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'subcategory': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['utils.SubCategory']", 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'article.articleread': {
- 'Meta': {'object_name': 'ArticleRead'},
- 'article': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['article.Article']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'reaction': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['article.Reaction']"}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reactions_read'", 'to': u"orm['auth.User']"})
- },
- u'article.reaction': {
- 'Meta': {'object_name': 'Reaction', '_ormbases': [u'utils.Comment']},
- 'article': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['article.Article']"}),
- u'comment_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['utils.Comment']", 'unique': 'True', 'primary_key': 'True'})
- },
- u'article.validation': {
- 'Meta': {'object_name': 'Validation'},
- 'article': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['article.Article']", 'null': 'True', 'blank': 'True'}),
- 'comment_authors': ('django.db.models.fields.TextField', [], {}),
- 'comment_validator': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
- 'date_proposition': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
- 'date_reserve': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'date_validation': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'status': ('django.db.models.fields.CharField', [], {'default': "'PENDING'", 'max_length': '10'}),
- 'validator': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'articles_author_validations'", 'null': 'True', 'to': u"orm['auth.User']"}),
- 'version': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'})
- },
- u'auth.group': {
- 'Meta': {'object_name': 'Group'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'auth.permission': {
- 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'utils.comment': {
- 'Meta': {'object_name': 'Comment'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': u"orm['auth.User']"}),
- 'dislike': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'editor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments-editor'", 'null': 'True', 'to': u"orm['auth.User']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'ip_address': ('django.db.models.fields.CharField', [], {'max_length': '39'}),
- 'is_visible': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'like': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'position': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {}),
- 'text_hidden': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '80'}),
- 'text_html': ('django.db.models.fields.TextField', [], {}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'utils.licence': {
- 'Meta': {'object_name': 'Licence'},
- 'code': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
- 'description': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'utils.subcategory': {
- 'Meta': {'object_name': 'SubCategory'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- }
- }
-
- complete_apps = ['article']
\ No newline at end of file
diff --git a/zds/article/tests/tests.py b/zds/article/tests/tests.py
index 9310e33494..c15a963c6e 100644
--- a/zds/article/tests/tests.py
+++ b/zds/article/tests/tests.py
@@ -28,15 +28,15 @@
from zds.article.models import Validation, Reaction, Article, Licence
from zds.member.factories import ProfileFactory, StaffProfileFactory
from zds.mp.models import PrivateTopic
-from zds.settings import SITE_ROOT
+from zds.settings import BASE_DIR
from zds.utils.models import Alert
overrided_zds_app = settings.ZDS_APP
-overrided_zds_app['article']['repo_path'] = os.path.join(SITE_ROOT, 'article-data-test')
+overrided_zds_app['article']['repo_path'] = os.path.join(BASE_DIR, 'article-data-test')
-@override_settings(MEDIA_ROOT=os.path.join(SITE_ROOT, 'media-test'))
+@override_settings(MEDIA_ROOT=os.path.join(BASE_DIR, 'media-test'))
@override_settings(ZDS_APP=overrided_zds_app)
class ArticleTests(TestCase):
@@ -110,7 +110,7 @@ def setUp(self):
def test_delete_image_on_change(self):
"""test que l'image est bien supprimée quand on la change"""
- root = settings.SITE_ROOT
+ root = settings.BASE_DIR
if not os.path.isdir(settings.MEDIA_ROOT):
os.mkdir(settings.MEDIA_ROOT)
shutil.copyfile(
diff --git a/zds/article/tests/tests_feeds.py b/zds/article/tests/tests_feeds.py
index 4b0ab515d9..704de877cd 100644
--- a/zds/article/tests/tests_feeds.py
+++ b/zds/article/tests/tests_feeds.py
@@ -13,14 +13,14 @@
from zds.article.models import Validation, Article
from zds.article.feeds import LastArticlesFeedRSS, LastArticlesFeedATOM
from zds.member.factories import ProfileFactory, StaffProfileFactory
-from zds.settings import SITE_ROOT
+from zds.settings import BASE_DIR
overrided_zds_app = settings.ZDS_APP
-overrided_zds_app['article']['repo_path'] = os.path.join(SITE_ROOT, 'article-data-test')
+overrided_zds_app['article']['repo_path'] = os.path.join(BASE_DIR, 'article-data-test')
-@override_settings(MEDIA_ROOT=os.path.join(SITE_ROOT, 'media-test'))
+@override_settings(MEDIA_ROOT=os.path.join(BASE_DIR, 'media-test'))
@override_settings(ZDS_APP=overrided_zds_app)
class LastArticlesFeedRSSTest(TestCase):
diff --git a/zds/article/views.py b/zds/article/views.py
index bc1d77c3fc..5264f85fc7 100644
--- a/zds/article/views.py
+++ b/zds/article/views.py
@@ -680,13 +680,20 @@ def modify(request):
# A validatir would like to valid an article in validation. We
# must update sha_public with the current sha of the validation.
elif 'valid-article' in request.POST:
- mep(article, article.sha_validation)
+
validation = Validation.objects\
.filter(article__pk=article.pk,
version=article.sha_validation)\
.latest('date_proposition')
if request.user == validation.validator:
+
+ try:
+ mep(article, article.sha_validation)
+ except UnicodeErrorInArticle as e:
+ messages.error(request, e)
+ return redirect(article.get_absolute_url() + '?version=' + validation.version)
+
validation.comment_validator = request.POST['comment-v']
validation.status = 'PUBLISHED'
validation.date_validation = datetime.now()
@@ -902,7 +909,7 @@ def list_validation(request):
# Get subcategory to filter validations.
try:
- subcategory = get_object_or_404(Category, pk=int(request.GET['subcategory']))
+ subcategory = get_object_or_404(SubCategory, pk=int(request.GET['subcategory']))
except (KeyError, ValueError, Http404):
subcategory = None
@@ -1036,7 +1043,12 @@ def history(request, article_pk, article_slug):
'article': article, 'logs': logs, 'formJs': form_js
})
+
# Reactions at an article.
+class UnicodeErrorInArticle(Exception):
+
+ def __init__(self, *args, **kwargs):
+ super(UnicodeErrorInArticle, self).__init__(*args, **kwargs)
def mep(article, sha):
@@ -1057,7 +1069,12 @@ def mep(article, sha):
is_js = "js"
else:
is_js = ""
- html_file.write(emarkdown(md_file_contenu, is_js))
+ try:
+ html_file.write(emarkdown(md_file_contenu, is_js))
+ except (UnicodeError, UnicodeEncodeError):
+ raise UnicodeErrorInArticle(
+ u'Une erreur est survenue lors de la génération du HTML, vérifiez que le code markdown ne contient '
+ u'pas d\'erreurs')
html_file.close()
diff --git a/zds/forum/admin.py b/zds/forum/admin.py
index 4e1692750e..59fe718631 100644
--- a/zds/forum/admin.py
+++ b/zds/forum/admin.py
@@ -7,6 +7,7 @@
admin.site.register(Category)
admin.site.register(Forum)
+# TODO Topic admin is broken (load an admin Topic page implies to load ALL Members and Posts!)
admin.site.register(Topic)
admin.site.register(Post)
admin.site.register(TopicRead)
diff --git a/zds/forum/factories.py b/zds/forum/factories.py
index 4b0a1ddb63..f08d844915 100644
--- a/zds/forum/factories.py
+++ b/zds/forum/factories.py
@@ -8,32 +8,30 @@
class CategoryFactory(factory.DjangoModelFactory):
FACTORY_FOR = Category
- title = factory.Sequence(lambda n: 'Ma catégorie No{0}'.format(n))
- slug = factory.Sequence(lambda n: 'category{0}'.format(n))
+ title = factory.Sequence('Ma catégorie No{0}'.format)
+ slug = factory.Sequence('category{0}'.format)
class ForumFactory(factory.DjangoModelFactory):
FACTORY_FOR = Forum
- title = factory.Sequence(lambda n: 'Mon Forum No{0}'.format(n))
- subtitle = factory.Sequence(
- lambda n: 'Sous Titre du Forum No{0}'.format(n))
- slug = factory.Sequence(lambda n: 'forum{0}'.format(n))
+ title = factory.Sequence('Mon Forum No{0}'.format)
+ subtitle = factory.Sequence('Sous Titre du Forum No{0}'.format)
+ slug = factory.Sequence('forum{0}'.format)
class TagFactory(factory.DjangoModelFactory):
FACTORY_FOR = Tag
- title = factory.Sequence(lambda n: 'Tag{0}'.format(n))
- slug = factory.Sequence(lambda n: 'tag{0}'.format(n))
+ title = factory.Sequence('Tag{0}'.format)
+ slug = factory.Sequence('tag{0}'.format)
class TopicFactory(factory.DjangoModelFactory):
FACTORY_FOR = Topic
- title = factory.Sequence(lambda n: 'Mon Sujet No{0}'.format(n))
- subtitle = factory.Sequence(
- lambda n: 'Sous Titre du sujet No{0}'.format(n))
+ title = factory.Sequence('Mon Sujet No{0}'.format)
+ subtitle = factory.Sequence('Sous Titre du sujet No{0}'.format)
class PostFactory(factory.DjangoModelFactory):
diff --git a/zds/forum/migrations/0001_initial.py b/zds/forum/migrations/0001_initial.py
index 536b3cf09b..23dff2927c 100644
--- a/zds/forum/migrations/0001_initial.py
+++ b/zds/forum/migrations/0001_initial.py
@@ -1,283 +1,116 @@
# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding model 'Category'
- db.create_table(
- u'forum_category', ((u'id', self.gf('django.db.models.fields.AutoField')(
- primary_key=True)), ('title', self.gf('django.db.models.fields.CharField')(
- max_length=80)), ('position', self.gf('django.db.models.fields.IntegerField')(
- null=True, blank=True)), ('slug', self.gf('django.db.models.fields.SlugField')(
- unique=True, max_length=80)), ))
- db.send_create_signal(u'forum', ['Category'])
-
- # Adding model 'Forum'
- db.create_table(
- u'forum_forum', ((u'id', self.gf('django.db.models.fields.AutoField')(
- primary_key=True)), ('title', self.gf('django.db.models.fields.CharField')(
- max_length=80)), ('subtitle', self.gf('django.db.models.fields.CharField')(
- max_length=200)), ('image', self.gf('django.db.models.fields.files.ImageField')(
- max_length=100)), ('category', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['forum.Category'])), ('position_in_category', self.gf('django.db.models.fields.IntegerField')(
- null=True, blank=True)), ('slug', self.gf('django.db.models.fields.SlugField')(
- unique=True, max_length=80)), ))
- db.send_create_signal(u'forum', ['Forum'])
-
- # Adding M2M table for field group on 'Forum'
- m2m_table_name = db.shorten_name(u'forum_forum_group')
- db.create_table(
- m2m_table_name, (('id', models.AutoField(
- verbose_name='ID', primary_key=True, auto_created=True)), ('forum', models.ForeignKey(
- orm[u'forum.forum'], null=False)), ('group', models.ForeignKey(
- orm[u'auth.group'], null=False))))
- db.create_unique(m2m_table_name, ['forum_id', 'group_id'])
-
- # Adding model 'Topic'
- db.create_table(
- u'forum_topic', ((u'id', self.gf('django.db.models.fields.AutoField')(
- primary_key=True)), ('title', self.gf('django.db.models.fields.CharField')(
- max_length=60)), ('subtitle', self.gf('django.db.models.fields.CharField')(
- max_length=100)), ('forum', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['forum.Forum'])), ('author', self.gf('django.db.models.fields.related.ForeignKey')(
- related_name='topics', to=orm['auth.User'])), ('last_message', self.gf('django.db.models.fields.related.ForeignKey')(
- related_name='last_message', null=True, to=orm['forum.Post'])), ('pubdate', self.gf('django.db.models.fields.DateTimeField')(
- auto_now_add=True, blank=True)), ('is_solved', self.gf('django.db.models.fields.BooleanField')(
- default=False)), ('is_locked', self.gf('django.db.models.fields.BooleanField')(
- default=False)), ('is_sticky', self.gf('django.db.models.fields.BooleanField')(
- default=False)), ))
- db.send_create_signal(u'forum', ['Topic'])
-
- # Adding model 'Post'
- db.create_table(
- u'forum_post',
- ((u'comment_ptr',
- self.gf('django.db.models.fields.related.OneToOneField')(
- to=orm['utils.Comment'],
- unique=True,
- primary_key=True)),
- ('topic',
- self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['forum.Topic'])),
- ('is_useful',
- self.gf('django.db.models.fields.BooleanField')(
- default=False)),
- ))
- db.send_create_signal(u'forum', ['Post'])
-
- # Adding model 'TopicRead'
- db.create_table(
- u'forum_topicread', ((u'id', self.gf('django.db.models.fields.AutoField')(
- primary_key=True)), ('topic', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['forum.Topic'])), ('post', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['forum.Post'])), ('user', self.gf('django.db.models.fields.related.ForeignKey')(
- related_name='topics_read', to=orm['auth.User'])), ))
- db.send_create_signal(u'forum', ['TopicRead'])
-
- # Adding model 'TopicFollowed'
- db.create_table(
- u'forum_topicfollowed', ((u'id', self.gf('django.db.models.fields.AutoField')(
- primary_key=True)), ('topic', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['forum.Topic'])), ('user', self.gf('django.db.models.fields.related.ForeignKey')(
- related_name='topics_followed', to=orm['auth.User'])), ))
- db.send_create_signal(u'forum', ['TopicFollowed'])
-
- def backwards(self, orm):
- # Deleting model 'Category'
- db.delete_table(u'forum_category')
-
- # Deleting model 'Forum'
- db.delete_table(u'forum_forum')
-
- # Removing M2M table for field group on 'Forum'
- db.delete_table(db.shorten_name(u'forum_forum_group'))
-
- # Deleting model 'Topic'
- db.delete_table(u'forum_topic')
-
- # Deleting model 'Post'
- db.delete_table(u'forum_post')
-
- # Deleting model 'TopicRead'
- db.delete_table(u'forum_topicread')
-
- # Deleting model 'TopicFollowed'
- db.delete_table(u'forum_topicfollowed')
-
- models = {
- u'auth.group': {
- 'Meta': {
- 'object_name': 'Group'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '80'}), 'permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})}, u'auth.permission': {
- 'Meta': {
- 'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, 'codename': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'content_type': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['contenttypes.ContentType']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '50'})}, u'auth.user': {
- 'Meta': {
- 'object_name': 'User'}, 'date_joined': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'email': (
- 'django.db.models.fields.EmailField', [], {
- 'max_length': '75', 'blank': 'True'}), 'first_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'groups': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'is_active': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'is_staff': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'is_superuser': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'last_login': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'last_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'password': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128'}), 'user_permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), 'username': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '30'})}, u'contenttypes.contenttype': {
- 'Meta': {
- 'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'model': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'})}, u'forum.category': {
- 'Meta': {
- 'object_name': 'Category'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'position': (
- 'django.db.models.fields.IntegerField', [], {
- 'null': 'True', 'blank': 'True'}), 'slug': (
- 'django.db.models.fields.SlugField', [], {
- 'unique': 'True', 'max_length': '80'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'})}, u'forum.forum': {
- 'Meta': {
- 'object_name': 'Forum'}, 'category': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['forum.Category']"}), 'group': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'to': u"orm['auth.Group']", 'null': 'True', 'blank': 'True'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'image': (
- 'django.db.models.fields.files.ImageField', [], {
- 'max_length': '100'}), 'position_in_category': (
- 'django.db.models.fields.IntegerField', [], {
- 'null': 'True', 'blank': 'True'}), 'slug': (
- 'django.db.models.fields.SlugField', [], {
- 'unique': 'True', 'max_length': '80'}), 'subtitle': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'})}, u'forum.post': {
- 'Meta': {
- 'object_name': 'Post', '_ormbases': [u'utils.Comment']}, u'comment_ptr': (
- 'django.db.models.fields.related.OneToOneField', [], {
- 'to': u"orm['utils.Comment']", 'unique': 'True', 'primary_key': 'True'}), 'is_useful': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'topic': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['forum.Topic']"})}, u'forum.topic': {
- 'Meta': {
- 'object_name': 'Topic'}, 'author': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'topics'", 'to': u"orm['auth.User']"}), 'forum': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['forum.Forum']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'is_locked': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'is_solved': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'is_sticky': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'last_message': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'last_message'", 'null': 'True', 'to': u"orm['forum.Post']"}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'auto_now_add': 'True', 'blank': 'True'}), 'subtitle': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '60'})}, u'forum.topicfollowed': {
- 'Meta': {
- 'object_name': 'TopicFollowed'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'topic': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['forum.Topic']"}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'topics_followed'", 'to': u"orm['auth.User']"})}, u'forum.topicread': {
- 'Meta': {
- 'object_name': 'TopicRead'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'post': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['forum.Post']"}), 'topic': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['forum.Topic']"}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'topics_read'", 'to': u"orm['auth.User']"})}, u'utils.alert': {
- 'Meta': {
- 'object_name': 'Alert'}, 'author': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'alerts'", 'to': u"orm['auth.User']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'text': (
- 'django.db.models.fields.TextField', [], {})}, u'utils.comment': {
- 'Meta': {
- 'object_name': 'Comment'}, 'alerts': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'to': u"orm['utils.Alert']", 'null': 'True', 'blank': 'True'}), 'author': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'comments'", 'to': u"orm['auth.User']"}), 'dislike': (
- 'django.db.models.fields.IntegerField', [], {
- 'default': '0'}), 'editor': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'blank': 'True', 'related_name': "'comments-editor'", 'null': 'True', 'to': u"orm['auth.User']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'ip_address': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '15'}), 'is_visible': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'like': (
- 'django.db.models.fields.IntegerField', [], {
- 'default': '0'}), 'position': (
- 'django.db.models.fields.IntegerField', [], {}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'auto_now_add': 'True', 'blank': 'True'}), 'text': (
- 'django.db.models.fields.TextField', [], {}), 'text_hidden': (
- 'django.db.models.fields.CharField', [], {
- 'default': "''", 'max_length': '80'}), 'text_html': (
- 'django.db.models.fields.TextField', [], {}), 'update': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'})}}
-
- complete_apps = ['forum']
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+from django.conf import settings
+import zds.forum.models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('utils', '0001_initial'),
+ ('auth', '0001_initial'),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Category',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('title', models.CharField(max_length=80, verbose_name=b'Titre')),
+ ('position', models.IntegerField(null=True, verbose_name=b'Position', blank=True)),
+ ('slug', models.SlugField(help_text=b"Ces slugs vont provoquer des conflits d'URL et sont donc interdits : notifications resolution_alerte sujet sujets message messages", unique=True, max_length=80)),
+ ],
+ options={
+ 'verbose_name': 'Cat\xe9gorie',
+ 'verbose_name_plural': 'Cat\xe9gories',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='Forum',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('title', models.CharField(max_length=80, verbose_name=b'Titre')),
+ ('subtitle', models.CharField(max_length=200, verbose_name=b'Sous-titre')),
+ ('image', models.ImageField(upload_to=zds.forum.models.image_path_forum)),
+ ('position_in_category', models.IntegerField(db_index=True, null=True, verbose_name=b'Position dans la cat\xc3\xa9gorie', blank=True)),
+ ('slug', models.SlugField(unique=True, max_length=80)),
+ ('category', models.ForeignKey(verbose_name=b'Cat\xc3\xa9gorie', to='forum.Category')),
+ ('group', models.ManyToManyField(to='auth.Group', null=True, verbose_name=b'Groupe autoris\xc3\xa9s (Aucun = public)', blank=True)),
+ ],
+ options={
+ 'verbose_name': 'Forum',
+ 'verbose_name_plural': 'Forums',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='Post',
+ fields=[
+ ('comment_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='utils.Comment')),
+ ('is_useful', models.BooleanField(default=False, verbose_name=b'Est utile')),
+ ],
+ options={
+ },
+ bases=('utils.comment',),
+ ),
+ migrations.CreateModel(
+ name='Topic',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('title', models.CharField(max_length=80, verbose_name=b'Titre')),
+ ('subtitle', models.CharField(max_length=200, verbose_name=b'Sous-titre')),
+ ('pubdate', models.DateTimeField(auto_now_add=True, verbose_name=b'Date de cr\xc3\xa9ation')),
+ ('is_solved', models.BooleanField(default=False, db_index=True, verbose_name=b'Est r\xc3\xa9solu')),
+ ('is_locked', models.BooleanField(default=False, verbose_name=b'Est verrouill\xc3\xa9')),
+ ('is_sticky', models.BooleanField(default=False, db_index=True, verbose_name=b'Est en post-it')),
+ ('key', models.IntegerField(null=True, verbose_name=b'cle', blank=True)),
+ ('author', models.ForeignKey(related_name='topics', verbose_name=b'Auteur', to=settings.AUTH_USER_MODEL)),
+ ('forum', models.ForeignKey(verbose_name=b'Forum', to='forum.Forum')),
+ ('last_message', models.ForeignKey(related_name='last_message', verbose_name=b'Dernier message', to='forum.Post', null=True)),
+ ('tags', models.ManyToManyField(db_index=True, to='utils.Tag', null=True, verbose_name=b'Tags du forum', blank=True)),
+ ],
+ options={
+ 'verbose_name': 'Sujet',
+ 'verbose_name_plural': 'Sujets',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='TopicFollowed',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('email', models.BooleanField(default=False, db_index=True, verbose_name=b'Notification par courriel')),
+ ('topic', models.ForeignKey(to='forum.Topic')),
+ ('user', models.ForeignKey(related_name='topics_followed', to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'verbose_name': 'Sujet suivi',
+ 'verbose_name_plural': 'Sujets suivis',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='TopicRead',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('post', models.ForeignKey(to='forum.Post')),
+ ('topic', models.ForeignKey(to='forum.Topic')),
+ ('user', models.ForeignKey(related_name='topics_read', to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'verbose_name': 'Sujet lu',
+ 'verbose_name_plural': 'Sujets lus',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.AddField(
+ model_name='post',
+ name='topic',
+ field=models.ForeignKey(verbose_name=b'Sujet', to='forum.Topic'),
+ preserve_default=True,
+ ),
+ ]
diff --git a/zds/forum/migrations/0002_auto_20150410_1505.py b/zds/forum/migrations/0002_auto_20150410_1505.py
new file mode 100644
index 0000000000..bfb9c69ac3
--- /dev/null
+++ b/zds/forum/migrations/0002_auto_20150410_1505.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('forum', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name='category',
+ options={'ordering': ['position', 'title'], 'verbose_name': 'Cat\xe9gorie', 'verbose_name_plural': 'Cat\xe9gories'},
+ ),
+ migrations.AlterModelOptions(
+ name='forum',
+ options={'ordering': ['position_in_category', 'title'], 'verbose_name': 'Forum', 'verbose_name_plural': 'Forums'},
+ ),
+ ]
diff --git a/zds/forum/migrations/0002_auto__chg_field_topic_subtitle__chg_field_topic_title.py b/zds/forum/migrations/0002_auto__chg_field_topic_subtitle__chg_field_topic_title.py
deleted file mode 100644
index 611430e071..0000000000
--- a/zds/forum/migrations/0002_auto__chg_field_topic_subtitle__chg_field_topic_title.py
+++ /dev/null
@@ -1,213 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
-
- # Changing field 'Topic.subtitle'
- db.alter_column(
- u'forum_topic',
- 'subtitle',
- self.gf('django.db.models.fields.CharField')(
- max_length=200))
-
- # Changing field 'Topic.title'
- db.alter_column(
- u'forum_topic',
- 'title',
- self.gf('django.db.models.fields.CharField')(
- max_length=80))
-
- def backwards(self, orm):
-
- # Changing field 'Topic.subtitle'
- db.alter_column(
- u'forum_topic',
- 'subtitle',
- self.gf('django.db.models.fields.CharField')(
- max_length=100))
-
- # Changing field 'Topic.title'
- db.alter_column(
- u'forum_topic',
- 'title',
- self.gf('django.db.models.fields.CharField')(
- max_length=60))
-
- models = {
- u'auth.group': {
- 'Meta': {
- 'object_name': 'Group'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '80'}), 'permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})}, u'auth.permission': {
- 'Meta': {
- 'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, 'codename': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'content_type': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['contenttypes.ContentType']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '50'})}, u'auth.user': {
- 'Meta': {
- 'object_name': 'User'}, 'date_joined': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'email': (
- 'django.db.models.fields.EmailField', [], {
- 'max_length': '75', 'blank': 'True'}), 'first_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'groups': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'is_active': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'is_staff': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'is_superuser': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'last_login': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'last_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'password': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128'}), 'user_permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), 'username': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '30'})}, u'contenttypes.contenttype': {
- 'Meta': {
- 'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'model': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'})}, u'forum.category': {
- 'Meta': {
- 'object_name': 'Category'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'position': (
- 'django.db.models.fields.IntegerField', [], {
- 'null': 'True', 'blank': 'True'}), 'slug': (
- 'django.db.models.fields.SlugField', [], {
- 'unique': 'True', 'max_length': '80'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'})}, u'forum.forum': {
- 'Meta': {
- 'object_name': 'Forum'}, 'category': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['forum.Category']"}), 'group': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'to': u"orm['auth.Group']", 'null': 'True', 'blank': 'True'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'image': (
- 'django.db.models.fields.files.ImageField', [], {
- 'max_length': '100'}), 'position_in_category': (
- 'django.db.models.fields.IntegerField', [], {
- 'null': 'True', 'blank': 'True'}), 'slug': (
- 'django.db.models.fields.SlugField', [], {
- 'unique': 'True', 'max_length': '80'}), 'subtitle': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'})}, u'forum.post': {
- 'Meta': {
- 'object_name': 'Post', '_ormbases': [u'utils.Comment']}, u'comment_ptr': (
- 'django.db.models.fields.related.OneToOneField', [], {
- 'to': u"orm['utils.Comment']", 'unique': 'True', 'primary_key': 'True'}), 'is_useful': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'topic': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['forum.Topic']"})}, u'forum.topic': {
- 'Meta': {
- 'object_name': 'Topic'}, 'author': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'topics'", 'to': u"orm['auth.User']"}), 'forum': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['forum.Forum']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'is_locked': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'is_solved': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'is_sticky': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'last_message': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'last_message'", 'null': 'True', 'to': u"orm['forum.Post']"}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'auto_now_add': 'True', 'blank': 'True'}), 'subtitle': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'})}, u'forum.topicfollowed': {
- 'Meta': {
- 'object_name': 'TopicFollowed'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'topic': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['forum.Topic']"}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'topics_followed'", 'to': u"orm['auth.User']"})}, u'forum.topicread': {
- 'Meta': {
- 'object_name': 'TopicRead'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'post': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['forum.Post']"}), 'topic': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['forum.Topic']"}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'topics_read'", 'to': u"orm['auth.User']"})}, u'utils.alert': {
- 'Meta': {
- 'object_name': 'Alert'}, 'author': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'alerts'", 'to': u"orm['auth.User']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'text': (
- 'django.db.models.fields.TextField', [], {})}, u'utils.comment': {
- 'Meta': {
- 'object_name': 'Comment'}, 'alerts': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'to': u"orm['utils.Alert']", 'null': 'True', 'blank': 'True'}), 'author': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'comments'", 'to': u"orm['auth.User']"}), 'dislike': (
- 'django.db.models.fields.IntegerField', [], {
- 'default': '0'}), 'editor': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'blank': 'True', 'related_name': "'comments-editor'", 'null': 'True', 'to': u"orm['auth.User']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'ip_address': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '15'}), 'is_visible': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'like': (
- 'django.db.models.fields.IntegerField', [], {
- 'default': '0'}), 'position': (
- 'django.db.models.fields.IntegerField', [], {}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'auto_now_add': 'True', 'blank': 'True'}), 'text': (
- 'django.db.models.fields.TextField', [], {}), 'text_hidden': (
- 'django.db.models.fields.CharField', [], {
- 'default': "''", 'max_length': '80'}), 'text_html': (
- 'django.db.models.fields.TextField', [], {}), 'update': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'})}}
-
- complete_apps = ['forum']
diff --git a/zds/forum/migrations/0003_auto.py b/zds/forum/migrations/0003_auto.py
deleted file mode 100644
index affddaa1c7..0000000000
--- a/zds/forum/migrations/0003_auto.py
+++ /dev/null
@@ -1,192 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding M2M table for field tags on 'Topic'
- m2m_table_name = db.shorten_name(u'forum_topic_tags')
- db.create_table(
- m2m_table_name, (('id', models.AutoField(
- verbose_name='ID', primary_key=True, auto_created=True)), ('topic', models.ForeignKey(
- orm[u'forum.topic'], null=False)), ('tag', models.ForeignKey(
- orm[u'utils.tag'], null=False))))
- db.create_unique(m2m_table_name, ['topic_id', 'tag_id'])
-
- def backwards(self, orm):
- # Removing M2M table for field tags on 'Topic'
- db.delete_table(db.shorten_name(u'forum_topic_tags'))
-
- models = {
- u'auth.group': {
- 'Meta': {
- 'object_name': 'Group'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '80'}), 'permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})}, u'auth.permission': {
- 'Meta': {
- 'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, 'codename': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'content_type': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['contenttypes.ContentType']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '50'})}, u'auth.user': {
- 'Meta': {
- 'object_name': 'User'}, 'date_joined': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'email': (
- 'django.db.models.fields.EmailField', [], {
- 'max_length': '75', 'blank': 'True'}), 'first_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'groups': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'is_active': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'is_staff': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'is_superuser': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'last_login': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'last_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'password': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128'}), 'user_permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), 'username': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '30'})}, u'contenttypes.contenttype': {
- 'Meta': {
- 'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'model': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'})}, u'forum.category': {
- 'Meta': {
- 'object_name': 'Category'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'position': (
- 'django.db.models.fields.IntegerField', [], {
- 'null': 'True', 'blank': 'True'}), 'slug': (
- 'django.db.models.fields.SlugField', [], {
- 'unique': 'True', 'max_length': '80'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'})}, u'forum.forum': {
- 'Meta': {
- 'object_name': 'Forum'}, 'category': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['forum.Category']"}), 'group': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'to': u"orm['auth.Group']", 'null': 'True', 'blank': 'True'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'image': (
- 'django.db.models.fields.files.ImageField', [], {
- 'max_length': '100'}), 'position_in_category': (
- 'django.db.models.fields.IntegerField', [], {
- 'null': 'True', 'blank': 'True'}), 'slug': (
- 'django.db.models.fields.SlugField', [], {
- 'unique': 'True', 'max_length': '80'}), 'subtitle': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'})}, u'forum.post': {
- 'Meta': {
- 'object_name': 'Post', '_ormbases': [u'utils.Comment']}, u'comment_ptr': (
- 'django.db.models.fields.related.OneToOneField', [], {
- 'to': u"orm['utils.Comment']", 'unique': 'True', 'primary_key': 'True'}), 'is_useful': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'topic': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['forum.Topic']"})}, u'forum.topic': {
- 'Meta': {
- 'object_name': 'Topic'}, 'author': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'topics'", 'to': u"orm['auth.User']"}), 'forum': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['forum.Forum']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'is_locked': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'is_solved': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'is_sticky': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'last_message': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'last_message'", 'null': 'True', 'to': u"orm['forum.Post']"}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'auto_now_add': 'True', 'blank': 'True'}), 'subtitle': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200'}), 'tags': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'to': u"orm['utils.Tag']", 'null': 'True', 'blank': 'True'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'})}, u'forum.topicfollowed': {
- 'Meta': {
- 'object_name': 'TopicFollowed'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'topic': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['forum.Topic']"}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'topics_followed'", 'to': u"orm['auth.User']"})}, u'forum.topicread': {
- 'Meta': {
- 'object_name': 'TopicRead'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'post': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['forum.Post']"}), 'topic': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['forum.Topic']"}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'topics_read'", 'to': u"orm['auth.User']"})}, u'utils.comment': {
- 'Meta': {
- 'object_name': 'Comment'}, 'author': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'comments'", 'to': u"orm['auth.User']"}), 'dislike': (
- 'django.db.models.fields.IntegerField', [], {
- 'default': '0'}), 'editor': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'blank': 'True', 'related_name': "'comments-editor'", 'null': 'True', 'to': u"orm['auth.User']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'ip_address': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '15'}), 'is_visible': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'like': (
- 'django.db.models.fields.IntegerField', [], {
- 'default': '0'}), 'position': (
- 'django.db.models.fields.IntegerField', [], {}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'auto_now_add': 'True', 'blank': 'True'}), 'text': (
- 'django.db.models.fields.TextField', [], {}), 'text_hidden': (
- 'django.db.models.fields.CharField', [], {
- 'default': "''", 'max_length': '80'}), 'text_html': (
- 'django.db.models.fields.TextField', [], {}), 'update': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'})}, u'utils.tag': {
- 'Meta': {
- 'object_name': 'Tag'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '20'})}}
-
- complete_apps = ['forum']
diff --git a/zds/forum/migrations/0004_auto__add_field_topicfollowed_email.py b/zds/forum/migrations/0004_auto__add_field_topicfollowed_email.py
deleted file mode 100644
index 2443cb04f8..0000000000
--- a/zds/forum/migrations/0004_auto__add_field_topicfollowed_email.py
+++ /dev/null
@@ -1,135 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'TopicFollowed.email'
- db.add_column(u'forum_topicfollowed', 'email',
- self.gf('django.db.models.fields.BooleanField')(default=False),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'TopicFollowed.email'
- db.delete_column(u'forum_topicfollowed', 'email')
-
-
- models = {
- u'auth.group': {
- 'Meta': {'object_name': 'Group'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'auth.permission': {
- 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'forum.category': {
- 'Meta': {'object_name': 'Category'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'position': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '80'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'forum.forum': {
- 'Meta': {'object_name': 'Forum'},
- 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forum.Category']"}),
- 'group': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['auth.Group']", 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}),
- 'position_in_category': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '80'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'forum.post': {
- 'Meta': {'object_name': 'Post', '_ormbases': [u'utils.Comment']},
- u'comment_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['utils.Comment']", 'unique': 'True', 'primary_key': 'True'}),
- 'is_useful': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'topic': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forum.Topic']"})
- },
- u'forum.topic': {
- 'Meta': {'object_name': 'Topic'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'topics'", 'to': u"orm['auth.User']"}),
- 'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forum.Forum']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_solved': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_sticky': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_message': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_message'", 'null': 'True', 'to': u"orm['forum.Post']"}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['utils.Tag']", 'null': 'True', 'blank': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'forum.topicfollowed': {
- 'Meta': {'object_name': 'TopicFollowed'},
- 'email': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'topic': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forum.Topic']"}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'topics_followed'", 'to': u"orm['auth.User']"})
- },
- u'forum.topicread': {
- 'Meta': {'object_name': 'TopicRead'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'post': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forum.Post']"}),
- 'topic': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forum.Topic']"}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'topics_read'", 'to': u"orm['auth.User']"})
- },
- u'utils.comment': {
- 'Meta': {'object_name': 'Comment'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': u"orm['auth.User']"}),
- 'dislike': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'editor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments-editor'", 'null': 'True', 'to': u"orm['auth.User']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'ip_address': ('django.db.models.fields.CharField', [], {'max_length': '39'}),
- 'is_visible': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'like': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'position': ('django.db.models.fields.IntegerField', [], {}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {}),
- 'text_hidden': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '80'}),
- 'text_html': ('django.db.models.fields.TextField', [], {}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'utils.tag': {
- 'Meta': {'object_name': 'Tag'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '20'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '20'})
- }
- }
-
- complete_apps = ['forum']
\ No newline at end of file
diff --git a/zds/forum/migrations/0005_auto__add_index_forum_position_in_category__add_index_topicfollowed_em.py b/zds/forum/migrations/0005_auto__add_index_forum_position_in_category__add_index_topicfollowed_em.py
deleted file mode 100644
index f884b716c5..0000000000
--- a/zds/forum/migrations/0005_auto__add_index_forum_position_in_category__add_index_topicfollowed_em.py
+++ /dev/null
@@ -1,151 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding index on 'Forum', fields ['position_in_category']
- db.create_index(u'forum_forum', ['position_in_category'])
-
- # Adding index on 'TopicFollowed', fields ['email']
- db.create_index(u'forum_topicfollowed', ['email'])
-
- # Adding index on 'Topic', fields ['is_sticky']
- db.create_index(u'forum_topic', ['is_sticky'])
-
- # Adding index on 'Topic', fields ['is_solved']
- db.create_index(u'forum_topic', ['is_solved'])
-
-
- def backwards(self, orm):
- # Removing index on 'Topic', fields ['is_solved']
- db.delete_index(u'forum_topic', ['is_solved'])
-
- # Removing index on 'Topic', fields ['is_sticky']
- db.delete_index(u'forum_topic', ['is_sticky'])
-
- # Removing index on 'TopicFollowed', fields ['email']
- db.delete_index(u'forum_topicfollowed', ['email'])
-
- # Removing index on 'Forum', fields ['position_in_category']
- db.delete_index(u'forum_forum', ['position_in_category'])
-
-
- models = {
- u'auth.group': {
- 'Meta': {'object_name': 'Group'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'auth.permission': {
- 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'forum.category': {
- 'Meta': {'object_name': 'Category'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'position': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '80'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'forum.forum': {
- 'Meta': {'object_name': 'Forum'},
- 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forum.Category']"}),
- 'group': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['auth.Group']", 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}),
- 'position_in_category': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '80'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'forum.post': {
- 'Meta': {'object_name': 'Post', '_ormbases': [u'utils.Comment']},
- u'comment_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['utils.Comment']", 'unique': 'True', 'primary_key': 'True'}),
- 'is_useful': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'topic': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forum.Topic']"})
- },
- u'forum.topic': {
- 'Meta': {'object_name': 'Topic'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'topics'", 'to': u"orm['auth.User']"}),
- 'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forum.Forum']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_solved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
- 'is_sticky': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
- 'last_message': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_message'", 'null': 'True', 'to': u"orm['forum.Post']"}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['utils.Tag']", 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'forum.topicfollowed': {
- 'Meta': {'object_name': 'TopicFollowed'},
- 'email': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'topic': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forum.Topic']"}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'topics_followed'", 'to': u"orm['auth.User']"})
- },
- u'forum.topicread': {
- 'Meta': {'object_name': 'TopicRead'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'post': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forum.Post']"}),
- 'topic': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forum.Topic']"}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'topics_read'", 'to': u"orm['auth.User']"})
- },
- u'utils.comment': {
- 'Meta': {'object_name': 'Comment'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': u"orm['auth.User']"}),
- 'dislike': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'editor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments-editor'", 'null': 'True', 'to': u"orm['auth.User']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'ip_address': ('django.db.models.fields.CharField', [], {'max_length': '39'}),
- 'is_visible': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'like': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'position': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {}),
- 'text_hidden': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '80'}),
- 'text_html': ('django.db.models.fields.TextField', [], {}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'utils.tag': {
- 'Meta': {'object_name': 'Tag'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '20'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '20'})
- }
- }
-
- complete_apps = ['forum']
\ No newline at end of file
diff --git a/zds/forum/migrations/0006_auto__add_field_topic_key.py b/zds/forum/migrations/0006_auto__add_field_topic_key.py
deleted file mode 100644
index 538c5bf883..0000000000
--- a/zds/forum/migrations/0006_auto__add_field_topic_key.py
+++ /dev/null
@@ -1,136 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'Topic.key'
- db.add_column(u'forum_topic', 'key',
- self.gf('django.db.models.fields.IntegerField')(null=True, blank=True),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'Topic.key'
- db.delete_column(u'forum_topic', 'key')
-
-
- models = {
- u'auth.group': {
- 'Meta': {'object_name': 'Group'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'auth.permission': {
- 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'forum.category': {
- 'Meta': {'object_name': 'Category'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'position': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '80'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'forum.forum': {
- 'Meta': {'object_name': 'Forum'},
- 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forum.Category']"}),
- 'group': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['auth.Group']", 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}),
- 'position_in_category': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '80'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'forum.post': {
- 'Meta': {'object_name': 'Post', '_ormbases': [u'utils.Comment']},
- u'comment_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['utils.Comment']", 'unique': 'True', 'primary_key': 'True'}),
- 'is_useful': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'topic': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forum.Topic']"})
- },
- u'forum.topic': {
- 'Meta': {'object_name': 'Topic'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'topics'", 'to': u"orm['auth.User']"}),
- 'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forum.Forum']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_solved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
- 'is_sticky': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
- 'key': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'last_message': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_message'", 'null': 'True', 'to': u"orm['forum.Post']"}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['utils.Tag']", 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'forum.topicfollowed': {
- 'Meta': {'object_name': 'TopicFollowed'},
- 'email': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'topic': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forum.Topic']"}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'topics_followed'", 'to': u"orm['auth.User']"})
- },
- u'forum.topicread': {
- 'Meta': {'object_name': 'TopicRead'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'post': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forum.Post']"}),
- 'topic': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forum.Topic']"}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'topics_read'", 'to': u"orm['auth.User']"})
- },
- u'utils.comment': {
- 'Meta': {'object_name': 'Comment'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': u"orm['auth.User']"}),
- 'dislike': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'editor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments-editor'", 'null': 'True', 'to': u"orm['auth.User']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'ip_address': ('django.db.models.fields.CharField', [], {'max_length': '39'}),
- 'is_visible': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'like': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'position': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {}),
- 'text_hidden': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '80'}),
- 'text_html': ('django.db.models.fields.TextField', [], {}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'utils.tag': {
- 'Meta': {'object_name': 'Tag'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '20'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '20'})
- }
- }
-
- complete_apps = ['forum']
\ No newline at end of file
diff --git a/zds/forum/models.py b/zds/forum/models.py
index 318b0b29ac..3aa65c98bc 100644
--- a/zds/forum/models.py
+++ b/zds/forum/models.py
@@ -25,21 +25,33 @@ def sub_tag(g):
def image_path_forum(instance, filename):
- """Return path to an image."""
+ """
+ Return path to an image.
+ TODO: what is the usage of this function?
+ :param instance:
+ :param filename:
+ :return:
+ """
ext = filename.split('.')[-1]
filename = u'{}.{}'.format(str(uuid.uuid4()), string.lower(ext))
return os.path.join('forum/normal', str(instance.pk), filename)
class Category(models.Model):
-
- """A category, containing forums."""
+ """
+ A Category is a simple container for Forums.
+ There is no kind of logic in a Category. It simply here for Forum presentation in a predefined order.
+ """
class Meta:
verbose_name = 'Catégorie'
verbose_name_plural = 'Catégories'
+ ordering = ['position', 'title']
title = models.CharField('Titre', max_length=80)
position = models.IntegerField('Position', null=True, blank=True)
+ # Some category slugs are forbidden due to path collisions: Category path is `/forums/
` but some actions on
+ # forums have path like `/forums/`. Forbidden slugs are all top-level path in forum's `url.py` module.
+ # As Categories can only be managed by superadmin, this is purely declarative and there is no control on slug.
slug = models.SlugField(max_length=80,
unique=True,
help_text="Ces slugs vont provoquer des conflits "
@@ -55,26 +67,33 @@ def get_absolute_url(self):
kwargs={'cat_slug': self.slug})
def get_forums(self):
+ """
+ :return: All forums in category, ordered by forum's position in category
+ """
return Forum.objects.all()\
.filter(category=self)\
.order_by('position_in_category')
class Forum(models.Model):
-
- """A forum, containing topics."""
+ """
+ A Forum, containing Topics. It can be public or restricted to some groups.
+ """
class Meta:
verbose_name = 'Forum'
verbose_name_plural = 'Forums'
+ ordering = ['position_in_category', 'title']
title = models.CharField('Titre', max_length=80)
subtitle = models.CharField('Sous-titre', max_length=200)
+ # Groups authorized to read this forum. If no group is defined, the forum is public (and anyone can read it).
group = models.ManyToManyField(
Group,
verbose_name='Groupe autorisés (Aucun = public)',
null=True,
blank=True)
+ # TODO: A forum defines an image, but it doesn't seems to be used...
image = models.ImageField(upload_to=image_path_forum)
category = models.ForeignKey(Category, db_index=True, verbose_name='Catégorie')
@@ -84,7 +103,6 @@ class Meta:
slug = models.SlugField(max_length=80, unique=True)
def __unicode__(self):
- """Textual form of a forum."""
return self.title
def get_absolute_url(self):
@@ -93,22 +111,36 @@ def get_absolute_url(self):
'forum_slug': self.slug})
def get_topic_count(self):
- """Gets the number of threads in the forum."""
+ """
+ :return: the number of threads in the forum.
+ """
return Topic.objects.all().filter(forum__pk=self.pk).count()
def get_post_count(self):
- """Gets the number of posts for a forum."""
+ """
+ :return: the number of posts for a forum.
+ """
return Post.objects.filter(topic__forum=self).count()
+ # TODO: Rename this method for something clearer
def get_last_message(self):
- """Gets the last message on the forum, if there are any."""
+ """
+ :return: the last message on the forum, if there are any.
+ """
try:
return Post.objects.all().filter(topic__forum__pk=self.pk).order_by('-pubdate')[0]
except IndexError:
return None
def can_read(self, user):
- """Checks if the forum can be read by the user."""
+ """
+ Checks if an user can read current forum.
+ The forum can be read if:
+ - The forum has no access restriction (= no group), or
+ - The user is authenticated and he has access to groups defined for this forum.
+ :param user: the user to check the rights
+ :return: `True` if the user can read this forum, `False` otherwise.
+ """
if self.group.count() == 0:
return True
@@ -123,8 +155,14 @@ def can_read(self, user):
class Topic(models.Model):
+ """
+ A Topic is a thread of posts.
+ A topic has several states, witch are all independent:
+ - Solved: it was a question, and this question has been answered. The "solved" state is set at author's discretion.
+ - Locked: none can write on a locked topic.
+ - Sticky: sticky topics are displayed on top of topic lists (ex: on forum page).
+ """
- """A thread, containing posts."""
class Meta:
verbose_name = 'Sujet'
verbose_name_plural = 'Sujets'
@@ -151,12 +189,14 @@ class Meta:
blank=True,
db_index=True)
+ # This attribute is the link between beta of tutorials and topic of these beta.
+ # In Tuto logic we can found something like this: `Topic.objet.get(key=tutorial.pk)`
+ # TODO: 1. Use a better name, 2. maybe there can be a cleaner way to do this
key = models.IntegerField('cle', null=True, blank=True)
objects = TopicManager()
def __unicode__(self):
- """Textual form of a thread."""
return self.title
def get_absolute_url(self):
@@ -166,15 +206,24 @@ def get_absolute_url(self):
)
def get_post_count(self):
- """Return the number of posts in the topic."""
+ """
+ :return: the number of posts in the topic.
+ """
return Post.objects.filter(topic__pk=self.pk).count()
def get_last_post(self):
- """Gets the last post in the thread."""
- return Post.objects.select_related("author__profile").get(pk=self.last_message)
+ """
+ :return: the last post in the thread.
+ """
+ return self.last_message
def get_last_answer(self):
- """Gets the last answer in the thread, if any."""
+ """
+ Gets the last answer in this tread, if any.
+ Note the first post is not considered as an answer, therefore a topic with a single post (the 1st one) will
+ return `None`.
+ :return: the last answer in the thread, if any.
+ """
last_post = self.get_last_post()
if last_post == self.first_post():
@@ -183,7 +232,11 @@ def get_last_answer(self):
return last_post
def first_post(self):
- """Return the first post of a topic, written by topic's author."""
+ """
+ :return: the first post of a topic, written by topic's author.
+ """
+ # TODO: Force relation with author here is strange. Probably linked with the `get_last_answer` function that
+ # should compare PK and not objects
return Post.objects\
.filter(topic=self)\
.select_related("author")\
@@ -191,6 +244,11 @@ def first_post(self):
.first()
def add_tags(self, tag_collection):
+ """
+ Add all tags contained in `tag_collection` to this topic.
+ If a tag is unknown, it is added to the system.
+ :param tag_collection: A collection of tags.
+ """
for tag in tag_collection:
tag_title = smart_text(tag.strip().lower())
current_tag = Tag.objects.filter(title=tag_title).first()
@@ -202,11 +260,18 @@ def add_tags(self, tag_collection):
self.save()
def get_followers_by_email(self):
- """Return set on followers by email"""
+ """
+ :return: the set of users that follows this topic by email.
+ """
return TopicFollowed.objects.filter(topic=self, email=True).select_related("user")
def last_read_post(self):
- """Return the last post the user has read."""
+ """
+ Returns the last post the current user has read in this topic.
+ If it has never read this topic, returns the first post.
+ Used in "last read post" balloon (base.html line 91).
+ :return: the last post the user has read.
+ """
try:
return TopicRead.objects\
.select_related()\
@@ -216,7 +281,13 @@ def last_read_post(self):
return self.first_post()
def first_unread_post(self):
- """Return the first post the user has unread."""
+ """
+ Returns the first post of this topics the current user has never read, or the first post if it has never read
+ this topic.
+ Used in notification menu.
+ :return: The first unread post for this topic and this user.
+ """
+ # TODO: Why 2 nearly-identical functions? What is the functional need of these 2 things?
try:
last_post = TopicRead.objects\
.filter(topic=self, user=get_current_user())\
@@ -231,10 +302,10 @@ def first_unread_post(self):
return self.first_post()
def is_followed(self, user=None):
- """Check if the topic is currently followed by the user.
-
- This method uses the TopicFollowed objects.
-
+ """
+ Checks if the user follows this topic.
+ :param user: An user. If undefined, the current user is used.
+ :return: `True` if the user follows this topic, `False` otherwise.
"""
if user is None:
user = get_current_user()
@@ -242,10 +313,10 @@ def is_followed(self, user=None):
return TopicFollowed.objects.filter(topic=self, user=user).exists()
def is_email_followed(self, user=None):
- """Check if the topic is currently email followed by the user.
-
- This method uses the TopicFollowed objects.
-
+ """
+ Checks if the user follows this topic by email.
+ :param user: An user. If undefined, the current user is used.
+ :return: `True` if the user follows this topic by email, `False` otherwise.
"""
if user is None:
user = get_current_user()
@@ -257,14 +328,13 @@ def is_email_followed(self, user=None):
return True
def antispam(self, user=None):
- """Check if the user is allowed to post in a topic according to the
- SPAM_LIMIT_SECONDS value.
-
- If user shouldn't be able to post, then antispam is activated
- and this method returns True. Otherwise time elapsed between
- user's last post and now is enough, and the method will return
- False.
-
+ """
+ Check if the user is allowed to post in a topic according to the `ZDS_APP['forum']['spam_limit_seconds']` value.
+ The user can always post if someone else has posted last.
+ If the user is the last poster and there is less than `ZDS_APP['forum']['spam_limit_seconds']` since the last
+ post, the anti-spam is active and the user cannot post.
+ :param user: An user. If undefined, the current user is used.
+ :return: `True` if the anti-spam is active (user can't post), `False` otherwise.
"""
if user is None:
user = get_current_user()
@@ -287,18 +357,23 @@ def never_read(self):
class Post(Comment):
-
- """A forum post written by an user."""
+ """
+ A forum post written by an user.
+ A post can be marked as useful: topic's author (or admin) can declare any topic as "useful", and this post is
+ displayed as is on front.
+ """
topic = models.ForeignKey(Topic, verbose_name='Sujet', db_index=True)
is_useful = models.BooleanField('Est utile', default=False)
def __unicode__(self):
- """Textual form of a post."""
return u''.format(self.topic, self.pk)
def get_absolute_url(self):
+ """
+ :return: the absolute URL for this post, including page in the topic.
+ """
page = int(ceil(float(self.position) / settings.ZDS_APP['forum']['posts_per_page']))
return '{0}?page={1}#p{2}'.format(
@@ -308,17 +383,15 @@ def get_absolute_url(self):
class TopicRead(models.Model):
-
- """Small model which keeps track of the user viewing topics.
-
- It remembers the topic he looked and what was the last Post at this
- time.
-
+ """
+ This model tracks the last post read in a topic by a user.
+ Technically it is a simple joint [user, topic, last read post].
"""
class Meta:
verbose_name = 'Sujet lu'
verbose_name_plural = 'Sujets lus'
+ # TODO: ça a l'air d'être OK en base, mais ne devrait-il pas y avoir une contrainte unique sur (topic, user) ?
topic = models.ForeignKey(Topic, db_index=True)
post = models.ForeignKey(Post, db_index=True)
user = models.ForeignKey(User, related_name='topics_read', db_index=True)
@@ -330,12 +403,10 @@ def __unicode__(self):
class TopicFollowed(models.Model):
-
- """Small model which keeps track of the topics followed by an user.
-
- If an instance of this model is stored with an user and topic
- instance, that means that this user is following this topic.
-
+ """
+ This model tracks which user follows which topic.
+ It serves only to manual topic following.
+ This model also indicates if the topic is followed by email.
"""
class Meta:
verbose_name = 'Sujet suivi'
@@ -351,8 +422,15 @@ def __unicode__(self):
def never_read(topic, user=None):
- """Check if a topic has been read by an user since it last post was
- added."""
+ """
+ Check if the user has read the **last post** of the topic.
+ Note if the user has already read the topic but not the last post, it will consider it has never read the topic...
+ Technically this is done by check if there is a `TopicRead` for the topic, its last post and the user.
+ :param topic: A topic
+ :param user: A user. If undefined, the current user is used.
+ :return:
+ """
+ # TODO: cette méthode est très mal nommée en plus d'avoir un nom "booléen négatif" !
if user is None:
user = get_current_user()
@@ -361,8 +439,12 @@ def never_read(topic, user=None):
def mark_read(topic):
- """Mark a topic as read for the user."""
+ """
+ Mark the last message of a topic as read for the current user.
+ :param topic: A topic.
+ """
u = get_current_user()
+ # TODO: voilà entre autres pourquoi il devrait y avoir une contrainte unique sur (topic, user) sur TopicRead.
t = TopicRead.objects.filter(topic=topic, user=u).first()
if t is None:
t = TopicRead(post=topic.last_message, topic=topic, user=u)
@@ -372,7 +454,12 @@ def mark_read(topic):
def follow(topic, user=None):
- """Toggle following of a topic for an user."""
+ """
+ Toggle following of a topic for an user.
+ :param topic: A topic.
+ :param user: A user. If undefined, the current user is used.
+ :return: `True` if the topic is now followed, `False` if is has been un-followed.
+ """
ret = None
if user is None:
user = get_current_user()
@@ -399,7 +486,12 @@ def follow(topic, user=None):
def follow_by_email(topic, user=None):
- """Toggle following of a topic for an user."""
+ """
+ Toggle following by email of a topic for an user.
+ :param topic: A topic.
+ :param user: A user. If undefined, the current user is used.
+ :return: `True` if the topic is now followed, `False` if is has been un-followed.
+ """
ret = None
if user is None:
user = get_current_user()
@@ -429,6 +521,7 @@ def follow_by_email(topic, user=None):
def get_last_topics(user):
"""Returns the 5 very last topics."""
+ # TODO semble inutilisé (et peu efficace dans la manière de faire)
topics = Topic.objects.all().order_by('-last_message__pubdate')
tops = []
@@ -443,7 +536,14 @@ def get_last_topics(user):
def get_topics(forum_pk, is_sticky, filter=None):
- """Get topics according to parameters."""
+ """
+ Get topics for a forum.
+ The optional filter allows to retrieve only solved, unsolved or "non-answered" (i.e. with only the 1st post) topics.
+ :param forum_pk: the primary key of forum
+ :param is_sticky: indicates if the sticky topics must or must not be retrieved
+ :param filter: optional filter to retrieve only specific topics.
+ :return:
+ """
if filter == 'solve':
topics = Topic.objects.filter(forum__pk=forum_pk, is_sticky=is_sticky, is_solved=True)
diff --git a/zds/forum/search_indexes.py b/zds/forum/search_indexes.py
index 8097cd819d..d59dce4efa 100644
--- a/zds/forum/search_indexes.py
+++ b/zds/forum/search_indexes.py
@@ -1,11 +1,16 @@
# coding: utf-8
+"""
+This package contains classes and methods to allow forums to be indexed
+"""
+
from haystack import indexes
from zds.forum.models import Topic, Post
class TopicIndex(indexes.SearchIndex, indexes.Indexable):
+ """Indexes topic data"""
text = indexes.CharField(document=True, use_template=True)
title = indexes.CharField(model_attr='title')
subtitle = indexes.CharField(model_attr='subtitle')
@@ -17,6 +22,7 @@ def get_model(self):
class PostIndex(indexes.SearchIndex, indexes.Indexable):
+ """Indexes Post data"""
text = indexes.CharField(document=True, use_template=True)
txt = indexes.CharField(model_attr='text')
author = indexes.CharField(model_attr='author')
diff --git a/zds/forum/views.py b/zds/forum/views.py
index d4428b86cf..27e2040ba1 100644
--- a/zds/forum/views.py
+++ b/zds/forum/views.py
@@ -37,7 +37,9 @@
def index(request):
- """Display the category list with all their forums."""
+ """
+ The forum index. Displays the category list with all their forums the current user can read.
+ """
categories = top_categories(request.user)
@@ -48,7 +50,12 @@ def index(request):
def details(request, cat_slug, forum_slug):
- """Display the given forum and all its topics."""
+ """
+ Displays a forum with all its topic, if the current use is allowed to read it.
+ The topic list is paginated (`settings.ZDS_APP['forum']['topics_per_page']` topics per page) and can be filtered.
+ :param cat_slug: As a forum slug is unique through the database, this is unused.
+ :param forum_slug: The slug of the forum to display.
+ """
forum = get_object_or_404(Forum, slug=forum_slug)
if not forum.can_read(request.user):
@@ -86,7 +93,10 @@ def details(request, cat_slug, forum_slug):
def cat_details(request, cat_slug):
- """Display the forums belonging to the given category."""
+ """
+ Displays a category and all its forums the current user can read.
+ :param cat_slug: The slug of the category to display.
+ """
category = get_object_or_404(Category, slug=cat_slug)
@@ -111,7 +121,15 @@ def cat_details(request, cat_slug):
def topic(request, topic_pk, topic_slug):
- """Display a thread and its posts using a pager."""
+ """
+ Displays a topic (if the user can read it) and all its posts, paginated with
+ `settings.ZDS_APP['forum']['posts_per_page']` posts per page.
+ If the page to display is not the first one, the last post of the previous page is displayed as the first post of
+ the current page.
+ :param topic_pk: The primary key of the topic to display
+ :param topic_slug: The slug of the topic to display. If the slug doesn't match the topic slug, the user is
+ redirected to the proper topic URL.
+ """
topic = get_object_or_404(Topic, pk=topic_pk)
if not topic.forum.can_read(request.user):
@@ -190,6 +208,18 @@ def topic(request, topic_pk, topic_slug):
def get_tag_by_title(title):
+ """
+ Extract tags from title.
+ In a title, tags can be set this way:
+ > [Tag 1][Tag 2] There is the real title
+ Rules to detect tags:
+ - Tags are enclosed in square brackets. This allows multi-word tags instead of hashtags.
+ - Tags can embed square brackets: [Tag] is a valid tag and must be written [[Tag]] in the raw title
+ - All tags must be declared at the beginning of the title. Example: _"Title [tag]"_ will not create a tag.
+ - Tags and title correctness (example: empty tag/title detection) is **not** checked here
+ :param title: The raw title
+ :return: A tuple: (the tag list, the title without the tags).
+ """
nb_bracket = 0
current_tag = u""
current_title = u""
@@ -212,7 +242,7 @@ def get_tag_by_title(title):
elif current_tag.strip() != u"" and nb_bracket > 0:
current_tag = current_tag + char
- elif ((char != u"[" and char.strip() != "") or not continue_parsing_tags):
+ elif (char != u"[" and char.strip() != "") or not continue_parsing_tags:
continue_parsing_tags = False
current_title = current_title + char
title = current_title
@@ -227,7 +257,9 @@ def get_tag_by_title(title):
@login_required
@transaction.atomic
def new(request):
- """Creates a new topic in a forum."""
+ """
+ Creates a new topic in a forum.
+ """
try:
forum_pk = int(request.GET["forum"])
@@ -302,8 +334,11 @@ def new(request):
@require_POST
@transaction.atomic
def solve_alert(request):
-
- # only staff can move topic
+ """
+ Solves an alert (i.e. delete it from alert list) and sends an email to the user that created the alert, if the
+ resolver leaves a comment.
+ This can only be done by staff.
+ """
if not request.user.has_perm("forum.change_post"):
raise PermissionDenied
@@ -344,8 +379,10 @@ def solve_alert(request):
@require_POST
@transaction.atomic
def move_topic(request):
-
- # only staff can move topic
+ """
+ Moves a topic to another forum.
+ This can only be done by staff.
+ """
if not request.user.has_perm("forum.change_topic"):
raise PermissionDenied
@@ -361,8 +398,8 @@ def move_topic(request):
topic.forum = forum
topic.save()
- # unfollow user auth
-
+ # If the topic is moved in a restricted forum, users that cannot read this topic any more un-follow it.
+ # This avoids unreachable notifications.
followers = TopicFollowed.objects.filter(topic=topic)
for follower in followers:
if not forum.can_read(follower.user):
@@ -378,7 +415,9 @@ def move_topic(request):
@login_required
@require_POST
def edit(request):
- """Edit the given topic."""
+ """
+ Edit the given topic metadata: follow, follow by email, solved, locked, sticky.
+ """
try:
topic_pk = request.POST['topic']
@@ -424,6 +463,7 @@ def edit(request):
else:
g_topic.is_sticky = False
messages.success(request, _(u'Le sujet « {0} » n\'est désormais plus épinglé.').format(g_topic.title))
+ # TODO: Doublon avec "move_topic" ?
if "move" in data:
try:
forum_pk = int(request.POST["move_target"])
@@ -447,7 +487,13 @@ def edit(request):
@login_required
@transaction.atomic
def answer(request):
- """Adds an answer from a user to a topic."""
+ """
+ Answers (= add a new post) to an existing topic.
+ This method also allows the user to preview its answer.
+ If there is at least one new answer since the beginning of post redaction, the system displays the updated topic and
+ asks the user if it wants to posts its answers as is or edit it before re-send it. This is done by sending the
+ "current" last post ID with in the new form post and check on submit if there is a new last post ID.
+ """
try:
topic_pk = int(request.GET["sujet"])
@@ -483,7 +529,7 @@ def answer(request):
data = request.POST
newpost = last_post_pk != int(data["last_post"])
- # Using the « preview button », the « more » button or new post
+ # Using the "preview button", the "more" button or new post
if "preview" in data or newpost:
form = PostForm(g_topic, request.user, initial={"text": data["text"]})
@@ -609,7 +655,11 @@ def answer(request):
@login_required
@transaction.atomic
def edit_post(request):
- """Edit the given user's post."""
+ """
+ Edit a post. Also allows to signal a message to the staff, hide a message (in code this is called "delete" it), show
+ it and allows the user to preview its edited message.
+ This displays a warning if a moderator edits someone else's post.
+ """
try:
post_pk = request.GET["message"]
@@ -767,7 +817,10 @@ def edit_post(request):
@login_required
@require_POST
def useful_post(request):
- """Marks a message as useful (for the OP)"""
+ """
+ Marks an answer as "useful".
+ Only the topic creator (or a staff member) can do this.
+ """
try:
post_pk = int(request.GET["message"])
@@ -798,7 +851,13 @@ def useful_post(request):
@can_write_and_read_now
@login_required
def unread_post(request):
- """Marks a message as unread """
+ """
+ Marks a post as "unread".
+ If the post is the first one, the whole topic is marked as "unread" - technically, the whole `TopicRead` entry is
+ removed.
+ If the post is not the first one, the topic is marked as "unread" starting this post - technically, the `TopicRead`
+ entry is updated or created.
+ """
try:
post_pk = int(request.GET["message"])
@@ -831,11 +890,17 @@ def unread_post(request):
return redirect(reverse("zds.forum.views.details", args=[post.topic.forum.category.slug, post.topic.forum.slug]))
+# TODO nécessite une transaction ?
@can_write_and_read_now
@login_required
@require_POST
def like_post(request):
- """Like a post."""
+ """
+ The current user likes the post, or stops to like it if it was already liked. A like replaces the eventual existing
+ dislike on this post.
+ As the "like/dislike" data is de-normalized for performance purposes, also this also updates the de-normalized data
+ at `Post` level.
+ """
try:
post_pk = int(request.GET["message"])
@@ -879,11 +944,17 @@ def like_post(request):
return redirect(post.get_absolute_url())
+# TODO nécessite une transaction ?
@can_write_and_read_now
@login_required
@require_POST
def dislike_post(request):
- """Dislike a post."""
+ """
+ The current user dislikes the post, or stops to dislike it if it was already liked. A dislike replaces the eventual
+ existing like on this post.
+ As the "like/dislike" data is de-normalized for performance purposes, also this also updates the de-normalized data
+ at `Post` level.
+ """
try:
post_pk = int(request.GET["message"])
@@ -926,8 +997,16 @@ def dislike_post(request):
return redirect(post.get_absolute_url())
+# TODO: PK AND slug -> one of them is probably useless
def find_topic_by_tag(request, tag_pk, tag_slug):
- """Finds all topics byg tag."""
+ """
+ Displays all topics with provided tag. Also handles a filter on "solved". Only the topics the user can read are
+ displayed.
+ The tag primary key and the tag slug must match, otherwise nothing will be found.
+ Topics found are displayed paginated with `settings.ZDS_APP['forum']['topics_per_page']` topics per page.
+ :param tag_pk: the primary key of the tag to find by
+ :param tag_slug: the slug of the tag to find by
+ """
tag = Tag.objects.filter(pk=tag_pk, slug=tag_slug).first()
if tag is None:
@@ -981,7 +1060,12 @@ def find_topic_by_tag(request, tag_pk, tag_slug):
def find_topic(request, user_pk):
- """Finds all topics of a user."""
+ """
+ Displays all topics created by the provided user, paginated with `settings.ZDS_APP['forum']['topics_per_page']`
+ topics per page.
+ Only the topics the current user can read are displayed.
+ :param user_pk: the user to find the topics.
+ """
displayed_user = get_object_or_404(User, pk=user_pk)
topics = \
@@ -1013,7 +1097,11 @@ def find_topic(request, user_pk):
def find_post(request, user_pk):
- """Finds all posts of a user."""
+ """
+ Displays all posts of a user, paginated with `settings.ZDS_APP['forum']['posts_per_page']` post per page.
+ Only the posts the current user can read are displayed.
+ :param user_pk: the user to find the posts.
+ """
displayed_user = get_object_or_404(User, pk=user_pk)
user = request.user
@@ -1054,7 +1142,11 @@ def find_post(request, user_pk):
@login_required
def followed_topics(request):
- followed_topics = request.user.get_profile().get_followed_topics()
+ """
+ Displays the followed topics fo the current user, with `settings.ZDS_APP['forum']['followed_topics_per_page']`
+ topics per page.
+ """
+ followed_topics = request.user.profile.get_followed_topics()
# Paginator
@@ -1076,10 +1168,12 @@ def followed_topics(request):
"nb": page})
+# TODO suggestions de recherche auto lors d'un nouveau topic, cf issues #99 et #580. Actuellement désactivées :(
def complete_topic(request):
if not request.GET.get('q', None):
return HttpResponse("{}", content_type='application/json')
+ # TODO: WTF "sqs" ?!
sqs = SearchQuerySet().filter(content=AutoQuery(request.GET.get('q'))).order_by('-pubdate').all()
suggestions = {}
diff --git a/zds/gallery/admin.py b/zds/gallery/admin.py
index a0c945df62..2d0d0758b2 100644
--- a/zds/gallery/admin.py
+++ b/zds/gallery/admin.py
@@ -2,9 +2,30 @@
from django.contrib import admin
-from .models import Gallery, Image, UserGallery
+from zds.gallery.models import Gallery, Image, UserGallery
-admin.site.register(Gallery)
-admin.site.register(Image)
-admin.site.register(UserGallery)
+class GalleryAdmin(admin.ModelAdmin):
+
+ """Representation of Gallery model in the admin interface."""
+
+ list_display = ('title', 'subtitle', 'pubdate', 'update')
+
+
+class ImageAdmin(admin.ModelAdmin):
+
+ """Representation of Image model in the admin interface."""
+
+ list_display = ('title', 'gallery', 'legend', 'pubdate', 'update')
+
+
+class UserGalleryAdmin(admin.ModelAdmin):
+
+ """Representation of UserGallery model in the admin interface."""
+
+ list_display = ('user', 'gallery', 'mode')
+
+
+admin.site.register(Gallery, GalleryAdmin)
+admin.site.register(Image, ImageAdmin)
+admin.site.register(UserGallery, UserGalleryAdmin)
diff --git a/zds/gallery/factories.py b/zds/gallery/factories.py
index 57bc46701f..ccf63c45c5 100644
--- a/zds/gallery/factories.py
+++ b/zds/gallery/factories.py
@@ -9,9 +9,9 @@
class ImageFactory(factory.DjangoModelFactory):
FACTORY_FOR = Image
- title = factory.Sequence(lambda n: u"titre de l\'image {0}".format(n))
+ title = factory.Sequence(u"titre de l\'image {0}".format)
slug = factory.LazyAttribute(lambda o: "{0}".format(slugify(o.title)))
- legend = factory.Sequence(lambda n: u"legende de l'image {0}".format(n))
+ legend = factory.Sequence(u"legende de l'image {0}".format)
physical = factory.django.ImageField(color='blue')
@classmethod
@@ -27,8 +27,8 @@ def _prepare(cls, create, **kwargs):
class GalleryFactory(factory.DjangoModelFactory):
FACTORY_FOR = Gallery
- title = factory.Sequence(lambda n: u"titre de la gallerie {0}".format(n))
- subtitle = factory.Sequence(lambda n: u"Sous-titre de la gallerie {0}".format(n))
+ title = factory.Sequence(u"titre de la gallerie {0}".format)
+ subtitle = factory.Sequence(u"Sous-titre de la gallerie {0}".format)
slug = factory.LazyAttribute(lambda o: "{0}".format(slugify(o.title)))
diff --git a/zds/gallery/forms.py b/zds/gallery/forms.py
index 3651b3c394..6ae9e040f7 100644
--- a/zds/gallery/forms.py
+++ b/zds/gallery/forms.py
@@ -14,23 +14,18 @@
from django.utils.translation import ugettext_lazy as _
-class GalleryForm(forms.Form):
- title = forms.CharField(
- label=_('Titre'),
- max_length=Gallery._meta.get_field('title').max_length,
- )
+class GalleryForm(forms.ModelForm):
- subtitle = forms.CharField(
- label=_('Sous-titre'),
- max_length=Gallery._meta.get_field('subtitle').max_length,
- required=False
- )
+ class Meta:
+ model = Gallery
+
+ fields = ['title', 'subtitle']
def __init__(self, *args, **kwargs):
super(GalleryForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_class = 'clearfix'
- self.helper.form_action = reverse('zds.gallery.views.new_gallery')
+ self.helper.form_action = reverse('gallery-new')
self.helper.form_method = 'post'
self.helper.layout = Layout(
@@ -55,6 +50,23 @@ def clean(self):
return cleaned_data
+class UpdateGalleryForm(GalleryForm):
+
+ def __init__(self, *args, **kwargs):
+ super(UpdateGalleryForm, self).__init__(*args, **kwargs)
+ self.helper = FormHelper()
+ self.helper.form_class = 'clearfix'
+ self.helper.form_method = 'post'
+
+ self.helper.layout = Layout(
+ Field('title'),
+ Field('subtitle'),
+ ButtonHolder(
+ StrictButton(_(u'Mettre à jour'), type='submit'),
+ ),
+ )
+
+
class UserGalleryForm(forms.Form):
user = forms.CharField(
label='',
@@ -105,18 +117,12 @@ def clean(self):
return cleaned_data
-class ImageForm(forms.Form):
- title = forms.CharField(
- label=_(u'Titre'),
- max_length=Image._meta.get_field('title').max_length,
- required=True,
- )
+class ImageForm(forms.ModelForm):
- legend = forms.CharField(
- label=_(u'Légende'),
- max_length=Image._meta.get_field('legend').max_length,
- required=False,
- )
+ class Meta:
+ model = Image
+
+ fields = ['title', 'legend']
physical = forms.ImageField(
label=_(u'Sélectionnez votre image'),
@@ -151,6 +157,27 @@ def clean(self):
return cleaned_data
+class UpdateImageForm(ImageForm):
+
+ def __init__(self, *args, **kwargs):
+ super(UpdateImageForm, self).__init__(*args, **kwargs)
+
+ self.fields['physical'].required = False
+
+ self.helper = FormHelper()
+ self.helper.form_class = 'clearfix'
+ self.helper.form_method = 'post'
+
+ self.helper.layout = Layout(
+ Field('title'),
+ Field('legend'),
+ Field('physical'),
+ ButtonHolder(
+ StrictButton(_(u'Mettre à jour'), type='submit'),
+ ),
+ )
+
+
class ArchiveImageForm(forms.Form):
file = forms.FileField(
label=_(u"Sélectionnez l'archive contenant les images à charger"),
@@ -187,27 +214,6 @@ def clean(self):
return cleaned_data
-class UpdateImageForm(ImageForm):
-
- def __init__(self, *args, **kwargs):
- super(UpdateImageForm, self).__init__(*args, **kwargs)
-
- self.fields['physical'].required = False
-
- self.helper = FormHelper()
- self.helper.form_class = 'clearfix'
- self.helper.form_method = 'post'
-
- self.helper.layout = Layout(
- Field('title'),
- Field('legend'),
- Field('physical'),
- ButtonHolder(
- StrictButton(_(u'Mettre à jour'), type='submit'),
- ),
- )
-
-
class ImageAsAvatarForm(forms.Form):
""""Form to add current image as avatar"""
diff --git a/zds/gallery/migrations/0001_initial.py b/zds/gallery/migrations/0001_initial.py
index d577beeb5b..f69e65f0eb 100644
--- a/zds/gallery/migrations/0001_initial.py
+++ b/zds/gallery/migrations/0001_initial.py
@@ -1,161 +1,65 @@
# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
+from __future__ import unicode_literals
+from django.db import models, migrations
+from django.conf import settings
+import easy_thumbnails.fields
+import zds.gallery.models
-class Migration(SchemaMigration):
- def forwards(self, orm):
- # Adding model 'UserGallery'
- db.create_table(
- u'gallery_usergallery', ((u'id', self.gf('django.db.models.fields.AutoField')(
- primary_key=True)), ('user', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['auth.User'])), ('gallery', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['gallery.Gallery'])), ('mode', self.gf('django.db.models.fields.CharField')(
- default='R', max_length=1)), ))
- db.send_create_signal(u'gallery', ['UserGallery'])
+class Migration(migrations.Migration):
- # Adding model 'Image'
- db.create_table(
- u'gallery_image', ((u'id', self.gf('django.db.models.fields.AutoField')(
- primary_key=True)), ('gallery', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['gallery.Gallery'])), ('title', self.gf('django.db.models.fields.CharField')(
- max_length=80, null=True, blank=True)), ('slug', self.gf('django.db.models.fields.SlugField')(
- max_length=80)), ('physical', self.gf('django.db.models.fields.files.ImageField')(
- max_length=100)), ('thumb', self.gf('django.db.models.fields.files.ImageField')(
- max_length=100, null=True, blank=True)), ('medium', self.gf('django.db.models.fields.files.ImageField')(
- max_length=100, null=True, blank=True)), ('legend', self.gf('django.db.models.fields.CharField')(
- max_length=80, null=True, blank=True)), ('pubdate', self.gf('django.db.models.fields.DateTimeField')(
- auto_now_add=True, blank=True)), ('update', self.gf('django.db.models.fields.DateTimeField')(
- null=True, blank=True)), ))
- db.send_create_signal(u'gallery', ['Image'])
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
- # Adding model 'Gallery'
- db.create_table(
- u'gallery_gallery', ((u'id', self.gf('django.db.models.fields.AutoField')(
- primary_key=True)), ('title', self.gf('django.db.models.fields.CharField')(
- max_length=80)), ('subtitle', self.gf('django.db.models.fields.CharField')(
- max_length=200)), ('slug', self.gf('django.db.models.fields.SlugField')(
- max_length=80)), ('pubdate', self.gf('django.db.models.fields.DateTimeField')(
- auto_now_add=True, blank=True)), ('update', self.gf('django.db.models.fields.DateTimeField')(
- null=True, blank=True)), ))
- db.send_create_signal(u'gallery', ['Gallery'])
-
- def backwards(self, orm):
- # Deleting model 'UserGallery'
- db.delete_table(u'gallery_usergallery')
-
- # Deleting model 'Image'
- db.delete_table(u'gallery_image')
-
- # Deleting model 'Gallery'
- db.delete_table(u'gallery_gallery')
-
- models = {
- u'auth.group': {
- 'Meta': {
- 'object_name': 'Group'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '80'}), 'permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})}, u'auth.permission': {
- 'Meta': {
- 'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, 'codename': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'content_type': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['contenttypes.ContentType']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '50'})}, u'auth.user': {
- 'Meta': {
- 'object_name': 'User'}, 'date_joined': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'email': (
- 'django.db.models.fields.EmailField', [], {
- 'max_length': '75', 'blank': 'True'}), 'first_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'groups': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'is_active': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'is_staff': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'is_superuser': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'last_login': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'last_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'password': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128'}), 'user_permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), 'username': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '30'})}, u'contenttypes.contenttype': {
- 'Meta': {
- 'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'model': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'})}, u'gallery.gallery': {
- 'Meta': {
- 'object_name': 'Gallery'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'auto_now_add': 'True', 'blank': 'True'}), 'slug': (
- 'django.db.models.fields.SlugField', [], {
- 'max_length': '80'}), 'subtitle': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'}), 'update': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'})}, u'gallery.image': {
- 'Meta': {
- 'object_name': 'Image'}, 'gallery': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['gallery.Gallery']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'legend': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80', 'null': 'True', 'blank': 'True'}), 'medium': (
- 'django.db.models.fields.files.ImageField', [], {
- 'max_length': '100', 'null': 'True', 'blank': 'True'}), 'physical': (
- 'django.db.models.fields.files.ImageField', [], {
- 'max_length': '100'}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'auto_now_add': 'True', 'blank': 'True'}), 'slug': (
- 'django.db.models.fields.SlugField', [], {
- 'max_length': '80'}), 'thumb': (
- 'django.db.models.fields.files.ImageField', [], {
- 'max_length': '100', 'null': 'True', 'blank': 'True'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80', 'null': 'True', 'blank': 'True'}), 'update': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'})}, u'gallery.usergallery': {
- 'Meta': {
- 'object_name': 'UserGallery'}, 'gallery': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['gallery.Gallery']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'mode': (
- 'django.db.models.fields.CharField', [], {
- 'default': "'R'", 'max_length': '1'}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['auth.User']"})}}
-
- complete_apps = ['gallery']
+ operations = [
+ migrations.CreateModel(
+ name='Gallery',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('title', models.CharField(max_length=80, verbose_name=b'Titre')),
+ ('subtitle', models.CharField(max_length=200, verbose_name=b'Sous titre')),
+ ('slug', models.SlugField(max_length=80)),
+ ('pubdate', models.DateTimeField(auto_now_add=True, verbose_name=b'Date de cr\xc3\xa9ation', db_index=True)),
+ ('update', models.DateTimeField(null=True, verbose_name=b'Date de modification', blank=True)),
+ ],
+ options={
+ 'verbose_name': 'Galerie',
+ 'verbose_name_plural': 'Galeries',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='Image',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('title', models.CharField(max_length=80, null=True, verbose_name=b'Titre', blank=True)),
+ ('slug', models.SlugField(max_length=80)),
+ ('physical', easy_thumbnails.fields.ThumbnailerImageField(upload_to=zds.gallery.models.image_path)),
+ ('legend', models.CharField(max_length=80, null=True, verbose_name=b'L\xc3\xa9gende', blank=True)),
+ ('pubdate', models.DateTimeField(auto_now_add=True, verbose_name=b'Date de cr\xc3\xa9ation', db_index=True)),
+ ('update', models.DateTimeField(null=True, verbose_name=b'Date de modification', blank=True)),
+ ('gallery', models.ForeignKey(verbose_name=b'Galerie', to='gallery.Gallery')),
+ ],
+ options={
+ 'verbose_name': 'Image',
+ 'verbose_name_plural': 'Images',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='UserGallery',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('mode', models.CharField(default=b'R', max_length=1, choices=[(b'R', b'Lecture'), (b'W', b'Ecriture')])),
+ ('gallery', models.ForeignKey(verbose_name=b'Galerie', to='gallery.Gallery')),
+ ('user', models.ForeignKey(verbose_name=b'Membre', to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'verbose_name': "Galeries de l'utilisateur",
+ 'verbose_name_plural': "Galeries de l'utilisateur",
+ },
+ bases=(models.Model,),
+ ),
+ ]
diff --git a/zds/gallery/migrations/0002_auto_20150409_2122.py b/zds/gallery/migrations/0002_auto_20150409_2122.py
new file mode 100644
index 0000000000..47606d3656
--- /dev/null
+++ b/zds/gallery/migrations/0002_auto_20150409_2122.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('gallery', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='gallery',
+ name='pubdate',
+ field=models.DateTimeField(auto_now_add=True, verbose_name='Date de cr\xe9ation', db_index=True),
+ preserve_default=True,
+ ),
+ migrations.AlterField(
+ model_name='gallery',
+ name='subtitle',
+ field=models.CharField(max_length=200, verbose_name='Sous titre', blank=True),
+ preserve_default=True,
+ ),
+ migrations.AlterField(
+ model_name='image',
+ name='legend',
+ field=models.CharField(max_length=80, null=True, verbose_name='L\xe9gende', blank=True),
+ preserve_default=True,
+ ),
+ migrations.AlterField(
+ model_name='image',
+ name='pubdate',
+ field=models.DateTimeField(auto_now_add=True, verbose_name='Date de cr\xe9ation', db_index=True),
+ preserve_default=True,
+ ),
+ migrations.AlterField(
+ model_name='image',
+ name='title',
+ field=models.CharField(default='', max_length=80, verbose_name='Titre'),
+ preserve_default=False,
+ ),
+ migrations.AlterField(
+ model_name='usergallery',
+ name='mode',
+ field=models.CharField(default=b'R', max_length=1, choices=[(b'R', 'Lecture'), (b'W', '\xc9criture')]),
+ preserve_default=True,
+ ),
+ ]
diff --git a/zds/gallery/migrations/0002_auto__add_index_image_pubdate__add_index_gallery_pubdate.py b/zds/gallery/migrations/0002_auto__add_index_image_pubdate__add_index_gallery_pubdate.py
deleted file mode 100644
index 8c29fb81bd..0000000000
--- a/zds/gallery/migrations/0002_auto__add_index_image_pubdate__add_index_gallery_pubdate.py
+++ /dev/null
@@ -1,94 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding index on 'Image', fields ['pubdate']
- db.create_index(u'gallery_image', ['pubdate'])
-
- # Adding index on 'Gallery', fields ['pubdate']
- db.create_index(u'gallery_gallery', ['pubdate'])
-
-
- def backwards(self, orm):
- # Removing index on 'Gallery', fields ['pubdate']
- db.delete_index(u'gallery_gallery', ['pubdate'])
-
- # Removing index on 'Image', fields ['pubdate']
- db.delete_index(u'gallery_image', ['pubdate'])
-
-
- models = {
- u'auth.group': {
- 'Meta': {'object_name': 'Group'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'auth.permission': {
- 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'gallery.gallery': {
- 'Meta': {'object_name': 'Gallery'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'gallery.image': {
- 'Meta': {'object_name': 'Image'},
- 'gallery': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gallery.Gallery']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'legend': ('django.db.models.fields.CharField', [], {'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'medium': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
- 'physical': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'thumb': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'gallery.usergallery': {
- 'Meta': {'object_name': 'UserGallery'},
- 'gallery': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gallery.Gallery']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'mode': ('django.db.models.fields.CharField', [], {'default': "'R'", 'max_length': '1'}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
- }
- }
-
- complete_apps = ['gallery']
\ No newline at end of file
diff --git a/zds/gallery/models.py b/zds/gallery/models.py
index 3e2524aa8c..cc30988a52 100644
--- a/zds/gallery/models.py
+++ b/zds/gallery/models.py
@@ -1,92 +1,138 @@
# coding: utf-8
import os
-import string
-import uuid
+from string import lower
+from uuid import uuid4
+
+from easy_thumbnails.fields import ThumbnailerImageField
-from django.conf import settings
-from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
+from django.contrib.auth.models import User
from django.db import models
from django.dispatch import receiver
-from easy_thumbnails.fields import ThumbnailerImageField
-from zds.settings import MEDIA_ROOT
+from django.utils.translation import ugettext as _
+
+from zds.settings import MEDIA_ROOT, MEDIA_URL
+
+# Models settings
GALLERY_WRITE = 'W'
GALLERY_READ = 'R'
def image_path(instance, filename):
- """Return path to an image."""
+ """
+ Get the local filesystem path of the uploaded image. This function is used in models.
+
+ :param instance: an instance of the model where the ImageField is defined
+ :type instance: str
+ :param filename: the filename that was originally given to the file
+ :type filename: str
+ :return: local filesystem path of the uploaded image
+ :rtype: unicode
+ """
ext = filename.split('.')[-1]
- filename = u'{}.{}'.format(str(uuid.uuid4()), string.lower(ext))
+ filename = u'{0}.{1}'.format(str(uuid4()), lower(ext))
+
return os.path.join('galleries', str(instance.gallery.pk), filename)
class UserGallery(models.Model):
+ """A gallery of images created by a user."""
class Meta:
- verbose_name = "Galeries de l'utilisateur"
- verbose_name_plural = "Galeries de l'utilisateur"
+ verbose_name = _(u'Galeries de l\'utilisateur')
+ verbose_name_plural = _(u'Galeries de l\'utilisateur')
- user = models.ForeignKey(User, verbose_name=('Membre'), db_index=True)
- gallery = models.ForeignKey('Gallery', verbose_name=('Galerie'), db_index=True)
MODE_CHOICES = (
- (GALLERY_READ, 'Lecture'),
- (GALLERY_WRITE, 'Ecriture')
+ (GALLERY_READ, _(u'Lecture')),
+ (GALLERY_WRITE, _(u'Écriture'))
)
+
+ user = models.ForeignKey(User, verbose_name=_(u'Membre'), db_index=True)
+ gallery = models.ForeignKey('Gallery', verbose_name=_(u'Galerie'), db_index=True)
mode = models.CharField(max_length=1, choices=MODE_CHOICES, default=GALLERY_READ)
def __unicode__(self):
- """Textual form of an User Gallery."""
- return u'Galerie "{0}" envoye par {1}'.format(self.gallery,
- self.user)
+ """Human-readable representation of the UserGallery model.
- def is_write(self):
+ :return: UserGalley description
+ :rtype: unicode
+ """
+ return _(u'Galerie « {0} » de {1}').format(self.gallery, self.user)
+
+ def can_write(self):
+ """Check if user can write in the gallery.
+
+ :return: True if user can write in the gallery
+ :rtype: bool
+ """
return self.mode == GALLERY_WRITE
- def is_read(self):
+ def can_read(self):
+ """Check if user can read in the gallery.
+
+ :return: True if user can read in the gallery
+ :rtype: bool
+ """
return self.mode == GALLERY_READ
def get_images(self):
- return Image.objects.all()\
- .filter(gallery=self.gallery)\
- .order_by('update')
+ """Get all images in the gallery.
- def get_gallery(self, user):
- return Gallery.objects.all()\
- .filter(pk=self.gallery.pk)
+ :return: all images in the gallery
+ :rtype: QuerySet
+ """
+ return Image.objects.filter(gallery=self.gallery).order_by('update').all()
class Image(models.Model):
+ """Represent an image in database"""
class Meta:
- verbose_name = "Image"
- verbose_name_plural = "Images"
+ verbose_name = _(u'Image')
+ verbose_name_plural = _(u'Images')
- gallery = models.ForeignKey('Gallery', verbose_name=('Galerie'), db_index=True)
- title = models.CharField('Titre', max_length=80, null=True, blank=True)
+ gallery = models.ForeignKey('Gallery', verbose_name=_(u'Galerie'), db_index=True)
+ title = models.CharField(_(u'Titre'), max_length=80)
slug = models.SlugField(max_length=80)
physical = ThumbnailerImageField(upload_to=image_path)
- legend = models.CharField('Légende', max_length=80, null=True, blank=True)
- pubdate = models.DateTimeField('Date de création', auto_now_add=True, db_index=True)
- update = models.DateTimeField(
- 'Date de modification', null=True, blank=True)
+ legend = models.CharField(_(u'Légende'), max_length=80, null=True, blank=True)
+ pubdate = models.DateTimeField(_(u'Date de création'), auto_now_add=True, db_index=True)
+ update = models.DateTimeField(_(u'Date de modification'), null=True, blank=True)
def __unicode__(self):
- """Textual form of an Image."""
+ """Human-readable representation of the Image model.
+
+ :return: Image slug
+ :rtype: unicode
+ """
return self.slug
def get_absolute_url(self):
- return '{0}/{1}'.format(settings.MEDIA_URL, self.physical)
+ """URL of a single Image.
+
+ :return: Image object URL
+ :rtype: str
+ """
+ return '{0}/{1}'.format(MEDIA_URL, self.physical)
def get_extension(self):
+ """Get the extension of an image (used in tests).
+
+ :return: the extension of the image
+ :rtype: unicode
+ """
return os.path.splitext(self.physical.name)[1][1:]
@receiver(models.signals.post_delete, sender=Image)
def auto_delete_file_on_delete(sender, instance, **kwargs):
- """Deletes image from filesystem when corresponding object is deleted."""
+ """Deletes image from filesystem when corresponding object is deleted.
+
+ :return: nothing
+ :rtype: None
+ """
if instance.physical:
if os.path.isfile(instance.physical.path):
os.remove(instance.physical.path)
@@ -95,46 +141,70 @@ def auto_delete_file_on_delete(sender, instance, **kwargs):
class Gallery(models.Model):
class Meta:
- verbose_name = "Galerie"
- verbose_name_plural = "Galeries"
+ verbose_name = _(u'Galerie')
+ verbose_name_plural = _(u'Galeries')
- title = models.CharField('Titre', max_length=80)
- subtitle = models.CharField('Sous titre', max_length=200)
+ title = models.CharField(_(u'Titre'), max_length=80)
+ subtitle = models.CharField(_(u'Sous titre'), max_length=200, blank=True)
slug = models.SlugField(max_length=80)
- pubdate = models.DateTimeField('Date de création', auto_now_add=True, db_index=True)
- update = models.DateTimeField(
- 'Date de modification', null=True, blank=True)
+ pubdate = models.DateTimeField(_(u'Date de création'), auto_now_add=True, db_index=True)
+ update = models.DateTimeField(_(u'Date de modification'), null=True, blank=True)
def __unicode__(self):
- """Textual form of an Gallery."""
+ """Human-readable representation of the Gallery model.
+
+ :return: Gallery title
+ :rtype: unicode
+ """
return self.title
def get_absolute_url(self):
- return reverse('zds.gallery.views.gallery_details',
- args=[self.pk, self.slug])
+ """URL of a single Gallery.
+
+ :return: Gallery object URL
+ :rtype: str
+ """
+ return reverse('gallery-details', args=[self.pk, self.slug])
def get_gallery_path(self):
- """get the physical path to this gallery root"""
+ """Get the filesystem path to this gallery root.
+
+ :return: filesystem path to this gallery root
+ :rtype: unicode
+ """
return os.path.join(MEDIA_ROOT, 'galleries', str(self.pk))
def get_linked_users(self):
- """get all the linked users for this gallery whatever their rights"""
- return UserGallery.objects.all()\
- .filter(gallery=self)
+ """Get all the linked users for this gallery whatever their rights
+
+ :return: all the linked users for this gallery
+ :rtype: QuerySet
+ """
+ return UserGallery.objects.filter(gallery=self).all()
def get_images(self):
- return Image.objects.all()\
- .filter(gallery=self)\
- .order_by('pubdate')
+ """Get all images in the gallery, ordered by publication date.
+
+ :return: all images in the gallery
+ :rtype: QuerySet
+ """
+ return Image.objects.filter(gallery=self).order_by('pubdate').all()
def get_last_image(self):
- return Image.objects.all()\
- .filter(gallery=self)\
- .last()
+ """Get the last image added in the gallery.
+
+ :return: last image added in the gallery
+ :rtype: Image object
+ """
+ return Image.objects.filter(gallery=self).last()
@receiver(models.signals.post_delete, sender=Gallery)
def auto_delete_image_on_delete(sender, instance, **kwargs):
- """Deletes image from filesystem when corresponding object is deleted."""
+ """Deletes image from filesystem when corresponding object is deleted.
+
+ :return: nothing
+ :rtype: None
+ """
for image in instance.get_images():
image.delete()
diff --git a/zds/gallery/tests/tests_forms.py b/zds/gallery/tests/tests_forms.py
index 50a56111bb..de4462fd02 100644
--- a/zds/gallery/tests/tests_forms.py
+++ b/zds/gallery/tests/tests_forms.py
@@ -67,7 +67,7 @@ def test_invalid_user_gallery_form_noexist_user(self):
class ImageFormTest(TestCase):
def test_valid_image_form(self):
- upload_file = open(os.path.join(settings.SITE_ROOT, 'fixtures', 'logo.png'), 'r')
+ upload_file = open(os.path.join(settings.BASE_DIR, 'fixtures', 'logo.png'), 'r')
data = {
'title': 'Test Image',
@@ -83,7 +83,7 @@ def test_valid_image_form(self):
upload_file.close()
def test_valid_archive_image_form(self):
- upload_file = open(os.path.join(settings.SITE_ROOT, 'fixtures', 'archive-gallery.zip'), 'r')
+ upload_file = open(os.path.join(settings.BASE_DIR, 'fixtures', 'archive-gallery.zip'), 'r')
data = {}
files = {
@@ -95,7 +95,7 @@ def test_valid_archive_image_form(self):
upload_file.close()
def test_empty_title_image_form(self):
- upload_file = open(os.path.join(settings.SITE_ROOT, 'fixtures', 'logo.png'), 'r')
+ upload_file = open(os.path.join(settings.BASE_DIR, 'fixtures', 'logo.png'), 'r')
data = {
'title': '',
@@ -125,7 +125,7 @@ def test_empty_pic_image_form(self):
self.assertFalse(form.is_valid())
def test_too_big_pic_image_form(self):
- upload_file = open(os.path.join(settings.SITE_ROOT, 'fixtures', 'image_test.jpg'), 'r')
+ upload_file = open(os.path.join(settings.BASE_DIR, 'fixtures', 'image_test.jpg'), 'r')
data = {
'title': 'Test Title',
@@ -141,7 +141,7 @@ def test_too_big_pic_image_form(self):
upload_file.close()
def test_bot_a_pic_image_form(self):
- upload_file = open(os.path.join(settings.SITE_ROOT, 'fixtures', 'forums.yaml'), 'r')
+ upload_file = open(os.path.join(settings.BASE_DIR, 'fixtures', 'forums.yaml'), 'r')
data = {
'title': 'Test Title',
@@ -157,7 +157,7 @@ def test_bot_a_pic_image_form(self):
upload_file.close()
def test_too_long_title_image_form(self):
- upload_file = open(os.path.join(settings.SITE_ROOT, 'fixtures', 'logo.png'), 'r')
+ upload_file = open(os.path.join(settings.BASE_DIR, 'fixtures', 'logo.png'), 'r')
data = {
'title': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam condimentum enim amet.',
@@ -171,7 +171,7 @@ def test_too_long_title_image_form(self):
upload_file.close()
def test_too_long_legend_image_form(self):
- upload_file = open(os.path.join(settings.SITE_ROOT, 'fixtures', 'logo.png'), 'r')
+ upload_file = open(os.path.join(settings.BASE_DIR, 'fixtures', 'logo.png'), 'r')
data = {
'title': 'Test Title',
diff --git a/zds/gallery/tests/tests_models.py b/zds/gallery/tests/tests_models.py
index b41a9d0ec2..a1d13e7557 100644
--- a/zds/gallery/tests/tests_models.py
+++ b/zds/gallery/tests/tests_models.py
@@ -4,6 +4,7 @@
from django.test import TestCase
from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext as _
from zds.gallery.factories import GalleryFactory, UserGalleryFactory, ImageFactory
from zds.member.factories import ProfileFactory
@@ -26,21 +27,21 @@ def tearDown(self):
self.gallery.delete()
def test_unicode(self):
- result = u'Galerie "{0}" envoye par {1}'.format(self.gallery, self.profile.user)
+ result = _(u'Galerie « {0} » de {1}').format(self.gallery, self.profile.user)
self.assertEqual(result, self.user_gallery.__unicode__())
- def test_is_write(self):
+ def test_can_write(self):
self.user_gallery.mode = 'W'
- self.assertTrue(self.user_gallery.is_write())
- self.assertFalse(self.user_gallery.is_read())
+ self.assertTrue(self.user_gallery.can_write())
+ self.assertFalse(self.user_gallery.can_read())
- def test_is_read(self):
+ def test_can_read(self):
self.user_gallery.mode = 'R'
- self.assertFalse(self.user_gallery.is_write())
- self.assertTrue(self.user_gallery.is_read())
+ self.assertFalse(self.user_gallery.can_write())
+ self.assertTrue(self.user_gallery.can_read())
def test_get_images(self):
self.assertEqual(2, len(self.user_gallery.get_images()))
@@ -48,12 +49,6 @@ def test_get_images(self):
self.assertEqual(self.image1, self.user_gallery.get_images()[0])
self.assertEqual(self.image2, self.user_gallery.get_images()[1])
- def test_get_gallery(self):
- gallery_results = self.user_gallery.get_gallery(self.profile.user)
-
- self.assertEqual(1, len(gallery_results))
- self.assertEqual(self.gallery, gallery_results[0])
-
class ImageTest(TestCase):
@@ -103,7 +98,7 @@ def test_unicode(self):
self.assertEqual(self.gallery.title, self.gallery.__unicode__())
def test_get_absolute_url(self):
- absolute_url = reverse('zds.gallery.views.gallery_details',
+ absolute_url = reverse('gallery-details',
args=[self.gallery.pk, self.gallery.slug])
self.assertEqual(absolute_url, self.gallery.get_absolute_url())
diff --git a/zds/gallery/tests/tests_views.py b/zds/gallery/tests/tests_views.py
index 3628fa2d56..ecec876ee5 100644
--- a/zds/gallery/tests/tests_views.py
+++ b/zds/gallery/tests/tests_views.py
@@ -16,10 +16,10 @@
class GalleryListViewTest(TestCase):
def test_denies_anonymous(self):
- response = self.client.get(reverse('zds.gallery.views.gallery_list'), follow=True)
+ response = self.client.get(reverse('gallery-list'), follow=True)
self.assertRedirects(response,
reverse('zds.member.views.login_view') +
- '?next=' + urllib.quote(reverse('zds.gallery.views.gallery_list'), ''))
+ '?next=' + urllib.quote(reverse('gallery-list'), ''))
def test_list_galeries_belong_to_member(self):
profile = ProfileFactory()
@@ -33,7 +33,7 @@ def test_list_galeries_belong_to_member(self):
)
self.assertTrue(login_check)
- response = self.client.get(reverse('zds.gallery.views.gallery_list'), follow=True)
+ response = self.client.get(reverse('gallery-list'), follow=True)
self.assertEqual(200, response.status_code)
self.assertEqual(1, len(response.context['galleries']))
@@ -47,17 +47,17 @@ def setUp(self):
self.profile2 = ProfileFactory()
def test_denies_anonymous(self):
- response = self.client.get(reverse('zds.gallery.views.gallery_details',
+ response = self.client.get(reverse('gallery-details',
args=['89', 'test-gallery']), follow=True)
self.assertRedirects(response,
reverse('zds.member.views.login_view') +
- '?next=' + urllib.quote(reverse('zds.gallery.views.gallery_details',
+ '?next=' + urllib.quote(reverse('gallery-details',
args=['89', 'test-gallery']), ''))
def test_fail_gallery_no_exist(self):
login_check = self.client.login(username=self.profile1.user.username, password='hostel77')
self.assertTrue(login_check)
- response = self.client.get(reverse('zds.gallery.views.gallery_details',
+ response = self.client.get(reverse('gallery-details',
args=['89', 'test-gallery']), follow=True)
self.assertEqual(404, response.status_code)
@@ -70,7 +70,7 @@ def test_fail_gallery_details_no_permission(self):
login_check = self.client.login(username=self.profile2.user.username, password='hostel77')
self.assertTrue(login_check)
- response = self.client.get(reverse('zds.gallery.views.gallery_details',
+ response = self.client.get(reverse('gallery-details',
args=[gallery.pk, gallery.slug]))
self.assertEqual(403, response.status_code)
@@ -82,7 +82,7 @@ def test_success_gallery_details_permission_authorized(self):
login_check = self.client.login(username=self.profile2.user.username, password='hostel77')
self.assertTrue(login_check)
- response = self.client.get(reverse('zds.gallery.views.gallery_details',
+ response = self.client.get(reverse('gallery-details',
args=[gallery.pk, gallery.slug]))
self.assertEqual(200, response.status_code)
@@ -93,24 +93,24 @@ def setUp(self):
self.profile1 = ProfileFactory()
def test_denies_anonymous(self):
- response = self.client.get(reverse('zds.gallery.views.new_gallery'), follow=True)
+ response = self.client.get(reverse('gallery-new'), follow=True)
self.assertRedirects(response,
reverse('zds.member.views.login_view') +
'?next=' +
- urllib.quote(reverse('zds.gallery.views.new_gallery'), ''))
+ urllib.quote(reverse('gallery-new'), ''))
- response = self.client.post(reverse('zds.gallery.views.new_gallery'), follow=True)
+ response = self.client.post(reverse('gallery-new'), follow=True)
self.assertRedirects(response,
reverse('zds.member.views.login_view') +
'?next=' +
- urllib.quote(reverse('zds.gallery.views.new_gallery'), ''))
+ urllib.quote(reverse('gallery-new'), ''))
def test_access_member(self):
""" just verify with get request that everythings is ok """
login_check = self.client.login(username=self.profile1.user.username, password='hostel77')
self.assertTrue(login_check)
- response = self.client.get(reverse('zds.gallery.views.new_gallery'))
+ response = self.client.get(reverse('gallery-new'))
self.assertEqual(200, response.status_code)
def test_fail_new_gallery_with_missing_params(self):
@@ -118,7 +118,7 @@ def test_fail_new_gallery_with_missing_params(self):
self.assertTrue(login_check)
self.assertEqual(0, Gallery.objects.count())
- response = self.client.post(reverse('zds.gallery.views.new_gallery'), {
+ response = self.client.post(reverse('gallery-new'), {
'subtitle': 'test'})
self.assertEqual(200, response.status_code)
self.assertTrue(response.context['form'].errors)
@@ -129,7 +129,7 @@ def test_success_new_gallery(self):
self.assertTrue(login_check)
self.assertEqual(0, Gallery.objects.count())
- response = self.client.post(reverse('zds.gallery.views.new_gallery'), {
+ response = self.client.post(reverse('gallery-new'), {
'title': 'test title', 'subtitle': 'test subtitle'}, follow=True)
self.assertEqual(200, response.status_code)
@@ -308,6 +308,85 @@ def test_success_add_user_write_permission(self):
self.assertEqual('W', permissions[0].mode)
+class EditGalleryTestView(TestCase):
+ def setUp(self):
+ self.profile1 = ProfileFactory()
+ self.profile2 = ProfileFactory()
+ self.profile3 = ProfileFactory()
+ self.gallery1 = GalleryFactory()
+ self.user_gallery1 = UserGalleryFactory(user=self.profile1.user, gallery=self.gallery1)
+ self.user_gallery3 = UserGalleryFactory(user=self.profile3.user, gallery=self.gallery1, mode='R')
+
+ def test_fail_member_no_permission_can_edit_gallery(self):
+ login_check = self.client.login(username=self.profile2.user.username, password='hostel77')
+ self.assertTrue(login_check)
+
+ given_title = 'Un nouveau titre'
+ given_subtile = 'Un nouveau sous-titre'
+
+ self.client.post(
+ reverse(
+ 'gallery-edit',
+ args=[self.gallery1.pk, self.gallery1.slug]
+ ),
+ {
+ 'title': given_title,
+ 'subtitle': given_subtile
+ },
+ follow=True
+ )
+
+ gallery = Gallery.objects.get(pk=self.gallery1.pk)
+ self.assertNotEqual(given_title, gallery.title)
+ self.assertNotEqual(given_subtile, gallery.subtitle)
+
+ def test_fail_member_read_permission_can_edit_gallery(self):
+ login_check = self.client.login(username=self.profile3.user.username, password='hostel77')
+ self.assertTrue(login_check)
+
+ given_title = 'Un nouveau titre'
+ given_subtile = 'Un nouveau sous-titre'
+
+ self.client.post(
+ reverse(
+ 'gallery-edit',
+ args=[self.gallery1.pk, self.gallery1.slug]
+ ),
+ {
+ 'title': given_title,
+ 'subtitle': given_subtile
+ },
+ follow=True
+ )
+
+ gallery = Gallery.objects.get(pk=self.gallery1.pk)
+ self.assertNotEqual(given_title, gallery.title)
+ self.assertNotEqual(given_subtile, gallery.subtitle)
+
+ def test_success_member_edit_gallery(self):
+ login_check = self.client.login(username=self.profile1.user.username, password='hostel77')
+ self.assertTrue(login_check)
+
+ given_title = 'Un nouveau titre'
+ given_subtile = 'Un nouveau sous-titre'
+
+ self.client.post(
+ reverse(
+ 'gallery-edit',
+ args=[self.gallery1.pk, self.gallery1.slug]
+ ),
+ {
+ 'title': given_title,
+ 'subtitle': given_subtile
+ },
+ follow=True
+ )
+
+ gallery = Gallery.objects.get(pk=self.gallery1.pk)
+ self.assertEqual(given_title, gallery.title)
+ self.assertEqual(given_subtile, gallery.subtitle)
+
+
class EditImageViewTest(TestCase):
def setUp(self):
@@ -325,24 +404,24 @@ def tearDown(self):
def test_denies_anonymous(self):
response = self.client.get(
reverse(
- 'zds.gallery.views.edit_image',
+ 'gallery-image-edit',
args=[15, 156]
),
follow=True
)
self.assertRedirects(response,
reverse('zds.member.views.login_view') +
- '?next=' + urllib.quote(reverse('zds.gallery.views.edit_image', args=[15, 156]), ''))
+ '?next=' + urllib.quote(reverse('gallery-image-edit', args=[15, 156]), ''))
def test_fail_member_no_permission_can_edit_image(self):
login_check = self.client.login(username=self.profile3.user.username, password='hostel77')
self.assertTrue(login_check)
- with open(os.path.join(settings.SITE_ROOT, 'fixtures', 'logo.png'), 'r') as fp:
+ with open(os.path.join(settings.BASE_DIR, 'fixtures', 'logo.png'), 'r') as fp:
self.client.post(
reverse(
- 'zds.gallery.views.edit_image',
+ 'gallery-image-edit',
args=[self.gallery.pk, self.image.pk]
),
{
@@ -362,11 +441,11 @@ def test_success_member_edit_image(self):
login_check = self.client.login(username=self.profile1.user.username, password='hostel77')
self.assertTrue(login_check)
- with open(os.path.join(settings.SITE_ROOT, 'fixtures', 'logo.png'), 'r') as fp:
+ with open(os.path.join(settings.BASE_DIR, 'fixtures', 'logo.png'), 'r') as fp:
response = self.client.post(
reverse(
- 'zds.gallery.views.edit_image',
+ 'gallery-image-edit',
args=[self.gallery.pk, self.image.pk]
),
{
@@ -387,7 +466,7 @@ def test_access_permission(self):
self.assertTrue(login_check)
response = self.client.get(reverse(
- 'zds.gallery.views.edit_image',
+ 'gallery-image-edit',
args=[self.gallery.pk, self.image.pk]
))
@@ -415,17 +494,17 @@ def tearDown(self):
self.image3.delete()
def test_denies_anonymous(self):
- response = self.client.get(reverse('zds.gallery.views.delete_image'), follow=True)
+ response = self.client.get(reverse('gallery-image-delete'), follow=True)
self.assertRedirects(response,
reverse('zds.member.views.login_view') +
- '?next=' + urllib.quote(reverse('zds.gallery.views.delete_image'), ''))
+ '?next=' + urllib.quote(reverse('gallery-image-delete'), ''))
def test_fail_modify_image_with_no_permission(self):
login_check = self.client.login(username=self.profile3.user.username, password='hostel77')
self.assertTrue(login_check)
response = self.client.post(
- reverse('zds.gallery.views.delete_image'),
+ reverse('gallery-image-delete'),
{
'gallery': self.gallery1.pk,
},
@@ -445,7 +524,7 @@ def test_delete_image_from_other_user(self):
self.assertTrue(login_check)
self.client.post(
- reverse('zds.gallery.views.delete_image'),
+ reverse('gallery-image-delete'),
{
'gallery': self.gallery1.pk,
'delete': '',
@@ -462,7 +541,7 @@ def test_success_delete_image_write_permission(self):
self.assertTrue(login_check)
response = self.client.post(
- reverse('zds.gallery.views.delete_image'),
+ reverse('gallery-image-delete'),
{
'gallery': self.gallery1.pk,
'delete': '',
@@ -479,7 +558,7 @@ def test_success_delete_list_images_write_permission(self):
self.assertTrue(login_check)
response = self.client.post(
- reverse('zds.gallery.views.delete_image'),
+ reverse('gallery-image-delete'),
{
'gallery': self.gallery1.pk,
'delete_multi': '',
@@ -497,7 +576,7 @@ def test_fail_delete_image_read_permission(self):
self.assertTrue(login_check)
response = self.client.post(
- reverse('zds.gallery.views.delete_image'),
+ reverse('gallery-image-delete'),
{
'gallery': self.gallery1.pk,
'delete': '',
@@ -521,20 +600,20 @@ def setUp(self):
self.user_gallery2 = UserGalleryFactory(user=self.profile2.user, gallery=self.gallery, mode='R')
def test_denies_anonymous(self):
- response = self.client.get(reverse('zds.gallery.views.new_image', args=[1]), follow=True)
+ response = self.client.get(reverse('gallery-image-new', args=[1]), follow=True)
self.assertRedirects(response,
reverse('zds.member.views.login_view') +
- '?next=' + urllib.quote(reverse('zds.gallery.views.new_image', args=[1]), ''))
+ '?next=' + urllib.quote(reverse('gallery-image-new', args=[1]), ''))
def test_success_new_image_write_permission(self):
login_check = self.client.login(username=self.profile1.user.username, password='hostel77')
self.assertTrue(login_check)
self.assertEqual(0, len(self.gallery.get_images()))
- with open(os.path.join(settings.SITE_ROOT, 'fixtures', 'logo.png'), 'r') as fp:
+ with open(os.path.join(settings.BASE_DIR, 'fixtures', 'logo.png'), 'r') as fp:
response = self.client.post(
reverse(
- 'zds.gallery.views.new_image',
+ 'gallery-image-new',
args=[self.gallery.pk]
),
{
@@ -555,10 +634,10 @@ def test_fail_new_image_with_read_permission(self):
self.assertTrue(login_check)
self.assertEqual(0, len(self.gallery.get_images()))
- with open(os.path.join(settings.SITE_ROOT, 'fixtures', 'logo.png'), 'r') as fp:
+ with open(os.path.join(settings.BASE_DIR, 'fixtures', 'logo.png'), 'r') as fp:
response = self.client.post(
reverse(
- 'zds.gallery.views.new_image',
+ 'gallery-image-new',
args=[self.gallery.pk]
),
{
@@ -578,10 +657,10 @@ def test_fail_new_image_with_no_permission(self):
self.assertTrue(login_check)
self.assertEqual(0, len(self.gallery.get_images()))
- with open(os.path.join(settings.SITE_ROOT, 'fixtures', 'logo.png'), 'r') as fp:
+ with open(os.path.join(settings.BASE_DIR, 'fixtures', 'logo.png'), 'r') as fp:
response = self.client.post(
reverse(
- 'zds.gallery.views.new_image',
+ 'gallery-image-new',
args=[self.gallery.pk]
),
{
@@ -600,10 +679,10 @@ def test_fail_gallery_not_exist(self):
login_check = self.client.login(username=self.profile1.user.username, password='hostel77')
self.assertTrue(login_check)
- with open(os.path.join(settings.SITE_ROOT, 'fixtures', 'logo.png'), 'r') as fp:
+ with open(os.path.join(settings.BASE_DIR, 'fixtures', 'logo.png'), 'r') as fp:
response = self.client.post(
reverse(
- 'zds.gallery.views.new_image',
+ 'gallery-image-new',
args=[156]
),
{
@@ -621,10 +700,10 @@ def test_import_images_in_gallery(self):
login_check = self.client.login(username=self.profile1.user.username, password='hostel77')
self.assertTrue(login_check)
- with open(os.path.join(settings.SITE_ROOT, 'fixtures', 'archive-gallery.zip'), 'r') as fp:
+ with open(os.path.join(settings.BASE_DIR, 'fixtures', 'archive-gallery.zip'), 'r') as fp:
response = self.client.post(
reverse(
- 'zds.gallery.views.import_image',
+ 'gallery-image-import',
args=[self.gallery.pk]
),
{
@@ -639,10 +718,10 @@ def test_denies_import_images_in_gallery(self):
login_check = self.client.login(username=self.profile2.user.username, password='hostel77')
self.assertTrue(login_check)
- with open(os.path.join(settings.SITE_ROOT, 'fixtures', 'archive-gallery.zip'), 'r') as fp:
+ with open(os.path.join(settings.BASE_DIR, 'fixtures', 'archive-gallery.zip'), 'r') as fp:
response = self.client.post(
reverse(
- 'zds.gallery.views.import_image',
+ 'gallery-image-import',
args=[self.gallery.pk]
),
{
diff --git a/zds/gallery/urls.py b/zds/gallery/urls.py
index 7a6b4dee3c..b8d2ddd2f0 100644
--- a/zds/gallery/urls.py
+++ b/zds/gallery/urls.py
@@ -2,25 +2,27 @@
from django.conf.urls import patterns, url
-from . import views
+from zds.gallery.views import NewGallery, NewImage, DeleteImages, EditImage, ImportImages, GalleryDetails, \
+ EditGallery, ListGallery
urlpatterns = patterns('',
- # Viewing a gallery
- url(r'^nouveau/$',
- 'zds.gallery.views.new_gallery'),
- url(r'^modifier/$',
- 'zds.gallery.views.modify_gallery'),
- url(r'^(?P\d+)/(?P.+)/$',
- 'zds.gallery.views.gallery_details'),
- url(r'^$',
- 'zds.gallery.views.gallery_list'),
- url(r'^image/ajouter/(?P\d+)/$',
- 'zds.gallery.views.new_image'),
- url(r'^image/modifier/$',
- 'zds.gallery.views.delete_image'),
- url(r'^image/editer/(?P\d+)/(?P\d+)/$',
- 'zds.gallery.views.edit_image'),
- url(r'^image/importer/(?P\d+)/$',
- 'zds.gallery.views.import_image'),
- )
+ # Add and edit a gallery
+ url(r'^nouveau/$', NewGallery.as_view(), name='gallery-new'),
+ url(r'^modifier/$', 'zds.gallery.views.modify_gallery'),
+
+ # Image operations
+ url(r'^image/ajouter/(?P\d+)/$', NewImage.as_view(), name='gallery-image-new'),
+ url(r'^image/supprimer/$', DeleteImages.as_view(), name='gallery-image-delete'),
+ url(r'^image/editer/(?P\d+)/(?P\d+)/$', EditImage.as_view(), name='gallery-image-edit'),
+ url(r'^image/importer/(?P\d+)/$', ImportImages.as_view(), name='gallery-image-import'),
+
+ # View a gallery
+ url(r'^(?P\d+)/(?P.+)/$', GalleryDetails.as_view(), name='gallery-details'),
+
+ # edit a gallery
+ url(r'^editer/(?P\d+)/(?P.+)/$', EditGallery.as_view(), name='gallery-edit'),
+
+ # Index
+ url(r'^$', ListGallery.as_view(), name='gallery-list'),
+)
diff --git a/zds/gallery/views.py b/zds/gallery/views.py
index 0a07c4f3d8..75192a163c 100644
--- a/zds/gallery/views.py
+++ b/zds/gallery/views.py
@@ -1,11 +1,15 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
+import tempfile
+
from datetime import datetime
+import time
+
from PIL import Image as ImagePIL
from django.conf import settings
from django.contrib import messages
-from django.http import Http404
+from django.http import Http404, HttpResponseRedirect
from django.views.decorators.http import require_POST
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
@@ -13,7 +17,7 @@
from django.core.urlresolvers import reverse
from django.shortcuts import redirect, get_object_or_404, render
from zds.gallery.forms import ArchiveImageForm, ImageForm, UpdateImageForm, \
- GalleryForm, UserGalleryForm, ImageAsAvatarForm
+ GalleryForm, UpdateGalleryForm, UserGalleryForm, ImageAsAvatarForm
from zds.gallery.models import UserGallery, Image, Gallery
from zds.member.decorator import can_write_and_read_now
from zds.utils import slugify
@@ -24,87 +28,143 @@
import zipfile
import shutil
import os
-from django.db import transaction
from django.utils.translation import ugettext as _
+from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView, FormView
+from django.utils.decorators import method_decorator
-@login_required
-def gallery_list(request):
- """Display the gallery list with all their images."""
- galleries = UserGallery.objects.all().filter(user=request.user)
- return render(request, "gallery/gallery/list.html",
- {"galleries": galleries})
+class ListGallery(ListView):
+ """Display the gallery list with all their images"""
+ object = UserGallery
+ template_name = "gallery/gallery/list.html"
+ context_object_name = "galleries"
-@login_required
-def gallery_details(request, gal_pk, gal_slug):
- """Gallery details."""
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(ListGallery, self).dispatch(*args, **kwargs)
+
+ def get_queryset(self):
+ return UserGallery.objects.all().filter(user=self.request.user)
+
+
+class NewGallery(CreateView):
+ """Create a new gallery"""
+
+ template_name = "gallery/gallery/new.html"
+ form_class = GalleryForm
+
+ @method_decorator(login_required)
+ @method_decorator(can_write_and_read_now)
+ def dispatch(self, *args, **kwargs):
+ return super(NewGallery, self).dispatch(*args, **kwargs)
+
+ def form_valid(self, form):
+ gallery = Gallery()
+ gallery.title = form.cleaned_data['title']
+ gallery.subtitle = form.cleaned_data['subtitle']
+ gallery.slug = slugify(form.cleaned_data['title'])
+ gallery.pubdate = datetime.now()
+ gallery.save()
+
+ # Attach user :
+ userg = UserGallery()
+ userg.gallery = gallery
+ userg.mode = "W"
+ userg.user = self.request.user
+ userg.save()
+
+ return HttpResponseRedirect(gallery.get_absolute_url())
+
+
+def ensure_user_access(gallery, user, can_write=False):
+ """
+ :param gallery: the gallery
+ :param user: user who want to access the gallery
+ :param can_write: check if the user has the writing access to the gallery
+ :return: the gallery of the user
+ :rtype: UserGallery
+ :raise PermissionDenied: if the user has not access or no write permission (if applicable)
+ """
- gal = get_object_or_404(Gallery, pk=gal_pk)
try:
- gal_mode = UserGallery.objects.get(gallery=gal, user=request.user)
- except:
+ user_gallery = UserGallery.objects.get(gallery=gallery, user=user)
+
+ if user_gallery:
+ if can_write and not user_gallery.can_write():
+ raise PermissionDenied
+ else:
+ raise PermissionDenied
+ except ObjectDoesNotExist: # the user_gallery does not exists
raise PermissionDenied
- images = gal.get_images()
- form = UserGalleryForm()
- return render(request, "gallery/gallery/details.html", {
- "gallery": gal,
- "gallery_mode": gal_mode,
- "images": images,
- "form": form,
- })
+ return user_gallery
-@can_write_and_read_now
-@login_required
-def new_gallery(request):
- """Creates a new gallery."""
+class GalleryDetails(DetailView):
+ """Gallery details"""
- if request.method == "POST":
- form = GalleryForm(request.POST)
- if form.is_valid():
- data = form.data
+ model = Gallery
+ template_name = "gallery/gallery/details.html"
+ context_object_name = "gallery"
- # Creating the gallery
+ @method_decorator(login_required)
+ def dispatch(self, *args, **kwargs):
+ return super(GalleryDetails, self).dispatch(*args, **kwargs)
- gal = Gallery()
- gal.title = data["title"]
- gal.subtitle = data["subtitle"]
- gal.slug = slugify(data["title"])
- gal.pubdate = datetime.now()
- gal.save()
+ def get_context_data(self, **kwargs):
+ context = super(GalleryDetails, self).get_context_data(**kwargs)
- # Attach user
+ context['gallery_mode'] = ensure_user_access(self.object, self.request.user)
+ context['images'] = self.object.get_images()
+ context['form'] = UserGalleryForm
- userg = UserGallery()
- userg.gallery = gal
- userg.mode = "W"
- userg.user = request.user
- userg.save()
- return redirect(gal.get_absolute_url())
- else:
- return render(request, "gallery/gallery/new.html", {"form": form})
- else:
- form = GalleryForm()
- return render(request, "gallery/gallery/new.html", {"form": form})
+ return context
+
+
+class EditGallery(UpdateView):
+ """Update gallery information"""
+
+ model = Gallery
+ template_name = "gallery/gallery/edit.html"
+ form_class = UpdateGalleryForm
+
+ @method_decorator(login_required)
+ @method_decorator(can_write_and_read_now)
+ def dispatch(self, *args, **kwargs):
+ return super(EditGallery, self).dispatch(*args, **kwargs)
+
+ def get_object(self, queryset=None):
+
+ pkey = self.kwargs.pop('pk', None)
+ slug = self.kwargs.pop('slug', None)
+ gallery = get_object_or_404(Gallery, pk=pkey, slug=slug)
+
+ ensure_user_access(gallery, self.request.user, can_write=True)
+
+ return gallery
+
+ def form_valid(self, form):
+
+ self.object.slug = slugify(form.cleaned_data['title'])
+ return super(EditGallery, self).form_valid(form)
@can_write_and_read_now
@require_POST
@login_required
def modify_gallery(request):
- """Modify gallery instance."""
+ """Modify gallery instance: delete galleries or add user to them"""
# Global actions
if "delete_multi" in request.POST:
- l = request.POST.getlist("items")
+ list_items = request.POST.getlist("items")
# Don't delete gallery when it's link to tutorial
free_galleries = []
- for g_pk in l:
+ for g_pk in list_items:
if Tutorial.objects.filter(gallery__pk=g_pk).exists():
gallery = Gallery.objects.get(pk=g_pk)
messages.error(
@@ -133,7 +193,7 @@ def modify_gallery(request):
# Finally delete the selected galleries
Gallery.objects.filter(pk__in=free_galleries).delete()
- return redirect(reverse("zds.gallery.views.gallery_list"))
+ return redirect(reverse("gallery-list"))
elif "adduser" in request.POST:
# Gallery-specific actions
@@ -177,230 +237,218 @@ def modify_gallery(request):
"images": gallery.get_images(),
"form": form,
})
- return redirect(gallery.get_absolute_url())
+ return redirect(gallery.get_absolute_url())
-@login_required
-@can_write_and_read_now
-def edit_image(request, gal_pk, img_pk):
+class GalleryMixin(object):
+ """Mixin that ensure the access to the gallery and fill context data properly"""
+
+ can_write = False # if `True`, check for user write access
+
+ def get_context_data(self, **kwargs):
+ context = super(GalleryMixin, self).get_context_data(**kwargs)
+ pk_gallery = self.kwargs.pop('pk_gallery', None)
+
+ gallery = get_object_or_404(Gallery, pk=pk_gallery)
+
+ user_gallery = ensure_user_access(gallery, self.request.user, can_write=self.can_write)
+
+ context['gallery'] = gallery
+ context['gallery_mode'] = user_gallery
+
+ return context
+
+
+class NewImage(GalleryMixin, CreateView):
+ """Creates a new image."""
+
+ form_class = ImageForm
+ template_name = 'gallery/image/new.html'
+ can_write = True # only allowed users can insert images
+
+ @method_decorator(login_required)
+ @method_decorator(can_write_and_read_now)
+ def dispatch(self, *args, **kwargs):
+ return super(NewImage, self).dispatch(*args, **kwargs)
+
+ def form_valid(self, form):
+
+ context = self.get_context_data(**self.kwargs)
+
+ img = Image()
+ img.gallery = context['gallery']
+ img.title = form.cleaned_data['title']
+
+ if form.cleaned_data['legend'] and form.cleaned_data['legend'] != '':
+ img.legend = form.cleaned_data['legend']
+ else:
+ img.legend = img.title
+
+ img.physical = self.request.FILES['physical']
+ img.pubdate = datetime.now()
+ img.save()
+
+ return redirect(reverse("gallery-image-edit", args=[img.gallery.pk, img.pk]))
+
+
+class EditImage(GalleryMixin, UpdateView):
"""Edit or view an existing image."""
- gal = get_object_or_404(Gallery, pk=gal_pk)
- img = get_object_or_404(Image, pk=img_pk)
+ model = Image
+ form_class = UpdateImageForm
+ template_name = "gallery/image/edit.html"
- # Check if user can edit image
- try:
- gal_mode = UserGallery.objects.get(user=request.user, gallery=gal)
- assert gal_mode is not None
- if not gal_mode.is_write() and request.method != "GET":
+ @method_decorator(login_required)
+ @method_decorator(can_write_and_read_now)
+ def dispatch(self, *args, **kwargs):
+ return super(EditImage, self).dispatch(*args, **kwargs)
+
+ def get_object(self, queryset=None):
+ pkey = self.kwargs.pop('pk', None)
+ return get_object_or_404(Image, pk=pkey)
+
+ def get_context_data(self, **kwargs):
+ context = super(EditImage, self).get_context_data(**kwargs)
+
+ context['as_avatar_form'] = ImageAsAvatarForm()
+
+ return context
+
+ def form_valid(self, form):
+ self.can_write = True # only allowed users can change images
+ context = self.get_context_data(**self.kwargs)
+ img = self.object
+ gallery = context['gallery']
+
+ if img.gallery != gallery:
raise PermissionDenied
- except (AssertionError, ObjectDoesNotExist):
- raise PermissionDenied
- # Check if the image belongs to the gallery
- if img.gallery != gal:
- raise PermissionDenied
+ can_change = True
- if request.method == "POST":
- form = UpdateImageForm(request.POST, request.FILES)
- if form.is_valid():
- if "physical" in request.FILES:
- if request.FILES["physical"].size > settings.ZDS_APP['gallery']['image_max_size']:
- messages.error(request, _(u"Votre image est beaucoup trop lourde, "
- u"réduisez sa taille à moins de {} "
- u"Kio "
- u"avant de l'envoyer.").format(
- str(settings.ZDS_APP['gallery']['image_max_size'] / 1024)))
- else:
- img.title = request.POST["title"]
- img.legend = request.POST["legend"]
- img.physical = request.FILES["physical"]
- img.slug = slugify(request.FILES["physical"])
- img.update = datetime.now()
- img.save()
- # Redirect to the newly uploaded image edit page after POST
- return redirect(reverse("zds.gallery.views.edit_image", args=[gal.pk, img.pk]))
+ if 'physical' in self.request.FILES: # the user request to change the image
+ if self.request.FILES["physical"].size > settings.ZDS_APP['gallery']['image_max_size']:
+ messages.error(
+ self.request,
+ _(u"Votre image est beaucoup trop lourde, réduisez sa taille à moins de {:.0f} "
+ u"Kio avant de l'envoyer.").format(
+ settings.ZDS_APP['gallery']['image_max_size'] / 1024))
+
+ can_change = False
else:
- img.title = request.POST["title"]
- img.legend = request.POST["legend"]
- img.update = datetime.now()
- img.save()
- # Redirect to the newly uploaded image edit page after POST
- return redirect(reverse("zds.gallery.views.edit_image", args=[gal.pk, img.pk]))
-
- else:
- form = UpdateImageForm(initial={
- "title": img.title,
- "legend": img.legend,
- "physical": img.physical,
- "new_image": False,
- })
-
- as_avatar_form = ImageAsAvatarForm()
- return render(
- request,
- "gallery/image/edit.html", {
- "form": form,
- "gallery_mode": gal_mode,
- "as_avatar_form": as_avatar_form,
- "gallery": gal,
- "image": img
- })
+ img.physical = self.request.FILES["physical"]
+ img.slug = slugify(self.request.FILES["physical"])
+ if can_change:
+ img.title = form.cleaned_data['title']
+ img.legend = form.cleaned_data['legend']
+ img.update = datetime.now()
+ img.save()
-@can_write_and_read_now
-@login_required
-@require_POST
-def delete_image(request):
+ return redirect(reverse("gallery-image-edit", args=[img.gallery.pk, img.pk]))
- try:
- gal_pk = request.POST["gallery"]
- except KeyError:
- raise Http404
- gal = get_object_or_404(Gallery, pk=gal_pk)
- try:
- gal_mode = UserGallery.objects.get(gallery=gal, user=request.user)
- assert gal_mode is not None
- # Only allow RW users to modify images
- if not gal_mode.is_write():
- raise PermissionDenied
- except:
- raise PermissionDenied
- if "delete" in request.POST:
- try:
- img = Image.objects.get(pk=request.POST["image"], gallery=gal)
- img.delete()
- except KeyError:
- pass
- except:
- pass
- elif "delete_multi" in request.POST:
- l = request.POST.getlist("items")
- Image.objects.filter(pk__in=l, gallery=gal).delete()
- return redirect(gal.get_absolute_url())
+class DeleteImages(DeleteView):
+ """Delete a given image"""
+ model = Image
+ http_method_names = ['post', 'delete']
-@can_write_and_read_now
-@login_required
-def new_image(request, gal_pk):
- """Creates a new image."""
+ @method_decorator(login_required)
+ @method_decorator(can_write_and_read_now)
+ def dispatch(self, *args, **kwargs):
+ return super(DeleteImages, self).dispatch(*args, **kwargs)
- gal = get_object_or_404(Gallery, pk=gal_pk)
+ def delete(self, request, *args, **kwargs):
- # check if the user can upload new image in this gallery
- try:
- gal_mode = UserGallery.objects.get(gallery=gal, user=request.user)
- assert gal_mode is not None
- if not gal_mode.is_write():
- raise PermissionDenied
- except:
- raise PermissionDenied
+ pk_gallery = self.request.POST['gallery']
+ gallery = get_object_or_404(Gallery, pk=pk_gallery)
+ ensure_user_access(gallery, request.user, can_write=True)
- if request.method == "POST":
- form = ImageForm(request.POST, request.FILES)
- if form.is_valid():
- img = Image()
- img.physical = request.FILES["physical"]
- img.gallery = gal
- img.title = request.POST["title"]
- img.slug = slugify(request.FILES["physical"])
- img.legend = request.POST["legend"]
- img.pubdate = datetime.now()
- img.save()
+ if 'delete_multi' in request.POST:
+ list_items = request.POST.getlist("items")
+ Image.objects.filter(pk__in=list_items, gallery=gallery).delete()
+ elif 'delete' in request.POST:
+ pkey = self.request.POST['image']
+ img = get_object_or_404(Image, pk=pkey)
- # Redirect to the newly uploaded image edit page after POST
- return redirect(reverse("zds.gallery.views.edit_image",
- args=[gal.pk, img.pk]))
- else:
- return render(request, "gallery/image/new.html", {"form": form,
- "gallery_mode": gal_mode,
- "gallery": gal})
- else:
- form = ImageForm(initial={"new_image": True}) # A empty, unbound form
- return render(request, "gallery/image/new.html", {"form": form,
- "gallery_mode": gal_mode,
- "gallery": gal})
+ if img.gallery != gallery:
+ raise PermissionDenied
+ img.delete()
-@can_write_and_read_now
-@login_required
-@transaction.atomic
-def import_image(request, gal_pk):
+ return redirect(gallery.get_absolute_url())
+
+
+class ImportImages(GalleryMixin, FormView):
"""Create images from zip archive."""
- gal = get_object_or_404(Gallery, pk=gal_pk)
+ form_class = ArchiveImageForm
+ http_method_names = ['get', 'post', 'put']
+ template_name = "gallery/image/import.html"
+ can_write = True # only allowed user can import new images
- try:
- gal_mode = UserGallery.objects.get(gallery=gal, user=request.user)
- assert gal_mode is not None
- if not gal_mode.is_write():
- raise PermissionDenied
- except:
- raise PermissionDenied
+ @method_decorator(login_required)
+ @method_decorator(can_write_and_read_now)
+ def dispatch(self, *args, **kwargs):
+ return super(ImportImages, self).dispatch(*args, **kwargs)
- # if request is POST
- if request.method == "POST":
- form = ArchiveImageForm(request.POST, request.FILES)
- if form.is_valid():
- archive = request.FILES["file"]
- temp = os.path.join(settings.SITE_ROOT, "temp")
- if not os.path.exists(temp):
- os.makedirs(temp)
- zfile = zipfile.ZipFile(archive, "a")
- for i in zfile.namelist():
- ph_temp = os.path.abspath(os.path.join(temp, i))
- (dirname, filename) = os.path.split(i)
- # if directory doesn't exist, created on
- if not os.path.exists(os.path.dirname(ph_temp)):
- os.makedirs(os.path.dirname(ph_temp))
- # if file is directory, don't create file
- if filename.strip() == "":
- continue
- data = zfile.read(i)
- # create file for image
- fp = open(ph_temp, "wb")
- fp.write(data)
- fp.close()
- title = os.path.basename(i)
- # if size is too large don't save
- if os.stat(ph_temp).st_size > settings.ZDS_APP['gallery']['image_max_size']:
- messages.error(request, _(u"Votre image est beaucoup trop lourde, "
- u"réduisez sa taille à moins de {} "
- u"Kio "
- u"avant de l'envoyer.").format(
- str(settings.ZDS_APP['gallery']['image_max_size'] / 1024)))
- continue
- # if it's not an image, pass
- try:
- ImagePIL.open(ph_temp)
- except IOError:
- continue
- f = File(open(ph_temp, "rb"))
- f.name = title
- # create picture in database
- pic = Image()
- pic.gallery = gal
- pic.title = title
- pic.pubdate = datetime.now()
- pic.physical = f
- pic.save()
- f.close()
-
- zfile.close()
-
- if os.path.exists(temp):
- shutil.rmtree(temp)
-
- # Redirect to the newly uploaded gallery
- return redirect(reverse("zds.gallery.views.gallery_details",
- args=[gal.pk, gal.slug]))
- else:
- return render(request, "gallery/image/new.html", {"form": form,
- "gallery_mode": gal_mode,
- "gallery": gal})
- else:
- form = ArchiveImageForm(initial={"new_image": True}) # A empty, unbound form
- return render(request, "gallery/image/new.html", {"form": form,
- "gallery_mode": gal_mode,
- "gallery": gal})
+ def form_valid(self, form):
+ context = self.get_context_data()
+ gallery = context['gallery']
+
+ archive = self.request.FILES["file"]
+ temp = os.path.join(tempfile.gettempdir(), str(time.time()))
+
+ if not os.path.exists(temp):
+ os.makedirs(temp)
+ zfile = zipfile.ZipFile(archive, "a")
+
+ for i in zfile.namelist():
+ filename = os.path.split(i)[1]
+
+ ph_temp = os.path.abspath(os.path.join(temp, os.path.basename(i)))
+
+ if filename.strip() == "": # don't deal with directory
+ continue
+
+ # create file for image
+ f_im = open(ph_temp, "wb")
+ f_im.write(zfile.read(i))
+ f_im.close()
+ title = os.path.basename(i)
+
+ # if size is too large, don't save
+ if os.stat(ph_temp).st_size > settings.ZDS_APP['gallery']['image_max_size']:
+ messages.error(
+ self.request, _(u'Votre image "{}" est beaucoup trop lourde, réduisez sa taille à moins de {:.0f}'
+ u'Kio avant de l\'envoyer.').format(
+ title, settings.ZDS_APP['gallery']['image_max_size'] / 1024))
+ continue
+
+ # if it's not an image, pass
+ try:
+ ImagePIL.open(ph_temp)
+ except IOError:
+ continue
+
+ # create picture in database:
+ f_im = File(open(ph_temp, "rb"))
+ f_im.name = title
+
+ pic = Image()
+ pic.gallery = gallery
+ pic.title = title
+ pic.pubdate = datetime.now()
+ pic.physical = f_im
+ pic.save()
+ f_im.close()
+
+ if os.path.exists(ph_temp):
+ os.remove(ph_temp)
+
+ zfile.close()
+
+ if os.path.exists(temp):
+ shutil.rmtree(temp)
+
+ return redirect(gallery.get_absolute_url())
diff --git a/zds/member/api/serializers.py b/zds/member/api/serializers.py
index e8bebee84c..3fc4e3c6cf 100644
--- a/zds/member/api/serializers.py
+++ b/zds/member/api/serializers.py
@@ -54,6 +54,7 @@ class ProfileDetailSerializer(serializers.ModelSerializer):
email = serializers.EmailField(source='user.email')
is_active = serializers.BooleanField(source='user.is_active')
date_joined = serializers.DateTimeField(source='user.date_joined')
+ avatar_url = serializers.CharField(source='get_avatar_url')
class Meta:
model = Profile
diff --git a/zds/member/api/tests.py b/zds/member/api/tests.py
index bd819bfa79..f7cd4cddab 100644
--- a/zds/member/api/tests.py
+++ b/zds/member/api/tests.py
@@ -4,7 +4,6 @@
from django.contrib.auth.models import User
from django.core import mail
from django.core.urlresolvers import reverse
-from django.test.utils import override_settings
from oauth2_provider.models import Application, AccessToken
from rest_framework import status
from rest_framework.test import APITestCase
@@ -14,11 +13,6 @@
from zds.member.models import TokenRegister
-overrided_drf = settings.REST_FRAMEWORK
-overrided_drf['MAX_PAGINATE_BY'] = 20
-
-
-@override_settings(REST_FRAMEWORK=overrided_drf)
class MemberListAPITest(APITestCase):
def setUp(self):
self.client = APIClient()
@@ -338,7 +332,7 @@ def test_detail_of_the_member(self):
self.assertEqual(profile.user.is_active, response.data.get('is_active'))
self.assertIsNotNone(response.data.get('date_joined'))
self.assertEqual(profile.site, response.data.get('site'))
- self.assertEqual(profile.avatar_url, response.data.get('avatar_url'))
+ self.assertEqual(profile.get_avatar_url(), response.data.get('avatar_url'))
self.assertEqual(profile.biography, response.data.get('biography'))
self.assertEqual(profile.sign, response.data.get('sign'))
self.assertFalse(response.data.get('show_email'))
@@ -377,7 +371,7 @@ def test_detail_of_a_member(self):
self.assertEqual(self.profile.user.is_active, response.data.get('is_active'))
self.assertIsNotNone(response.data.get('date_joined'))
self.assertEqual(self.profile.site, response.data.get('site'))
- self.assertEqual(self.profile.avatar_url, response.data.get('avatar_url'))
+ self.assertEqual(self.profile.get_avatar_url(), response.data.get('avatar_url'))
self.assertEqual(self.profile.biography, response.data.get('biography'))
self.assertEqual(self.profile.sign, response.data.get('sign'))
self.assertFalse(response.data.get('show_email'))
diff --git a/zds/member/commons.py b/zds/member/commons.py
index 03d2545817..e12af7c83f 100644
--- a/zds/member/commons.py
+++ b/zds/member/commons.py
@@ -12,7 +12,7 @@
from django.template.defaultfilters import pluralize
from django.utils.translation import ugettext_lazy as _
from zds.member.models import Profile, TokenRegister, Ban, logout_user
-from zds.settings import SITE_ROOT
+from zds.settings import BASE_DIR
from zds.utils.mps import send_mp
@@ -72,7 +72,7 @@ def validate_email(self, value):
if value:
msg = None
# Chech if email provider is authorized
- with open(os.path.join(SITE_ROOT, 'forbidden_email_providers.txt'), 'r') as fh:
+ with open(os.path.join(BASE_DIR, 'forbidden_email_providers.txt'), 'r') as fh:
for provider in fh:
if provider.strip() in value:
msg = _(u'Utilisez un autre fournisseur d\'adresses courriel.')
@@ -245,12 +245,12 @@ def get_message_unsanction(self):
:rtype: ugettext_lazy
"""
return _(u'Bonjour **{0}**,\n\n'
- u'**Bonne Nouvelle**, la sanction qui '
+ u'**Bonne nouvelle**, la sanction qui '
u'pesait sur vous a été levée par **{1}**.\n\n'
- u'Ce qui signifie que {2}\n\n'
- u'Le motif de votre sanction est :\n\n'
- u'> {3}\n\n'
- u'Cordialement, \n\nL\'équipe {4}.')
+ u'Ce qui signifie que {3}\n\n'
+ u'Le motif est :\n\n'
+ u'> {4}\n\n'
+ u'Cordialement, \n\n L\'équipe {5}.')
def get_message_sanction(self):
"""
@@ -282,7 +282,7 @@ def notify_member(self, ban, msg):
bot,
[ban.user],
ban.type,
- _("Sanction"),
+ "",
msg,
True,
direct=True,
@@ -348,7 +348,7 @@ def get_text(self):
return self.array_infos.get('unls-text', '')
def get_detail(self):
- return (_(u'Vous pouvez désormais poster sur les forums, dans les '
+ return (_(u'vous pouvez désormais poster sur les forums, dans les '
u'commentaires d\'articles et tutoriels.'))
def apply_sanction(self, profile, ban):
diff --git a/zds/member/decorator.py b/zds/member/decorator.py
index fedf565b2f..4032a9181a 100644
--- a/zds/member/decorator.py
+++ b/zds/member/decorator.py
@@ -4,7 +4,13 @@
def can_write_and_read_now(func):
- """Decorator to check that the user can read and write now."""
+ """
+ Checks if the current user has read and write rights, right now.
+ A visitor has correct rights only if it is connected and has proper rights attached to its profile.
+ Real roles in database are checked, this doesn't use session-cached stuff.
+ :param func: the decorated function
+ :return: `True` if the current user can read and write, `False` otherwise.
+ """
def _can_write_and_read_now(request, *args, **kwargs):
try:
profile = request.user.profile
diff --git a/zds/member/factories.py b/zds/member/factories.py
index ba7dbd476c..e8e8fcdcfc 100644
--- a/zds/member/factories.py
+++ b/zds/member/factories.py
@@ -5,15 +5,17 @@
from zds.member.models import Profile
-# Don't try to directly use UserFactory, this didn't create Profile then
-# don't work!
-
class UserFactory(factory.DjangoModelFactory):
+ """
+ This factory creates User.
+ WARNING: Don't try to directly use `UserFactory`, this didn't create associated Profile then don't work!
+ Use `ProfileFactory` instead.
+ """
FACTORY_FOR = User
- username = factory.Sequence(lambda n: 'firm{0}'.format(n))
- email = factory.Sequence(lambda n: 'firm{0}@zestedesavoir.com'.format(n))
+ username = factory.Sequence('firm{0}'.format)
+ email = factory.Sequence('firm{0}@zestedesavoir.com'.format)
password = 'hostel77'
is_active = True
@@ -28,16 +30,17 @@ def _prepare(cls, create, **kwargs):
user.save()
return user
-# Don't try to directly use StaffFactory, this didn't create Profile then
-# don't work!
-
class StaffFactory(factory.DjangoModelFactory):
+ """
+ This factory creates staff User.
+ WARNING: Don't try to directly use `StaffFactory`, this didn't create associated Profile then don't work!
+ Use `StaffProfileFactory` instead.
+ """
FACTORY_FOR = User
- username = factory.Sequence(lambda n: 'firmstaff{0}'.format(n))
- email = factory.Sequence(
- lambda n: 'firmstaff{0}@zestedesavoir.com'.format(n))
+ username = factory.Sequence('firmstaff{0}'.format)
+ email = factory.Sequence('firmstaff{0}@zestedesavoir.com'.format)
password = 'hostel77'
is_active = True
@@ -64,6 +67,9 @@ def _prepare(cls, create, **kwargs):
class ProfileFactory(factory.DjangoModelFactory):
+ """
+ Use this factory when you need a complete Profile for a standard user.
+ """
FACTORY_FOR = Profile
user = factory.SubFactory(UserFactory)
@@ -79,6 +85,9 @@ def biography(self):
class StaffProfileFactory(factory.DjangoModelFactory):
+ """
+ Use this factory when you need a complete Profile for a staff user.
+ """
FACTORY_FOR = Profile
user = factory.SubFactory(StaffFactory)
@@ -94,12 +103,20 @@ def biography(self):
class NonAsciiUserFactory(UserFactory):
+ """
+ This factory creates standard user with non-ASCII characters in its username.
+ WARNING: Don't try to directly use `NonAsciiUserFactory`, this didn't create associated Profile then don't work!
+ Use `NonAsciiProfileFactory` instead.
+ """
FACTORY_FOR = User
- username = factory.Sequence(lambda n: u'ïéàçÊÀ{0}'.format(n))
+ username = factory.Sequence(u'ïéàçÊÀ{0}'.format)
class NonAsciiProfileFactory(ProfileFactory):
+ """
+ Use this factory to create a standard user with non-ASCII characters in its username.
+ """
FACTORY_FOR = Profile
user = factory.SubFactory(NonAsciiUserFactory)
diff --git a/zds/member/forms.py b/zds/member/forms.py
index 23ce03efce..fd34dd7186 100644
--- a/zds/member/forms.py
+++ b/zds/member/forms.py
@@ -24,6 +24,9 @@
class OldTutoForm(forms.Form):
+ """
+ This form to attributes "Old" tutorials to the current user.
+ """
id = forms.ChoiceField(
label=_(u'Ancien Tutoriel'),
required=True,
@@ -47,6 +50,9 @@ def __init__(self, profile, *args, **kwargs):
class LoginForm(forms.Form):
+ """
+ The login form, including the "remember me" checkbox and the "password forget" link.
+ """
username = forms.CharField(
label=_(u"Nom d'utilisateur"),
max_length=User._meta.get_field('username').max_length,
@@ -92,6 +98,9 @@ def __init__(self, next=None, *args, **kwargs):
class RegisterForm(forms.Form, ProfileUsernameValidator, ProfileEmailValidator):
+ """
+ Form to register a new user.
+ """
email = forms.EmailField(
label=_(u'Adresse courriel'),
max_length=User._meta.get_field('email').max_length,
@@ -136,6 +145,19 @@ def __init__(self, *args, **kwargs):
))
def clean(self):
+ """
+ Cleans the input data and performs following checks:
+ - Both passwords are the same
+ - Username doesn't exist in database
+ - Username is not empty
+ - Username doesn't contain any comma (this will break the personal message system)
+ - Username doesn't begin or ends with spaces
+ - Password is different of username
+ - Email address is unique through all users
+ - Email provider is not a forbidden one
+ Forbidden email providers are stored in `forbidden_email_providers.txt` on project root.
+ :return: Cleaned data, and the error messages if they exist.
+ """
cleaned_data = super(RegisterForm, self).clean()
# Check that the password and it's confirmation match
@@ -177,6 +199,9 @@ def throw_error(self, key=None, message=None):
class MiniProfileForm(forms.Form):
+ """
+ Updates some profile data: biography, website, avatar URL, signature.
+ """
biography = forms.CharField(
label=_('Biographie'),
required=False,
@@ -238,8 +263,14 @@ def __init__(self, *args, **kwargs):
))
-# update extra information about user
class ProfileForm(MiniProfileForm):
+ """
+ Updates main profile rules:
+ - Display email address to everybody
+ - Display signatures
+ - Display menus on hover
+ - Receive an email when receiving a personal message
+ """
options = forms.MultipleChoiceField(
label='',
required=False,
@@ -280,7 +311,7 @@ def __init__(self, *args, **kwargs):
Field('site'),
Field('avatar_url'),
HTML(u"""
- Choisir un avatar dans une galerie
+
Choisir un avatar dans une galerie
Naviguez vers l'image voulue et cliquez sur le bouton "Choisir comme avatar ".
Créez une galerie et importez votre avatar si ce n'est pas déjà fait !
"""),
@@ -291,8 +322,10 @@ def __init__(self, *args, **kwargs):
))
-# to update email/username
class ChangeUserForm(forms.Form, ProfileUsernameValidator, ProfileEmailValidator):
+ """
+ Update username and email
+ """
username = forms.CharField(
label=_(u'Nouveau pseudo'),
max_length=User._meta.get_field('username').max_length,
@@ -348,8 +381,9 @@ def throw_error(self, key=None, message=None):
self._errors[key] = self.error_class([message])
-# to update a password
+# TODO: Updates the password --> requires a better name
class ChangePasswordForm(forms.Form):
+
password_new = forms.CharField(
label=_(u'Nouveau mot de passe'),
max_length=MAX_PASSWORD_LENGTH,
@@ -393,6 +427,7 @@ def clean(self):
password_new = cleaned_data.get('password_new')
password_confirm = cleaned_data.get('password_confirm')
+ # TODO: mutualizes these rules with registration ones?
# Check if the actual password is not empty
if password_old:
user_exist = authenticate(
@@ -430,7 +465,7 @@ def clean(self):
return cleaned_data
-# Reset the password
+# TODO Asks for a new password --> Requires a better name
class ForgotPasswordForm(forms.Form):
username = forms.CharField(
label=_(u'Nom d\'utilisateur'),
@@ -494,6 +529,9 @@ def clean(self):
class NewPasswordForm(forms.Form):
+ """
+ Defines a new password (when the current one has been forgotten)
+ """
password = forms.CharField(
label=_(u'Mot de passe'),
max_length=MAX_PASSWORD_LENGTH,
@@ -529,6 +567,7 @@ def clean(self):
password = cleaned_data.get('password')
password_confirm = cleaned_data.get('password_confirm')
+ # TODO: mutualizes these rules with registration ones?
if not password_confirm == password:
msg = _(u'Les mots de passe sont différents')
self._errors['password'] = self.error_class([''])
@@ -554,6 +593,9 @@ def clean(self):
class PromoteMemberForm(forms.Form):
+ """
+ Promotes a user to an arbitrary group
+ """
groups = forms.ModelMultipleChoiceField(
label=_(u"Groupe de l'utilisateur"),
queryset=Group.objects.all(),
diff --git a/zds/member/migrations/0001_initial.py b/zds/member/migrations/0001_initial.py
index c119a9a4f5..80dc60dd33 100644
--- a/zds/member/migrations/0001_initial.py
+++ b/zds/member/migrations/0001_initial.py
@@ -1,207 +1,104 @@
# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
+from __future__ import unicode_literals
+from django.db import models, migrations
+from django.conf import settings
-class Migration(SchemaMigration):
- def forwards(self, orm):
- # Adding model 'Profile'
- db.create_table(
- u'member_profile', ((u'id', self.gf('django.db.models.fields.AutoField')(
- primary_key=True)), ('user', self.gf('django.db.models.fields.related.OneToOneField')(
- to=orm['auth.User'], unique=True)), ('last_ip_address', self.gf('django.db.models.fields.CharField')(
- max_length=15, null=True, blank=True)), ('site', self.gf('django.db.models.fields.CharField')(
- max_length=128, blank=True)), ('show_email', self.gf('django.db.models.fields.BooleanField')(
- default=True)), ('avatar_url', self.gf('django.db.models.fields.CharField')(
- max_length=128, null=True, blank=True)), ('biography', self.gf('django.db.models.fields.TextField')(
- blank=True)), ('karma', self.gf('django.db.models.fields.IntegerField')(
- default=0)), ('sign', self.gf('django.db.models.fields.TextField')(
- blank=True)), ('show_sign', self.gf('django.db.models.fields.BooleanField')(
- default=True)), ('hover_or_click', self.gf('django.db.models.fields.BooleanField')(
- default=False)), ('can_read', self.gf('django.db.models.fields.BooleanField')(
- default=True)), ('end_ban_read', self.gf('django.db.models.fields.DateTimeField')(
- null=True, blank=True)), ('can_write', self.gf('django.db.models.fields.BooleanField')(
- default=True)), ('end_ban_write', self.gf('django.db.models.fields.DateTimeField')(
- null=True, blank=True)), ))
- db.send_create_signal(u'member', ['Profile'])
+class Migration(migrations.Migration):
- # Adding model 'TokenForgotPassword'
- db.create_table(
- u'member_tokenforgotpassword', ((u'id', self.gf('django.db.models.fields.AutoField')(
- primary_key=True)), ('user', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['auth.User'])), ('token', self.gf('django.db.models.fields.CharField')(
- max_length=100)), ('date_end', self.gf('django.db.models.fields.DateTimeField')()), ))
- db.send_create_signal(u'member', ['TokenForgotPassword'])
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
- # Adding model 'TokenRegister'
- db.create_table(
- u'member_tokenregister', ((u'id', self.gf('django.db.models.fields.AutoField')(
- primary_key=True)), ('user', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['auth.User'])), ('token', self.gf('django.db.models.fields.CharField')(
- max_length=100)), ('date_end', self.gf('django.db.models.fields.DateTimeField')()), ))
- db.send_create_signal(u'member', ['TokenRegister'])
-
- # Adding model 'Ban'
- db.create_table(
- u'member_ban',
- ((u'id',
- self.gf('django.db.models.fields.AutoField')(
- primary_key=True)),
- ('user',
- self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['auth.User'])),
- ('moderator',
- self.gf('django.db.models.fields.related.ForeignKey')(
- related_name='bans',
- to=orm['auth.User'])),
- ('type',
- self.gf('django.db.models.fields.CharField')(
- max_length=80)),
- ('text',
- self.gf('django.db.models.fields.TextField')()),
- ('pubdate',
- self.gf('django.db.models.fields.DateTimeField')(
- null=True,
- blank=True)),
- ))
- db.send_create_signal(u'member', ['Ban'])
-
- def backwards(self, orm):
- # Deleting model 'Profile'
- db.delete_table(u'member_profile')
-
- # Deleting model 'TokenForgotPassword'
- db.delete_table(u'member_tokenforgotpassword')
-
- # Deleting model 'TokenRegister'
- db.delete_table(u'member_tokenregister')
-
- # Deleting model 'Ban'
- db.delete_table(u'member_ban')
-
- models = {
- u'auth.group': {
- 'Meta': {
- 'object_name': 'Group'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '80'}), 'permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})}, u'auth.permission': {
- 'Meta': {
- 'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, 'codename': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'content_type': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['contenttypes.ContentType']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '50'})}, u'auth.user': {
- 'Meta': {
- 'object_name': 'User'}, 'date_joined': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'email': (
- 'django.db.models.fields.EmailField', [], {
- 'max_length': '75', 'blank': 'True'}), 'first_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'groups': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'is_active': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'is_staff': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'is_superuser': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'last_login': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'last_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'password': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128'}), 'user_permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), 'username': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '30'})}, u'contenttypes.contenttype': {
- 'Meta': {
- 'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'model': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'})}, u'member.ban': {
- 'Meta': {
- 'object_name': 'Ban'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'moderator': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'bans'", 'to': u"orm['auth.User']"}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'text': (
- 'django.db.models.fields.TextField', [], {}), 'type': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['auth.User']"})}, u'member.profile': {
- 'Meta': {
- 'object_name': 'Profile'}, 'avatar_url': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128', 'null': 'True', 'blank': 'True'}), 'biography': (
- 'django.db.models.fields.TextField', [], {
- 'blank': 'True'}), 'can_read': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'can_write': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'end_ban_read': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'end_ban_write': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'hover_or_click': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'karma': (
- 'django.db.models.fields.IntegerField', [], {
- 'default': '0'}), 'last_ip_address': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '15', 'null': 'True', 'blank': 'True'}), 'show_email': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'show_sign': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'sign': (
- 'django.db.models.fields.TextField', [], {
- 'blank': 'True'}), 'site': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128', 'blank': 'True'}), 'user': (
- 'django.db.models.fields.related.OneToOneField', [], {
- 'to': u"orm['auth.User']", 'unique': 'True'})}, u'member.tokenforgotpassword': {
- 'Meta': {
- 'object_name': 'TokenForgotPassword'}, 'date_end': (
- 'django.db.models.fields.DateTimeField', [], {}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'token': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['auth.User']"})}, u'member.tokenregister': {
- 'Meta': {
- 'object_name': 'TokenRegister'}, 'date_end': (
- 'django.db.models.fields.DateTimeField', [], {}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'token': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['auth.User']"})}}
-
- complete_apps = ['member']
+ operations = [
+ migrations.CreateModel(
+ name='Ban',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('type', models.CharField(max_length=80, verbose_name=b'Type', db_index=True)),
+ ('text', models.TextField(verbose_name=b'Explication de la sanction')),
+ ('pubdate', models.DateTimeField(db_index=True, null=True, verbose_name=b'Date de publication', blank=True)),
+ ('moderator', models.ForeignKey(related_name='bans', verbose_name=b'Moderateur', to=settings.AUTH_USER_MODEL)),
+ ('user', models.ForeignKey(verbose_name=b'Sanctionn\xc3\xa9', to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'verbose_name': 'Sanction',
+ 'verbose_name_plural': 'Sanctions',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='KarmaNote',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('comment', models.CharField(max_length=150, verbose_name=b'Commentaire')),
+ ('value', models.IntegerField(verbose_name=b'Valeur')),
+ ('create_at', models.DateTimeField(auto_now_add=True, verbose_name=b"Date d'ajout")),
+ ('staff', models.ForeignKey(related_name='karmanote_staff', to=settings.AUTH_USER_MODEL)),
+ ('user', models.ForeignKey(related_name='karmanote_user', to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'verbose_name': 'Note de karma',
+ 'verbose_name_plural': 'Notes de karma',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='Profile',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('last_ip_address', models.CharField(max_length=39, null=True, verbose_name=b'Adresse IP', blank=True)),
+ ('site', models.CharField(max_length=128, verbose_name=b'Site internet', blank=True)),
+ ('show_email', models.BooleanField(default=False, verbose_name=b'Afficher adresse mail publiquement')),
+ ('avatar_url', models.CharField(max_length=128, null=True, verbose_name=b"URL de l'avatar", blank=True)),
+ ('biography', models.TextField(verbose_name=b'Biographie', blank=True)),
+ ('karma', models.IntegerField(default=0, verbose_name=b'Karma')),
+ ('sign', models.TextField(max_length=250, verbose_name=b'Signature', blank=True)),
+ ('show_sign', models.BooleanField(default=True, verbose_name=b'Voir les signatures')),
+ ('hover_or_click', models.BooleanField(default=False, verbose_name=b'Survol ou click ?')),
+ ('email_for_answer', models.BooleanField(default=False, verbose_name=b'Envoyer pour les r\xc3\xa9ponse MP')),
+ ('sdz_tutorial', models.TextField(null=True, verbose_name=b'Identifiant des tutos SdZ', blank=True)),
+ ('can_read', models.BooleanField(default=True, verbose_name=b'Possibilit\xc3\xa9 de lire')),
+ ('end_ban_read', models.DateTimeField(null=True, verbose_name=b"Fin d'interdiction de lecture", blank=True)),
+ ('can_write', models.BooleanField(default=True, verbose_name=b"Possibilit\xc3\xa9 d'\xc3\xa9crire")),
+ ('end_ban_write', models.DateTimeField(null=True, verbose_name=b"Fin d'interdiction d'ecrire", blank=True)),
+ ('last_visit', models.DateTimeField(null=True, verbose_name=b'Date de derni\xc3\xa8re visite', blank=True)),
+ ('user', models.OneToOneField(related_name='profile', verbose_name=b'Utilisateur', to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'verbose_name': 'Profil',
+ 'verbose_name_plural': 'Profils',
+ 'permissions': (('moderation', 'Mod\xe9rer un membre'), ('show_ip', "Afficher les IP d'un membre")),
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='TokenForgotPassword',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('token', models.CharField(max_length=100, db_index=True)),
+ ('date_end', models.DateTimeField(verbose_name=b'Date de fin')),
+ ('user', models.ForeignKey(verbose_name=b'Utilisateur', to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'verbose_name': 'Token de mot de passe oubli\xe9',
+ 'verbose_name_plural': 'Tokens de mots de passe oubli\xe9s',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='TokenRegister',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('token', models.CharField(max_length=100, db_index=True)),
+ ('date_end', models.DateTimeField(verbose_name=b'Date de fin')),
+ ('user', models.ForeignKey(verbose_name=b'Utilisateur', to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'verbose_name': "Token d'inscription",
+ 'verbose_name_plural': "Tokens d'inscription",
+ },
+ bases=(models.Model,),
+ ),
+ ]
diff --git a/zds/member/migrations/0002_auto__chg_field_profile_sign.py b/zds/member/migrations/0002_auto__chg_field_profile_sign.py
deleted file mode 100644
index 8da588c1b7..0000000000
--- a/zds/member/migrations/0002_auto__chg_field_profile_sign.py
+++ /dev/null
@@ -1,149 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
-
- # Changing field 'Profile.sign'
- db.alter_column(
- u'member_profile',
- 'sign',
- self.gf('django.db.models.fields.TextField')(
- max_length=250))
-
- def backwards(self, orm):
-
- # Changing field 'Profile.sign'
- db.alter_column(
- u'member_profile',
- 'sign',
- self.gf('django.db.models.fields.TextField')())
-
- models = {
- u'auth.group': {
- 'Meta': {
- 'object_name': 'Group'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '80'}), 'permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})}, u'auth.permission': {
- 'Meta': {
- 'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, 'codename': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'content_type': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['contenttypes.ContentType']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '50'})}, u'auth.user': {
- 'Meta': {
- 'object_name': 'User'}, 'date_joined': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'email': (
- 'django.db.models.fields.EmailField', [], {
- 'max_length': '75', 'blank': 'True'}), 'first_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'groups': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'is_active': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'is_staff': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'is_superuser': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'last_login': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'last_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'password': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128'}), 'user_permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), 'username': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '30'})}, u'contenttypes.contenttype': {
- 'Meta': {
- 'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'model': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'})}, u'member.ban': {
- 'Meta': {
- 'object_name': 'Ban'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'moderator': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'bans'", 'to': u"orm['auth.User']"}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'text': (
- 'django.db.models.fields.TextField', [], {}), 'type': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['auth.User']"})}, u'member.profile': {
- 'Meta': {
- 'object_name': 'Profile'}, 'avatar_url': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128', 'null': 'True', 'blank': 'True'}), 'biography': (
- 'django.db.models.fields.TextField', [], {
- 'blank': 'True'}), 'can_read': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'can_write': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'end_ban_read': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'end_ban_write': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'hover_or_click': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'karma': (
- 'django.db.models.fields.IntegerField', [], {
- 'default': '0'}), 'last_ip_address': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '15', 'null': 'True', 'blank': 'True'}), 'show_email': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'show_sign': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'sign': (
- 'django.db.models.fields.TextField', [], {
- 'max_length': '250', 'blank': 'True'}), 'site': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128', 'blank': 'True'}), 'user': (
- 'django.db.models.fields.related.OneToOneField', [], {
- 'to': u"orm['auth.User']", 'unique': 'True'})}, u'member.tokenforgotpassword': {
- 'Meta': {
- 'object_name': 'TokenForgotPassword'}, 'date_end': (
- 'django.db.models.fields.DateTimeField', [], {}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'token': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['auth.User']"})}, u'member.tokenregister': {
- 'Meta': {
- 'object_name': 'TokenRegister'}, 'date_end': (
- 'django.db.models.fields.DateTimeField', [], {}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'token': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['auth.User']"})}}
-
- complete_apps = ['member']
diff --git a/zds/member/migrations/0003_auto__add_field_profile_sdz_tutorial.py b/zds/member/migrations/0003_auto__add_field_profile_sdz_tutorial.py
deleted file mode 100644
index ac6e7b8ab2..0000000000
--- a/zds/member/migrations/0003_auto__add_field_profile_sdz_tutorial.py
+++ /dev/null
@@ -1,149 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'Profile.sdz_tutorial'
- db.add_column(
- u'member_profile',
- 'sdz_tutorial',
- self.gf('django.db.models.fields.CharField')(
- max_length=30,
- null=True,
- blank=True),
- keep_default=False)
-
- def backwards(self, orm):
- # Deleting field 'Profile.sdz_tutorial'
- db.delete_column(u'member_profile', 'sdz_tutorial')
-
- models = {
- u'auth.group': {
- 'Meta': {
- 'object_name': 'Group'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '80'}), 'permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})}, u'auth.permission': {
- 'Meta': {
- 'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, 'codename': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'content_type': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['contenttypes.ContentType']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '50'})}, u'auth.user': {
- 'Meta': {
- 'object_name': 'User'}, 'date_joined': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'email': (
- 'django.db.models.fields.EmailField', [], {
- 'max_length': '75', 'blank': 'True'}), 'first_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'groups': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'is_active': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'is_staff': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'is_superuser': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'last_login': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'last_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'password': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128'}), 'user_permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), 'username': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '30'})}, u'contenttypes.contenttype': {
- 'Meta': {
- 'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'model': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'})}, u'member.ban': {
- 'Meta': {
- 'object_name': 'Ban'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'moderator': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'bans'", 'to': u"orm['auth.User']"}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'text': (
- 'django.db.models.fields.TextField', [], {}), 'type': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['auth.User']"})}, u'member.profile': {
- 'Meta': {
- 'object_name': 'Profile'}, 'avatar_url': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128', 'null': 'True', 'blank': 'True'}), 'biography': (
- 'django.db.models.fields.TextField', [], {
- 'blank': 'True'}), 'can_read': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'can_write': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'end_ban_read': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'end_ban_write': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'hover_or_click': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'karma': (
- 'django.db.models.fields.IntegerField', [], {
- 'default': '0'}), 'last_ip_address': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '15', 'null': 'True', 'blank': 'True'}), 'sdz_tutorial': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'null': 'True', 'blank': 'True'}), 'show_email': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'show_sign': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'sign': (
- 'django.db.models.fields.TextField', [], {
- 'max_length': '250', 'blank': 'True'}), 'site': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128', 'blank': 'True'}), 'user': (
- 'django.db.models.fields.related.OneToOneField', [], {
- 'to': u"orm['auth.User']", 'unique': 'True'})}, u'member.tokenforgotpassword': {
- 'Meta': {
- 'object_name': 'TokenForgotPassword'}, 'date_end': (
- 'django.db.models.fields.DateTimeField', [], {}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'token': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['auth.User']"})}, u'member.tokenregister': {
- 'Meta': {
- 'object_name': 'TokenRegister'}, 'date_end': (
- 'django.db.models.fields.DateTimeField', [], {}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'token': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['auth.User']"})}}
-
- complete_apps = ['member']
diff --git a/zds/member/migrations/0004_auto__add_field_profile_last_visit.py b/zds/member/migrations/0004_auto__add_field_profile_last_visit.py
deleted file mode 100644
index cd8142d179..0000000000
--- a/zds/member/migrations/0004_auto__add_field_profile_last_visit.py
+++ /dev/null
@@ -1,150 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'Profile.last_visit'
- db.add_column(
- u'member_profile',
- 'last_visit',
- self.gf('django.db.models.fields.DateTimeField')(
- null=True,
- blank=True),
- keep_default=False)
-
- def backwards(self, orm):
- # Deleting field 'Profile.last_visit'
- db.delete_column(u'member_profile', 'last_visit')
-
- models = {
- u'auth.group': {
- 'Meta': {
- 'object_name': 'Group'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '80'}), 'permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})}, u'auth.permission': {
- 'Meta': {
- 'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, 'codename': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'content_type': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['contenttypes.ContentType']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '50'})}, u'auth.user': {
- 'Meta': {
- 'object_name': 'User'}, 'date_joined': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'email': (
- 'django.db.models.fields.EmailField', [], {
- 'max_length': '75', 'blank': 'True'}), 'first_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'groups': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'is_active': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'is_staff': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'is_superuser': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'last_login': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'last_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'password': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128'}), 'user_permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), 'username': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '30'})}, u'contenttypes.contenttype': {
- 'Meta': {
- 'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'model': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'})}, u'member.ban': {
- 'Meta': {
- 'object_name': 'Ban'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'moderator': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'bans'", 'to': u"orm['auth.User']"}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'text': (
- 'django.db.models.fields.TextField', [], {}), 'type': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['auth.User']"})}, u'member.profile': {
- 'Meta': {
- 'object_name': 'Profile'}, 'avatar_url': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128', 'null': 'True', 'blank': 'True'}), 'biography': (
- 'django.db.models.fields.TextField', [], {
- 'blank': 'True'}), 'can_read': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'can_write': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'end_ban_read': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'end_ban_write': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'hover_or_click': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'karma': (
- 'django.db.models.fields.IntegerField', [], {
- 'default': '0'}), 'last_ip_address': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '15', 'null': 'True', 'blank': 'True'}), 'last_visit': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'sdz_tutorial': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'null': 'True', 'blank': 'True'}), 'show_email': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'show_sign': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'sign': (
- 'django.db.models.fields.TextField', [], {
- 'max_length': '250', 'blank': 'True'}), 'site': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128', 'blank': 'True'}), 'user': (
- 'django.db.models.fields.related.OneToOneField', [], {
- 'to': u"orm['auth.User']", 'unique': 'True'})}, u'member.tokenforgotpassword': {
- 'Meta': {
- 'object_name': 'TokenForgotPassword'}, 'date_end': (
- 'django.db.models.fields.DateTimeField', [], {}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'token': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['auth.User']"})}, u'member.tokenregister': {
- 'Meta': {
- 'object_name': 'TokenRegister'}, 'date_end': (
- 'django.db.models.fields.DateTimeField', [], {}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'token': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['auth.User']"})}}
-
- complete_apps = ['member']
diff --git a/zds/member/migrations/0005_auto__add_field_profile_email_for_answer.py b/zds/member/migrations/0005_auto__add_field_profile_email_for_answer.py
deleted file mode 100644
index f29f82f631..0000000000
--- a/zds/member/migrations/0005_auto__add_field_profile_email_for_answer.py
+++ /dev/null
@@ -1,151 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'Profile.email_for_answer'
- db.add_column(
- u'member_profile',
- 'email_for_answer',
- self.gf('django.db.models.fields.BooleanField')(
- default=False),
- keep_default=False)
-
- def backwards(self, orm):
- # Deleting field 'Profile.email_for_answer'
- db.delete_column(u'member_profile', 'email_for_answer')
-
- models = {
- u'auth.group': {
- 'Meta': {
- 'object_name': 'Group'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '80'}), 'permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})}, u'auth.permission': {
- 'Meta': {
- 'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, 'codename': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'content_type': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['contenttypes.ContentType']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '50'})}, u'auth.user': {
- 'Meta': {
- 'object_name': 'User'}, 'date_joined': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'email': (
- 'django.db.models.fields.EmailField', [], {
- 'max_length': '75', 'blank': 'True'}), 'first_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'groups': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'is_active': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'is_staff': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'is_superuser': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'last_login': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'last_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'password': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128'}), 'user_permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), 'username': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '30'})}, u'contenttypes.contenttype': {
- 'Meta': {
- 'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'model': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'})}, u'member.ban': {
- 'Meta': {
- 'object_name': 'Ban'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'moderator': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'bans'", 'to': u"orm['auth.User']"}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'text': (
- 'django.db.models.fields.TextField', [], {}), 'type': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['auth.User']"})}, u'member.profile': {
- 'Meta': {
- 'object_name': 'Profile'}, 'avatar_url': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128', 'null': 'True', 'blank': 'True'}), 'biography': (
- 'django.db.models.fields.TextField', [], {
- 'blank': 'True'}), 'can_read': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'can_write': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'email_for_answer': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'end_ban_read': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'end_ban_write': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'hover_or_click': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'karma': (
- 'django.db.models.fields.IntegerField', [], {
- 'default': '0'}), 'last_ip_address': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '15', 'null': 'True', 'blank': 'True'}), 'last_visit': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'sdz_tutorial': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'null': 'True', 'blank': 'True'}), 'show_email': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'show_sign': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'sign': (
- 'django.db.models.fields.TextField', [], {
- 'max_length': '250', 'blank': 'True'}), 'site': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128', 'blank': 'True'}), 'user': (
- 'django.db.models.fields.related.OneToOneField', [], {
- 'related_name': "'profile'", 'unique': 'True', 'to': u"orm['auth.User']"})}, u'member.tokenforgotpassword': {
- 'Meta': {
- 'object_name': 'TokenForgotPassword'}, 'date_end': (
- 'django.db.models.fields.DateTimeField', [], {}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'token': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['auth.User']"})}, u'member.tokenregister': {
- 'Meta': {
- 'object_name': 'TokenRegister'}, 'date_end': (
- 'django.db.models.fields.DateTimeField', [], {}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'token': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['auth.User']"})}}
-
- complete_apps = ['member']
diff --git a/zds/member/migrations/0006_auto__chg_field_profile_last_ip_address.py b/zds/member/migrations/0006_auto__chg_field_profile_last_ip_address.py
deleted file mode 100644
index 8d017144a7..0000000000
--- a/zds/member/migrations/0006_auto__chg_field_profile_last_ip_address.py
+++ /dev/null
@@ -1,103 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
-
- # Changing field 'Profile.last_ip_address'
- db.alter_column(u'member_profile', 'last_ip_address', self.gf('django.db.models.fields.CharField')(max_length=39, null=True))
-
- def backwards(self, orm):
-
- # Changing field 'Profile.last_ip_address'
- db.alter_column(u'member_profile', 'last_ip_address', self.gf('django.db.models.fields.CharField')(max_length=15, null=True))
-
- models = {
- u'auth.group': {
- 'Meta': {'object_name': 'Group'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'auth.permission': {
- 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'member.ban': {
- 'Meta': {'object_name': 'Ban'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'moderator': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'bans'", 'to': u"orm['auth.User']"}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {}),
- 'type': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
- },
- u'member.profile': {
- 'Meta': {'object_name': 'Profile'},
- 'avatar_url': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
- 'biography': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'can_read': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'can_write': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'email_for_answer': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'end_ban_read': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'end_ban_write': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'hover_or_click': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'karma': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'last_ip_address': ('django.db.models.fields.CharField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
- 'last_visit': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'sdz_tutorial': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}),
- 'show_email': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'show_sign': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'sign': ('django.db.models.fields.TextField', [], {'max_length': '250', 'blank': 'True'}),
- 'site': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
- 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': u"orm['auth.User']"})
- },
- u'member.tokenforgotpassword': {
- 'Meta': {'object_name': 'TokenForgotPassword'},
- 'date_end': ('django.db.models.fields.DateTimeField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'token': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
- },
- u'member.tokenregister': {
- 'Meta': {'object_name': 'TokenRegister'},
- 'date_end': ('django.db.models.fields.DateTimeField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'token': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
- }
- }
-
- complete_apps = ['member']
\ No newline at end of file
diff --git a/zds/member/migrations/0007_auto__chg_field_profile_sdz_tutorial.py b/zds/member/migrations/0007_auto__chg_field_profile_sdz_tutorial.py
deleted file mode 100644
index 9426b8ef3f..0000000000
--- a/zds/member/migrations/0007_auto__chg_field_profile_sdz_tutorial.py
+++ /dev/null
@@ -1,103 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
-
- # Changing field 'Profile.sdz_tutorial'
- db.alter_column(u'member_profile', 'sdz_tutorial', self.gf('django.db.models.fields.TextField')(null=True))
-
- def backwards(self, orm):
-
- # Changing field 'Profile.sdz_tutorial'
- db.alter_column(u'member_profile', 'sdz_tutorial', self.gf('django.db.models.fields.CharField')(max_length=30, null=True))
-
- models = {
- u'auth.group': {
- 'Meta': {'object_name': 'Group'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'auth.permission': {
- 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'member.ban': {
- 'Meta': {'object_name': 'Ban'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'moderator': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'bans'", 'to': u"orm['auth.User']"}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {}),
- 'type': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
- },
- u'member.profile': {
- 'Meta': {'object_name': 'Profile'},
- 'avatar_url': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
- 'biography': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'can_read': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'can_write': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'email_for_answer': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'end_ban_read': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'end_ban_write': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'hover_or_click': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'karma': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'last_ip_address': ('django.db.models.fields.CharField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
- 'last_visit': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'sdz_tutorial': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
- 'show_email': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'show_sign': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'sign': ('django.db.models.fields.TextField', [], {'max_length': '250', 'blank': 'True'}),
- 'site': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
- 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': u"orm['auth.User']"})
- },
- u'member.tokenforgotpassword': {
- 'Meta': {'object_name': 'TokenForgotPassword'},
- 'date_end': ('django.db.models.fields.DateTimeField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'token': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
- },
- u'member.tokenregister': {
- 'Meta': {'object_name': 'TokenRegister'},
- 'date_end': ('django.db.models.fields.DateTimeField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'token': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
- }
- }
-
- complete_apps = ['member']
\ No newline at end of file
diff --git a/zds/member/migrations/0008_auto__add_index_tokenregister_token__add_index_tokenforgotpassword_tok.py b/zds/member/migrations/0008_auto__add_index_tokenregister_token__add_index_tokenforgotpassword_tok.py
deleted file mode 100644
index f8947bad6c..0000000000
--- a/zds/member/migrations/0008_auto__add_index_tokenregister_token__add_index_tokenforgotpassword_tok.py
+++ /dev/null
@@ -1,121 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding index on 'TokenRegister', fields ['token']
- db.create_index(u'member_tokenregister', ['token'])
-
- # Adding index on 'TokenForgotPassword', fields ['token']
- db.create_index(u'member_tokenforgotpassword', ['token'])
-
- # Adding index on 'Ban', fields ['pubdate']
- db.create_index(u'member_ban', ['pubdate'])
-
- # Adding index on 'Ban', fields ['type']
- db.create_index(u'member_ban', ['type'])
-
-
- def backwards(self, orm):
- # Removing index on 'Ban', fields ['type']
- db.delete_index(u'member_ban', ['type'])
-
- # Removing index on 'Ban', fields ['pubdate']
- db.delete_index(u'member_ban', ['pubdate'])
-
- # Removing index on 'TokenForgotPassword', fields ['token']
- db.delete_index(u'member_tokenforgotpassword', ['token'])
-
- # Removing index on 'TokenRegister', fields ['token']
- db.delete_index(u'member_tokenregister', ['token'])
-
-
- models = {
- u'auth.group': {
- 'Meta': {'object_name': 'Group'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'auth.permission': {
- 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'member.ban': {
- 'Meta': {'object_name': 'Ban'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'moderator': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'bans'", 'to': u"orm['auth.User']"}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {}),
- 'type': ('django.db.models.fields.CharField', [], {'max_length': '80', 'db_index': 'True'}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
- },
- u'member.profile': {
- 'Meta': {'object_name': 'Profile'},
- 'avatar_url': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
- 'biography': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'can_read': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'can_write': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'email_for_answer': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'end_ban_read': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'end_ban_write': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'hover_or_click': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'karma': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'last_ip_address': ('django.db.models.fields.CharField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
- 'last_visit': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'sdz_tutorial': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
- 'show_email': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'show_sign': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'sign': ('django.db.models.fields.TextField', [], {'max_length': '250', 'blank': 'True'}),
- 'site': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
- 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': u"orm['auth.User']"})
- },
- u'member.tokenforgotpassword': {
- 'Meta': {'object_name': 'TokenForgotPassword'},
- 'date_end': ('django.db.models.fields.DateTimeField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'token': ('django.db.models.fields.CharField', [], {'max_length': '100', 'db_index': 'True'}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
- },
- u'member.tokenregister': {
- 'Meta': {'object_name': 'TokenRegister'},
- 'date_end': ('django.db.models.fields.DateTimeField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'token': ('django.db.models.fields.CharField', [], {'max_length': '100', 'db_index': 'True'}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
- }
- }
-
- complete_apps = ['member']
\ No newline at end of file
diff --git a/zds/member/migrations/0009_auto__add_karmanote.py b/zds/member/migrations/0009_auto__add_karmanote.py
deleted file mode 100644
index 48e83ec053..0000000000
--- a/zds/member/migrations/0009_auto__add_karmanote.py
+++ /dev/null
@@ -1,120 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding model 'KarmaNote'
- db.create_table(u'member_karmanote', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='karmanote_user', to=orm['auth.User'])),
- ('staff', self.gf('django.db.models.fields.related.ForeignKey')(related_name='karmanote_staff', to=orm['auth.User'])),
- ('comment', self.gf('django.db.models.fields.CharField')(max_length=150)),
- ('value', self.gf('django.db.models.fields.IntegerField')()),
- ('create_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
- ))
- db.send_create_signal(u'member', ['KarmaNote'])
-
-
- def backwards(self, orm):
- # Deleting model 'KarmaNote'
- db.delete_table(u'member_karmanote')
-
-
- models = {
- u'auth.group': {
- 'Meta': {'object_name': 'Group'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'auth.permission': {
- 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'member.ban': {
- 'Meta': {'object_name': 'Ban'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'moderator': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'bans'", 'to': u"orm['auth.User']"}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {}),
- 'type': ('django.db.models.fields.CharField', [], {'max_length': '80', 'db_index': 'True'}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
- },
- u'member.karmanote': {
- 'Meta': {'object_name': 'KarmaNote'},
- 'comment': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
- 'create_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'staff': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'karmanote_staff'", 'to': u"orm['auth.User']"}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'karmanote_user'", 'to': u"orm['auth.User']"}),
- 'value': ('django.db.models.fields.IntegerField', [], {})
- },
- u'member.profile': {
- 'Meta': {'object_name': 'Profile'},
- 'avatar_url': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
- 'biography': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'can_read': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'can_write': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'email_for_answer': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'end_ban_read': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'end_ban_write': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'hover_or_click': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'karma': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'last_ip_address': ('django.db.models.fields.CharField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
- 'last_visit': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'sdz_tutorial': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
- 'show_email': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'show_sign': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'sign': ('django.db.models.fields.TextField', [], {'max_length': '250', 'blank': 'True'}),
- 'site': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
- 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': u"orm['auth.User']"})
- },
- u'member.tokenforgotpassword': {
- 'Meta': {'object_name': 'TokenForgotPassword'},
- 'date_end': ('django.db.models.fields.DateTimeField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'token': ('django.db.models.fields.CharField', [], {'max_length': '100', 'db_index': 'True'}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
- },
- u'member.tokenregister': {
- 'Meta': {'object_name': 'TokenRegister'},
- 'date_end': ('django.db.models.fields.DateTimeField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'token': ('django.db.models.fields.CharField', [], {'max_length': '100', 'db_index': 'True'}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
- }
- }
-
- complete_apps = ['member']
\ No newline at end of file
diff --git a/zds/member/models.py b/zds/member/models.py
index e3861edccf..84a8105b51 100644
--- a/zds/member/models.py
+++ b/zds/member/models.py
@@ -17,15 +17,17 @@
import pygeoip
from zds.article.models import Article
from zds.forum.models import Post, Topic
+from zds.member.managers import ProfileManager
from zds.tutorial.models import Tutorial
from zds.utils.models import Alert
-from zds.member.managers import ProfileManager
-from django.utils.importlib import import_module
+from importlib import import_module
class Profile(models.Model):
+ """
+ A user profile. Complementary data of standard Django `auth.user`.
+ """
- """Represents an user profile."""
class Meta:
verbose_name = 'Profil'
verbose_name_plural = 'Profils'
@@ -34,6 +36,8 @@ class Meta:
("show_ip", u"Afficher les IP d'un membre"),
)
+ # Link with standard user is a simple one-to-one link, as recommended in official documentation.
+ # See https://docs.djangoproject.com/en/1.6/topics/auth/customizing/#extending-the-existing-user-model
user = models.OneToOneField(
User,
verbose_name='Utilisateur',
@@ -59,15 +63,15 @@ class Meta:
sign = models.TextField('Signature', max_length=250, blank=True)
- show_sign = models.BooleanField('Voir les signatures',
- default=True)
+ show_sign = models.BooleanField('Voir les signatures', default=True)
- hover_or_click = models.BooleanField('Survol ou click ?',
- default=False)
+ # TODO: Change this name. This is a boolean: "true" is "hover" or "click" ?!
+ hover_or_click = models.BooleanField('Survol ou click ?', default=False)
- email_for_answer = models.BooleanField('Envoyer pour les réponse MP',
- default=False)
+ email_for_answer = models.BooleanField('Envoyer pour les réponse MP', default=False)
+ # SdZ tutorial IDs separated by columns (:).
+ # TODO: bad field name (singular --> should be plural), manually handled multi-valued field.
sdz_tutorial = models.TextField(
'Identifiant des tutos SdZ',
blank=True,
@@ -93,7 +97,6 @@ class Meta:
objects = ProfileManager()
def __unicode__(self):
- """Textual forum of a profile."""
return self.user.username
def is_private(self):
@@ -107,7 +110,14 @@ def get_absolute_url(self):
return reverse('member-detail', kwargs={'user_name': urlquote(self.user.username)})
def get_city(self):
- """return physical adress by geolocalisation."""
+ """
+ Uses geo-localization to get physical localization of a profile through its last IP address.
+ This works relatively good with IPv4 addresses (~city level), but is very imprecise with IPv6 or exotic internet
+ providers.
+ :return: The city and the country name of this profile.
+ """
+ # FIXME: this test to differentiate IPv4 and IPv6 addresses doesn't work, as IPv6 addresses may have length < 16
+ # Example: localhost ("::1"). Real test: IPv4 addresses contains dots, IPv6 addresses contains columns.
if len(self.last_ip_address) <= 16:
gic = pygeoip.GeoIP(
os.path.join(
@@ -124,37 +134,56 @@ def get_city(self):
geo['city'], geo['country_name'])
def get_avatar_url(self):
- """Avatar URL (using custom URL or Gravatar)"""
+ """
+ Get the avatar URL for this profile. If the user has defined a custom URL, use it. If not, use Gravatar.
+ :return: The avatar URL for this profile
+ """
if self.avatar_url:
- return self.avatar_url
+ if self.avatar_url.startswith(settings.MEDIA_URL):
+ return u"{}{}".format(settings.ZDS_APP["site"]["url"], self.avatar_url)
+ else:
+ return self.avatar_url
else:
return 'https://secure.gravatar.com/avatar/{0}?d=identicon'.format(
md5(self.user.email.lower().encode("utf-8")).hexdigest())
def get_post_count(self):
- """Number of messages posted."""
+ """
+ :return: The forum post count. Doesn't count comments on articles or tutorials.
+ """
return Post.objects.filter(author__pk=self.user.pk, is_visible=True).count()
def get_post_count_as_staff(self):
"""Number of messages posted (view as staff)."""
+
return Post.objects.filter(author__pk=self.user.pk).count()
def get_topic_count(self):
- """Number of threads created."""
+ """
+ :return: the number of topics created by this user.
+ """
return Topic.objects.filter(author=self.user).count()
def get_tuto_count(self):
- """Number of tutos created."""
+ """
+ :return: the count of tutorials with this user as author. Count all tutorials, no only published one.
+ """
if self.is_private():
return 0
return Tutorial.objects.filter(authors__in=[self.user]).count()
def get_tutos(self):
- """Get all tutorials of the user."""
+ """
+ :return: All tutorials with this user as author.
+ """
return Tutorial.objects.filter(authors__in=[self.user]).all()
def get_draft_tutos(self):
- """Tutorial in draft."""
+ """
+ Return all draft tutorials with this user as author.
+ A draft tutorial is a tutorial which is not published, in validation or in beta.
+ :return: All draft tutorials with this user as author.
+ """
return Tutorial.objects.filter(
authors__in=[self.user],
sha_draft__isnull=False,
@@ -164,46 +193,62 @@ def get_draft_tutos(self):
).all()
def get_public_tutos(self):
- """Tutorial in public."""
+ """
+ :return: All published tutorials with this user as author.
+ """
return Tutorial.objects.filter(
authors__in=[
self.user],
sha_public__isnull=False).all()
def get_validate_tutos(self):
- """Tutorial in validation."""
+ """
+ :return: All tutorials in validation with this user as author.
+ """
return Tutorial.objects.filter(
authors__in=[
self.user],
sha_validation__isnull=False).all()
def get_beta_tutos(self):
- """Tutorial in beta."""
+ """
+ :return: All tutorials in beta with this user as author.
+ """
return Tutorial.objects.filter(
authors__in=[
self.user],
sha_beta__isnull=False).all()
def get_articles(self):
- """Get all articles of the user."""
+ """
+ :return: All articles with this user as author.
+ """
return Article.objects.filter(authors__in=[self.user]).all()
def get_public_articles(self):
- """Get all public articles of the user."""
+ """
+ :return: All published articles with this user as author.
+ """
return Article.objects.filter(
authors__in=[
self.user],
sha_public__isnull=False).all()
def get_validate_articles(self):
- """Articles in validation."""
+ """
+ :return: All articles in validation with this user as author.
+ """
return Article.objects.filter(
authors__in=[
self.user],
sha_validation__isnull=False).all()
def get_draft_articles(self):
- """Get all draft articles of the user."""
+ """
+ Return all draft article with this user as author.
+ A draft article is a article which is not published or in validation.
+ :return: All draft article with this user as author.
+ """
return Article.objects\
.filter(
authors__in=[self.user],
@@ -218,7 +263,11 @@ def get_posts(self):
def get_invisible_posts_count(self):
return Post.objects.filter(is_visible=False, author=self.user).count()
+ # TODO: improve this method's name?
def get_alerts_posts_count(self):
+ """
+ :return: The number of currently active alerts created by this user.
+ """
return Alert.objects.filter(author=self.user).count()
def can_read_now(self):
@@ -242,19 +291,28 @@ def can_write_now(self):
return False
def get_followed_topics(self):
- """Followed topics."""
+ """
+ :return: All forum topics followed by this user.
+ """
return Topic.objects.filter(topicfollowed__user=self.user)\
.order_by('-last_message__pubdate')
@receiver(models.signals.post_delete, sender=User)
def auto_delete_token_on_unregistering(sender, instance, **kwargs):
+ """
+ This signal receiver deletes forgotten password tokens and registering tokens for the un-registering user;
+ """
TokenForgotPassword.objects.filter(user=instance).delete()
TokenRegister.objects.filter(user=instance).delete()
class TokenForgotPassword(models.Model):
-
+ """
+ When a user forgot its password, the website sends it an email with a token (embedded in a URL).
+ If the user has the correct token, it can choose a new password on the dedicated page.
+ This model stores the tokens for the users that have forgot their passwords, with an expiration date.
+ """
class Meta:
verbose_name = 'Token de mot de passe oublié'
verbose_name_plural = 'Tokens de mots de passe oubliés'
@@ -264,13 +322,18 @@ class Meta:
date_end = models.DateTimeField('Date de fin')
def get_absolute_url(self):
- """Absolute URL to the new password page."""
- return reverse('zds.member.views.new_password') + \
- '?token={0}'.format(self.token)
+ """
+ :return: The absolute URL of the "New password" page, including the correct token.
+ """
+ return reverse('zds.member.views.new_password') + '?token={0}'.format(self.token)
class TokenRegister(models.Model):
-
+ """
+ On registration, a token is send by mail to the user. It must use this token (by clicking on a link) to activate its
+ account (and prove the email address is correct) and connect itself.
+ This model stores the registration token for each user, with an expiration date.
+ """
class Meta:
verbose_name = 'Token d\'inscription'
verbose_name_plural = 'Tokens d\'inscription'
@@ -280,15 +343,16 @@ class Meta:
date_end = models.DateTimeField('Date de fin')
def get_absolute_url(self):
- """Absolute URL to the active account page."""
- return reverse('zds.member.views.active_account') + \
- '?token={0}'.format(self.token)
+ """
+ :return: the absolute URL of the account validation page, including the token.
+ """
+ return reverse('zds.member.views.active_account') + '?token={0}'.format(self.token)
def __unicode__(self):
- """Textual forum of a profile."""
return u"{0} - {1}".format(self.user.username, self.date_end)
+# TODO: Seems unused
def save_profile(backend, user, response, *args, **kwargs):
profile = Profile.objects.filter(user=user).first()
if profile is None:
@@ -302,6 +366,11 @@ def save_profile(backend, user, response, *args, **kwargs):
class Ban(models.Model):
+ """
+ This model stores all sanctions (not only bans).
+ It stores sanctioned user, the moderator, the type of sanctions, the reason and the date.
+ Note this stores also un-sanctions.
+ """
class Meta:
verbose_name = 'Sanction'
@@ -319,19 +388,33 @@ class Meta:
class KarmaNote(models.Model):
-
+ """
+ A karma note is a tool for staff to store data about a member.
+ Data are:
+ - A note (negative values are bad)
+ - A comment about the member
+ - A date
+ This helps the staff to react and stores history of stupidities of a member.
+ """
class Meta:
verbose_name = 'Note de karma'
verbose_name_plural = 'Notes de karma'
user = models.ForeignKey(User, related_name='karmanote_user', db_index=True)
+ # TODO: coherence, "staff" is called "moderator" in Ban model.
staff = models.ForeignKey(User, related_name='karmanote_staff', db_index=True)
+ # TODO: coherence, "comment" is called "text" in Ban model.
comment = models.CharField('Commentaire', max_length=150)
value = models.IntegerField('Valeur')
+ # TODO: coherence, "create_at" is called "pubdate" in Ban model.
create_at = models.DateTimeField('Date d\'ajout', auto_now_add=True)
def logout_user(username):
+ """
+ Logout the member.
+ :param username: the name of the user to logout.
+ """
now = datetime.now()
request = HttpRequest()
@@ -347,7 +430,11 @@ def logout_user(username):
def listing():
-
+ """
+ Lists all SdZ tutorials stored on the server at `settings.SDZ_TUTO_DIR` location.
+ :return: a list of tuples (tutorial ID, path)
+ """
+ # TODO: French here. Improve the method name.
fichier = []
if os.path.isdir(settings.SDZ_TUTO_DIR):
for root in os.listdir(settings.SDZ_TUTO_DIR):
@@ -361,6 +448,12 @@ def listing():
def get_info_old_tuto(id):
+ """
+ Retrieve data from SdZ tutorials.
+ :param id: The ID of the SdZ tutorial.
+ :return: ID, title, tutorial file path, image list file paths, and logo file path of this SdZ tutorial.
+ """
+ # TODO: French here.
titre = ''
tuto = ''
images = ''
@@ -386,4 +479,4 @@ def get_info_old_tuto(id):
'gif']:
logo = os.path.join(root, file)
- return (id, titre, tuto, images, logo)
+ return id, titre, tuto, images, logo
diff --git a/zds/member/tests/tests_models.py b/zds/member/tests/tests_models.py
index 55c3fdb29a..11a6566757 100644
--- a/zds/member/tests/tests_models.py
+++ b/zds/member/tests/tests_models.py
@@ -17,18 +17,18 @@
from zds.member.factories import ProfileFactory, StaffProfileFactory
from zds.member.models import TokenForgotPassword, TokenRegister, Profile
from zds.tutorial.factories import MiniTutorialFactory
-from zds.gallery.factories import GalleryFactory
+from zds.gallery.factories import GalleryFactory, ImageFactory
from zds.utils.models import Alert
-from zds.settings import SITE_ROOT
+from zds.settings import BASE_DIR
overrided_zds_app = settings.ZDS_APP
-overrided_zds_app['tutorial']['repo_path'] = os.path.join(SITE_ROOT, 'tutoriels-private-test')
-overrided_zds_app['tutorial']['repo_public_path'] = os.path.join(SITE_ROOT, 'tutoriels-public-test')
-overrided_zds_app['article']['repo_path'] = os.path.join(SITE_ROOT, 'article-data-test')
+overrided_zds_app['tutorial']['repo_path'] = os.path.join(BASE_DIR, 'tutoriels-private-test')
+overrided_zds_app['tutorial']['repo_public_path'] = os.path.join(BASE_DIR, 'tutoriels-public-test')
+overrided_zds_app['article']['repo_path'] = os.path.join(BASE_DIR, 'article-data-test')
-@override_settings(MEDIA_ROOT=os.path.join(SITE_ROOT, 'media-test'))
+@override_settings(MEDIA_ROOT=os.path.join(BASE_DIR, 'media-test'))
@override_settings(ZDS_APP=overrided_zds_app)
class MemberModelsTest(TestCase):
@@ -58,6 +58,13 @@ def test_get_avatar_url(self):
user2.avatar_url = testurl
self.assertEqual(user2.get_avatar_url(), testurl)
+ # if url is relative, send absolute url
+ gallerie_avtar = GalleryFactory()
+ image_avatar = ImageFactory(gallery=gallerie_avtar)
+ user2.avatar_url = image_avatar.physical.url
+ self.assertNotEqual(user2.get_avatar_url(), image_avatar.physical.url)
+ self.assertIn("http", user2.get_avatar_url())
+
def test_get_post_count(self):
# Start with 0
self.assertEqual(self.user1.get_post_count(), 0)
diff --git a/zds/member/tests/tests_views.py b/zds/member/tests/tests_views.py
index 87db627a0f..39cd6d990d 100644
--- a/zds/member/tests/tests_views.py
+++ b/zds/member/tests/tests_views.py
@@ -10,7 +10,7 @@
from shutil import rmtree
-from zds.settings import SITE_ROOT
+from zds.settings import BASE_DIR
from zds.forum.models import TopicFollowed
from zds.member.factories import ProfileFactory, StaffProfileFactory, NonAsciiProfileFactory, UserFactory
from zds.mp.factories import PrivateTopicFactory, PrivatePostFactory
@@ -29,12 +29,12 @@
overrided_zds_app = settings.ZDS_APP
-overrided_zds_app['tutorial']['repo_path'] = os.path.join(SITE_ROOT, 'tutoriels-private-test')
-overrided_zds_app['tutorial']['repo_public_path'] = os.path.join(SITE_ROOT, 'tutoriels-public-test')
-overrided_zds_app['article']['repo_path'] = os.path.join(SITE_ROOT, 'article-data-test')
+overrided_zds_app['tutorial']['repo_path'] = os.path.join(BASE_DIR, 'tutoriels-private-test')
+overrided_zds_app['tutorial']['repo_public_path'] = os.path.join(BASE_DIR, 'tutoriels-public-test')
+overrided_zds_app['article']['repo_path'] = os.path.join(BASE_DIR, 'article-data-test')
-@override_settings(MEDIA_ROOT=os.path.join(SITE_ROOT, 'media-test'))
+@override_settings(MEDIA_ROOT=os.path.join(BASE_DIR, 'media-test'))
@override_settings(ZDS_APP=overrided_zds_app)
class MemberTests(TestCase):
@@ -197,22 +197,22 @@ def test_login(self):
# redirection to the "next" page.
result = self.client.post(
reverse('zds.member.views.login_view') +
- '?next=' + reverse('zds.gallery.views.gallery_list'),
+ '?next=' + reverse('gallery-list'),
{'username': user.user.username,
'password': 'hostel77',
'remember': 'remember'},
follow=False)
- self.assertRedirects(result, reverse('zds.gallery.views.gallery_list'))
+ self.assertRedirects(result, reverse('gallery-list'))
# check if the login form will redirect if there is
# a next parameter.
self.client.logout()
result = self.client.get(
reverse('zds.member.views.login_view') +
- '?next=' + reverse('zds.gallery.views.gallery_list'))
+ '?next=' + reverse('gallery-list'))
self.assertContains(result,
reverse('zds.member.views.login_view') +
- '?next=' + reverse('zds.gallery.views.gallery_list'),
+ '?next=' + reverse('gallery-list'),
count=1)
def test_register(self):
diff --git a/zds/member/views.py b/zds/member/views.py
index 2ca6a0e3eb..f54db69d24 100644
--- a/zds/member/views.py
+++ b/zds/member/views.py
@@ -1,5 +1,4 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
+# coding: utf-8
from datetime import datetime, timedelta
import uuid
@@ -85,7 +84,6 @@ class UpdateMember(UpdateView):
form_class = ProfileForm
template_name = 'member/settings/profile.html'
- @method_decorator(can_write_and_read_now)
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(UpdateMember, self).dispatch(*args, **kwargs)
@@ -389,13 +387,18 @@ def modify_profile(request, user_pk):
raise HttpResponseBadRequest
state.apply_sanction(profile, ban)
- msg = state.get_message_sanction() \
- .format(ban.user,
- ban.moderator,
- ban.type,
- state.get_detail(),
- ban.text,
- settings.ZDS_APP['site']['litteral_name'])
+
+ if 'un-ls' in request.POST or 'un-ban' in request.POST:
+ msg = state.get_message_unsanction()
+ else:
+ msg = state.get_message_sanction()
+
+ msg = msg.format(ban.user,
+ ban.moderator,
+ ban.type,
+ state.get_detail(),
+ ban.text,
+ settings.ZDS_APP['site']['litteral_name'])
state.notify_member(ban, msg)
return redirect(profile.get_absolute_url())
diff --git a/zds/mp/factories.py b/zds/mp/factories.py
index de74573c8c..efafb34d32 100644
--- a/zds/mp/factories.py
+++ b/zds/mp/factories.py
@@ -8,9 +8,8 @@
class PrivateTopicFactory(factory.DjangoModelFactory):
FACTORY_FOR = PrivateTopic
- title = factory.Sequence(lambda n: 'Mon Sujet No{0}'.format(n))
- subtitle = factory.Sequence(
- lambda n: 'Sous Titre du sujet No{0}'.format(n))
+ title = factory.Sequence('Mon Sujet No{0}'.format)
+ subtitle = factory.Sequence('Sous Titre du sujet No{0}'.format)
class PrivatePostFactory(factory.DjangoModelFactory):
diff --git a/zds/mp/migrations/0001_initial.py b/zds/mp/migrations/0001_initial.py
index 6057354173..800e6c56c6 100644
--- a/zds/mp/migrations/0001_initial.py
+++ b/zds/mp/migrations/0001_initial.py
@@ -1,207 +1,69 @@
# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
+from __future__ import unicode_literals
+from django.db import models, migrations
+from django.conf import settings
-class Migration(SchemaMigration):
- def forwards(self, orm):
- # Adding model 'PrivateTopic'
- db.create_table(
- u'mp_privatetopic',
- ((u'id',
- self.gf('django.db.models.fields.AutoField')(
- primary_key=True)),
- ('title',
- self.gf('django.db.models.fields.CharField')(
- max_length=80)),
- ('subtitle',
- self.gf('django.db.models.fields.CharField')(
- max_length=200)),
- ('author',
- self.gf('django.db.models.fields.related.ForeignKey')(
- related_name='author',
- to=orm['auth.User'])),
- ('last_message',
- self.gf('django.db.models.fields.related.ForeignKey')(
- related_name='last_message',
- null=True,
- to=orm['mp.PrivatePost'])),
- ('pubdate',
- self.gf('django.db.models.fields.DateTimeField')(
- auto_now_add=True,
- blank=True)),
- ))
- db.send_create_signal(u'mp', ['PrivateTopic'])
+class Migration(migrations.Migration):
- # Adding M2M table for field participants on 'PrivateTopic'
- m2m_table_name = db.shorten_name(u'mp_privatetopic_participants')
- db.create_table(
- m2m_table_name,
- (('id',
- models.AutoField(
- verbose_name='ID',
- primary_key=True,
- auto_created=True)),
- ('privatetopic',
- models.ForeignKey(
- orm[u'mp.privatetopic'],
- null=False)),
- ('user',
- models.ForeignKey(
- orm[u'auth.user'],
- null=False))))
- db.create_unique(m2m_table_name, ['privatetopic_id', 'user_id'])
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
- # Adding model 'PrivatePost'
- db.create_table(
- u'mp_privatepost',
- ((u'id',
- self.gf('django.db.models.fields.AutoField')(
- primary_key=True)),
- ('privatetopic',
- self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['mp.PrivateTopic'])),
- ('author',
- self.gf('django.db.models.fields.related.ForeignKey')(
- related_name='privateposts',
- to=orm['auth.User'])),
- ('text',
- self.gf('django.db.models.fields.TextField')()),
- ('pubdate',
- self.gf('django.db.models.fields.DateTimeField')(
- auto_now_add=True,
- blank=True)),
- ('update',
- self.gf('django.db.models.fields.DateTimeField')(
- null=True,
- blank=True)),
- ('position_in_topic',
- self.gf('django.db.models.fields.IntegerField')()),
- ))
- db.send_create_signal(u'mp', ['PrivatePost'])
-
- # Adding model 'PrivateTopicRead'
- db.create_table(
- u'mp_privatetopicread', ((u'id', self.gf('django.db.models.fields.AutoField')(
- primary_key=True)), ('privatetopic', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['mp.PrivateTopic'])), ('privatepost', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['mp.PrivatePost'])), ('user', self.gf('django.db.models.fields.related.ForeignKey')(
- related_name='privatetopics_read', to=orm['auth.User'])), ))
- db.send_create_signal(u'mp', ['PrivateTopicRead'])
-
- def backwards(self, orm):
- # Deleting model 'PrivateTopic'
- db.delete_table(u'mp_privatetopic')
-
- # Removing M2M table for field participants on 'PrivateTopic'
- db.delete_table(db.shorten_name(u'mp_privatetopic_participants'))
-
- # Deleting model 'PrivatePost'
- db.delete_table(u'mp_privatepost')
-
- # Deleting model 'PrivateTopicRead'
- db.delete_table(u'mp_privatetopicread')
-
- models = {
- u'auth.group': {
- 'Meta': {
- 'object_name': 'Group'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '80'}), 'permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})}, u'auth.permission': {
- 'Meta': {
- 'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, 'codename': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'content_type': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['contenttypes.ContentType']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '50'})}, u'auth.user': {
- 'Meta': {
- 'object_name': 'User'}, 'date_joined': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'email': (
- 'django.db.models.fields.EmailField', [], {
- 'max_length': '75', 'blank': 'True'}), 'first_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'groups': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'is_active': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'is_staff': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'is_superuser': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'last_login': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'last_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'password': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128'}), 'user_permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), 'username': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '30'})}, u'contenttypes.contenttype': {
- 'Meta': {
- 'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'model': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'})}, u'mp.privatepost': {
- 'Meta': {
- 'object_name': 'PrivatePost'}, 'author': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'privateposts'", 'to': u"orm['auth.User']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'position_in_topic': (
- 'django.db.models.fields.IntegerField', [], {}), 'privatetopic': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['mp.PrivateTopic']"}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'auto_now_add': 'True', 'blank': 'True'}), 'text': (
- 'django.db.models.fields.TextField', [], {}), 'update': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'})}, u'mp.privatetopic': {
- 'Meta': {
- 'object_name': 'PrivateTopic'}, 'author': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'author'", 'to': u"orm['auth.User']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'last_message': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'last_message'", 'null': 'True', 'to': u"orm['mp.PrivatePost']"}), 'participants': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'related_name': "'participants'", 'symmetrical': 'False', 'to': u"orm['auth.User']"}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'auto_now_add': 'True', 'blank': 'True'}), 'subtitle': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'})}, u'mp.privatetopicread': {
- 'Meta': {
- 'object_name': 'PrivateTopicRead'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'privatepost': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['mp.PrivatePost']"}), 'privatetopic': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['mp.PrivateTopic']"}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'privatetopics_read'", 'to': u"orm['auth.User']"})}}
-
- complete_apps = ['mp']
+ operations = [
+ migrations.CreateModel(
+ name='PrivatePost',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('text', models.TextField(verbose_name='Texte')),
+ ('text_html', models.TextField(verbose_name='Texte en HTML')),
+ ('pubdate', models.DateTimeField(auto_now_add=True, verbose_name='Date de publication', db_index=True)),
+ ('update', models.DateTimeField(null=True, verbose_name="Date d'\xe9dition", blank=True)),
+ ('position_in_topic', models.IntegerField(verbose_name='Position dans le sujet', db_index=True)),
+ ('author', models.ForeignKey(related_name='privateposts', verbose_name=b'Auteur', to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'verbose_name': 'R\xe9ponse \xe0 un message priv\xe9',
+ 'verbose_name_plural': 'R\xe9ponses \xe0 un message priv\xe9',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='PrivateTopic',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('title', models.CharField(max_length=130, verbose_name='Titre')),
+ ('subtitle', models.CharField(max_length=200, verbose_name='Sous-titre')),
+ ('pubdate', models.DateTimeField(auto_now_add=True, verbose_name='Date de cr\xe9ation', db_index=True)),
+ ('author', models.ForeignKey(related_name='author', verbose_name='Auteur', to=settings.AUTH_USER_MODEL)),
+ ('last_message', models.ForeignKey(related_name='last_message', verbose_name='Dernier message', to='mp.PrivatePost', null=True)),
+ ('participants', models.ManyToManyField(related_name='participants', verbose_name='Participants', to=settings.AUTH_USER_MODEL, db_index=True)),
+ ],
+ options={
+ 'verbose_name': 'Message priv\xe9',
+ 'verbose_name_plural': 'Messages priv\xe9s',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='PrivateTopicRead',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('privatepost', models.ForeignKey(to='mp.PrivatePost')),
+ ('privatetopic', models.ForeignKey(to='mp.PrivateTopic')),
+ ('user', models.ForeignKey(related_name='privatetopics_read', to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'verbose_name': 'Message priv\xe9 lu',
+ 'verbose_name_plural': 'Messages priv\xe9s lus',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.AddField(
+ model_name='privatepost',
+ name='privatetopic',
+ field=models.ForeignKey(verbose_name='Message priv\xe9', to='mp.PrivateTopic'),
+ preserve_default=True,
+ ),
+ ]
diff --git a/zds/mp/migrations/0002_auto__add_field_privatepost_text_html.py b/zds/mp/migrations/0002_auto__add_field_privatepost_text_html.py
deleted file mode 100644
index 66d59ead18..0000000000
--- a/zds/mp/migrations/0002_auto__add_field_privatepost_text_html.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'PrivatePost.text_html'
- db.add_column(u'mp_privatepost', 'text_html',
- self.gf('django.db.models.fields.TextField')(default='Old MP text not parsed in markdown'),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'PrivatePost.text_html'
- db.delete_column(u'mp_privatepost', 'text_html')
-
-
- models = {
- u'auth.group': {
- 'Meta': {'object_name': 'Group'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'auth.permission': {
- 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'mp.privatepost': {
- 'Meta': {'object_name': 'PrivatePost'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'privateposts'", 'to': u"orm['auth.User']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'position_in_topic': ('django.db.models.fields.IntegerField', [], {}),
- 'privatetopic': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['mp.PrivateTopic']"}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {}),
- 'text_html': ('django.db.models.fields.TextField', [], {}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'mp.privatetopic': {
- 'Meta': {'object_name': 'PrivateTopic'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'author'", 'to': u"orm['auth.User']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'last_message': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_message'", 'null': 'True', 'to': u"orm['mp.PrivatePost']"}),
- 'participants': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'participants'", 'symmetrical': 'False', 'to': u"orm['auth.User']"}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'mp.privatetopicread': {
- 'Meta': {'object_name': 'PrivateTopicRead'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'privatepost': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['mp.PrivatePost']"}),
- 'privatetopic': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['mp.PrivateTopic']"}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'privatetopics_read'", 'to': u"orm['auth.User']"})
- }
- }
-
- complete_apps = ['mp']
\ No newline at end of file
diff --git a/zds/mp/migrations/0003_auto__add_index_privatepost_position_in_topic__add_index_privatepost_p.py b/zds/mp/migrations/0003_auto__add_index_privatepost_position_in_topic__add_index_privatepost_p.py
deleted file mode 100644
index c5676c6d91..0000000000
--- a/zds/mp/migrations/0003_auto__add_index_privatepost_position_in_topic__add_index_privatepost_p.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding index on 'PrivatePost', fields ['position_in_topic']
- db.create_index(u'mp_privatepost', ['position_in_topic'])
-
- # Adding index on 'PrivatePost', fields ['pubdate']
- db.create_index(u'mp_privatepost', ['pubdate'])
-
- # Adding index on 'PrivateTopic', fields ['pubdate']
- db.create_index(u'mp_privatetopic', ['pubdate'])
-
-
- def backwards(self, orm):
- # Removing index on 'PrivateTopic', fields ['pubdate']
- db.delete_index(u'mp_privatetopic', ['pubdate'])
-
- # Removing index on 'PrivatePost', fields ['pubdate']
- db.delete_index(u'mp_privatepost', ['pubdate'])
-
- # Removing index on 'PrivatePost', fields ['position_in_topic']
- db.delete_index(u'mp_privatepost', ['position_in_topic'])
-
-
- models = {
- u'auth.group': {
- 'Meta': {'object_name': 'Group'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'auth.permission': {
- 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'mp.privatepost': {
- 'Meta': {'object_name': 'PrivatePost'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'privateposts'", 'to': u"orm['auth.User']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'position_in_topic': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'privatetopic': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['mp.PrivateTopic']"}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {}),
- 'text_html': ('django.db.models.fields.TextField', [], {}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'mp.privatetopic': {
- 'Meta': {'object_name': 'PrivateTopic'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'author'", 'to': u"orm['auth.User']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'last_message': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_message'", 'null': 'True', 'to': u"orm['mp.PrivatePost']"}),
- 'participants': ('django.db.models.fields.related.ManyToManyField', [], {'db_index': 'True', 'related_name': "'participants'", 'symmetrical': 'False', 'to': u"orm['auth.User']"}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'mp.privatetopicread': {
- 'Meta': {'object_name': 'PrivateTopicRead'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'privatepost': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['mp.PrivatePost']"}),
- 'privatetopic': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['mp.PrivateTopic']"}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'privatetopics_read'", 'to': u"orm['auth.User']"})
- }
- }
-
- complete_apps = ['mp']
\ No newline at end of file
diff --git a/zds/mp/migrations/0004_auto__chg_field_privatetopic_title.py b/zds/mp/migrations/0004_auto__chg_field_privatetopic_title.py
deleted file mode 100644
index 731859e0d6..0000000000
--- a/zds/mp/migrations/0004_auto__chg_field_privatetopic_title.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
-
- # Changing field 'PrivateTopic.title'
- db.alter_column(u'mp_privatetopic', 'title', self.gf('django.db.models.fields.CharField')(max_length=130))
-
- def backwards(self, orm):
-
- # Changing field 'PrivateTopic.title'
- db.alter_column(u'mp_privatetopic', 'title', self.gf('django.db.models.fields.CharField')(max_length=80))
-
- models = {
- u'auth.group': {
- 'Meta': {'object_name': 'Group'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'auth.permission': {
- 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'mp.privatepost': {
- 'Meta': {'object_name': 'PrivatePost'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'privateposts'", 'to': u"orm['auth.User']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'position_in_topic': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'privatetopic': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['mp.PrivateTopic']"}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {}),
- 'text_html': ('django.db.models.fields.TextField', [], {}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'mp.privatetopic': {
- 'Meta': {'object_name': 'PrivateTopic'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'author'", 'to': u"orm['auth.User']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'last_message': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_message'", 'null': 'True', 'to': u"orm['mp.PrivatePost']"}),
- 'participants': ('django.db.models.fields.related.ManyToManyField', [], {'db_index': 'True', 'related_name': "'participants'", 'symmetrical': 'False', 'to': u"orm['auth.User']"}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '130'})
- },
- u'mp.privatetopicread': {
- 'Meta': {'object_name': 'PrivateTopicRead'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'privatepost': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['mp.PrivatePost']"}),
- 'privatetopic': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['mp.PrivateTopic']"}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'privatetopics_read'", 'to': u"orm['auth.User']"})
- }
- }
-
- complete_apps = ['mp']
\ No newline at end of file
diff --git a/zds/mp/views.py b/zds/mp/views.py
index 80ceebdc5a..9a60db666c 100644
--- a/zds/mp/views.py
+++ b/zds/mp/views.py
@@ -240,11 +240,11 @@ def post(self, request, *args, **kwargs):
return redirect(reverse('mp-list'))
-class PrivatePostList(SingleObjectMixin, ZdSPagingListView):
+class PrivatePostList(ZdSPagingListView, SingleObjectMixin):
"""
Display a thread and its posts using a pager.
"""
-
+ object = None
paginate_by = settings.ZDS_APP['forum']['posts_per_page']
template_name = 'mp/topic/index.html'
diff --git a/zds/pages/migrations/0001_initial.py b/zds/pages/migrations/0001_initial.py
deleted file mode 100644
index 532f87e278..0000000000
--- a/zds/pages/migrations/0001_initial.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- pass
-
- def backwards(self, orm):
- pass
-
- models = {
-
- }
-
- complete_apps = ['pages']
diff --git a/zds/pages/views.py b/zds/pages/views.py
index a249784271..fcca9c64b0 100644
--- a/zds/pages/views.py
+++ b/zds/pages/views.py
@@ -16,7 +16,7 @@
from zds.article.models import get_last_articles
from zds.member.decorator import can_write_and_read_now
from zds.pages.forms import AssocSubscribeForm
-from zds.settings import SITE_ROOT
+from zds.settings import BASE_DIR
from zds.tutorial.models import get_last_tutorials
from zds.utils.models import Alert
from django.utils.translation import ugettext as _
@@ -38,7 +38,7 @@ def home(request):
articles.append(data)
try:
- with open(os.path.join(SITE_ROOT, 'quotes.txt'), 'r') as fh:
+ with open(os.path.join(BASE_DIR, 'quotes.txt'), 'r') as fh:
quote = random.choice(fh.readlines())
except IOError:
quote = settings.ZDS_APP['site']['slogan']
diff --git a/zds/settings.py b/zds/settings.py
index 7a36f73fe8..96886b1110 100644
--- a/zds/settings.py
+++ b/zds/settings.py
@@ -4,22 +4,17 @@
from django.utils.translation import gettext_lazy as _
+# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
+BASE_DIR = os.path.dirname(os.path.dirname(__file__))
DEBUG = True
TEMPLATE_DEBUG = DEBUG
# INTERNAL_IPS = ('127.0.0.1',) # debug toolbar
-
-ADMINS = (
- ('user', 'mail'),
-)
-
-MANAGERS = ADMINS
-
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
- 'NAME': 'base.db',
+ 'NAME': os.path.join(BASE_DIR, 'base.db'),
'USER': '',
'PASSWORD': '',
'HOST': '',
@@ -37,8 +32,6 @@
# http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = 'fr-fr'
-SITE_ID = 1
-
# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
USE_I18N = True
@@ -55,12 +48,9 @@
('en', _('Anglais')),
)
-
-SITE_ROOT = os.path.realpath(os.path.dirname(os.path.dirname(__file__)))
-
# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/home/media/media.lawrence.com/media/"
-MEDIA_ROOT = os.path.join(SITE_ROOT, 'media')
+MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
@@ -71,7 +61,7 @@
# Don't put anything in this directory yourself; store your static files
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
# Example: "/home/media/media.lawrence.com/static/"
-STATIC_ROOT = os.path.join(SITE_ROOT, 'static')
+STATIC_ROOT = os.path.join(BASE_DIR, 'static')
# URL prefix for static files.
# Example: "http://media.lawrence.com/static/"
@@ -82,7 +72,7 @@
# Put strings here, like "/home/html/static" or "C:/www/django/static".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
- os.path.join(SITE_ROOT, 'dist'),
+ os.path.join(BASE_DIR, 'dist'),
)
# List of finder classes that know how to find static files in
@@ -93,18 +83,11 @@
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
)
-FIXTURE_DIRS = (os.path.join(SITE_ROOT, 'fixtures'))
+FIXTURE_DIRS = (os.path.join(BASE_DIR, 'fixtures'))
# Make this unique, and don't share it with anybody.
SECRET_KEY = 'n!01nl+318#x75_%le8#s0=-*ysw&y49uc#t=*wvi(9hnyii0z'
-# List of callables that know how to import templates from various sources.
-TEMPLATE_LOADERS = (
- 'django.template.loaders.filesystem.Loader',
- 'django.template.loaders.app_directories.Loader',
- # 'django.template.loaders.eggs.Loader',
-)
-
FILE_UPLOAD_HANDLERS = (
"django.core.files.uploadhandler.MemoryFileUploadHandler",
"django.core.files.uploadhandler.TemporaryFileUploadHandler",
@@ -134,7 +117,7 @@
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
- os.path.join(SITE_ROOT, 'templates')
+ os.path.join(BASE_DIR, 'templates')
]
TEMPLATE_CONTEXT_PROCESSORS = (
@@ -168,7 +151,6 @@
'easy_thumbnails',
'easy_thumbnails.optimize',
- 'south',
'crispy_forms',
'haystack',
'munin',
@@ -194,9 +176,7 @@
# 'django.contrib.admindocs',
)
-SOUTH_MIGRATION_MODULES = {
- 'easy_thumbnails': 'easy_thumbnails.south_migrations',
-}
+SITE_ID = 1
THUMBNAIL_ALIASES = {
'': {
@@ -326,7 +306,6 @@
SESSION_ENGINE = "django.contrib.sessions.backends.cached_db"
-AUTH_PROFILE_MODULE = 'member.Profile'
LOGIN_URL = '/membres/connexion'
ABSOLUTE_URL_OVERRIDES = {
@@ -352,7 +331,7 @@
},
}
-GEOIP_PATH = os.path.join(SITE_ROOT, 'geodata')
+GEOIP_PATH = os.path.join(BASE_DIR, 'geodata')
# Fake mails (in console)
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
@@ -369,7 +348,7 @@
SDZ_TUTO_DIR = ''
LOCALE_PATHS = (
- os.path.join(SITE_ROOT, 'conf/locale/'),
+ os.path.join(BASE_DIR, 'conf/locale/'),
)
ZDS_APP = {
@@ -446,11 +425,11 @@
},
'article': {
'home_number': 5,
- 'repo_path': os.path.join(SITE_ROOT, 'articles-data')
+ 'repo_path': os.path.join(BASE_DIR, 'articles-data')
},
'tutorial': {
- 'repo_path': os.path.join(SITE_ROOT, 'tutoriels-private'),
- 'repo_public_path': os.path.join(SITE_ROOT, 'tutoriels-public'),
+ 'repo_path': os.path.join(BASE_DIR, 'tutoriels-private'),
+ 'repo_public_path': os.path.join(BASE_DIR, 'tutoriels-public'),
'default_license_pk': 7,
'home_number': 5,
'helps_per_page': 20
@@ -497,8 +476,13 @@
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = "696570367703-r6hc7mdd27t1sktdkivpnc5b25i0uip2.apps.googleusercontent.com"
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = "mApWNh3stCsYHwsGuWdbZWP8"
+# To remove a useless warning in Django 1.7.
+# See http://daniel.hepper.net/blog/2014/04/fixing-1_6-w001-when-upgrading-from-django-1-5-to-1-7/
+TEST_RUNNER = 'django.test.runner.DiscoverRunner'
+
# Load the production settings, overwrite the existing ones if needed
try:
from settings_prod import *
except ImportError:
pass
+
diff --git a/zds/settings_test.py b/zds/settings_test.py
index 223d8a975c..6db999265e 100644
--- a/zds/settings_test.py
+++ b/zds/settings_test.py
@@ -6,5 +6,6 @@
'PASSWORD': '',
'HOST': '127.0.0.1',
'PORT': '',
+ 'CONN_MAX_AGE': 600,
}
}
diff --git a/zds/tutorial/factories.py b/zds/tutorial/factories.py
index dd9147ee72..e18a035f1a 100644
--- a/zds/tutorial/factories.py
+++ b/zds/tutorial/factories.py
@@ -34,9 +34,8 @@
class BigTutorialFactory(factory.DjangoModelFactory):
FACTORY_FOR = Tutorial
- title = factory.Sequence(lambda n: 'Mon Tutoriel No{0}'.format(n))
- description = factory.Sequence(
- lambda n: 'Description du Tutoriel No{0}'.format(n))
+ title = factory.Sequence('Mon Tutoriel No{0}'.format)
+ description = factory.Sequence('Description du Tutoriel No{0}'.format)
type = 'BIG'
create_at = datetime.now()
introduction = 'introduction.md'
@@ -81,9 +80,8 @@ def _prepare(cls, create, **kwargs):
class MiniTutorialFactory(factory.DjangoModelFactory):
FACTORY_FOR = Tutorial
- title = factory.Sequence(lambda n: 'Mon Tutoriel No{0}'.format(n))
- description = factory.Sequence(
- lambda n: 'Description du Tutoriel No{0}'.format(n))
+ title = factory.Sequence('Mon Tutoriel No{0}'.format)
+ description = factory.Sequence('Description du Tutoriel No{0}'.format)
type = 'MINI'
create_at = datetime.now()
introduction = 'introduction.md'
@@ -132,7 +130,7 @@ def _prepare(cls, create, **kwargs):
class PartFactory(factory.DjangoModelFactory):
FACTORY_FOR = Part
- title = factory.Sequence(lambda n: 'Ma partie No{0}'.format(n))
+ title = factory.Sequence('Ma partie No{0}'.format)
@classmethod
def _prepare(cls, create, **kwargs):
@@ -189,7 +187,7 @@ def _prepare(cls, create, **kwargs):
class ChapterFactory(factory.DjangoModelFactory):
FACTORY_FOR = Chapter
- title = factory.Sequence(lambda n: 'Mon Chapitre No{0}'.format(n))
+ title = factory.Sequence('Mon Chapitre No{0}'.format)
@classmethod
def _prepare(cls, create, **kwargs):
@@ -284,7 +282,7 @@ def _prepare(cls, create, **kwargs):
class ExtractFactory(factory.DjangoModelFactory):
FACTORY_FOR = Extract
- title = factory.Sequence(lambda n: 'Mon Extrait No{0}'.format(n))
+ title = factory.Sequence('Mon Extrait No{0}'.format)
@classmethod
def _prepare(cls, create, **kwargs):
@@ -322,9 +320,9 @@ def _prepare(cls, create, **kwargs):
class SubCategoryFactory(factory.DjangoModelFactory):
FACTORY_FOR = SubCategory
- title = factory.Sequence(lambda n: 'Sous-Categorie {0} pour Tuto'.format(n))
- subtitle = factory.Sequence(lambda n: 'Sous titre de Sous-Categorie {0} pour Tuto'.format(n))
- slug = factory.Sequence(lambda n: 'sous-categorie-{0}'.format(n))
+ title = factory.Sequence('Sous-Categorie {0} pour Tuto'.format)
+ subtitle = factory.Sequence('Sous titre de Sous-Categorie {0} pour Tuto'.format)
+ slug = factory.Sequence('sous-categorie-{0}'.format)
class ValidationFactory(factory.DjangoModelFactory):
diff --git a/zds/tutorial/migrations/0001_initial.py b/zds/tutorial/migrations/0001_initial.py
index 73b4201462..6ab71c75af 100644
--- a/zds/tutorial/migrations/0001_initial.py
+++ b/zds/tutorial/migrations/0001_initial.py
@@ -1,497 +1,171 @@
# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding model 'Tutorial'
- db.create_table(
- u'tutorial_tutorial', ((u'id', self.gf('django.db.models.fields.AutoField')(
- primary_key=True)), ('title', self.gf('django.db.models.fields.CharField')(
- max_length=80)), ('description', self.gf('django.db.models.fields.CharField')(
- max_length=200)), ('slug', self.gf('django.db.models.fields.SlugField')(
- max_length=80)), ('image', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['gallery.Image'], null=True, blank=True)), ('gallery', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['gallery.Gallery'], null=True, blank=True)), ('create_at', self.gf('django.db.models.fields.DateTimeField')()), ('pubdate', self.gf('django.db.models.fields.DateTimeField')(
- null=True, blank=True)), ('update', self.gf('django.db.models.fields.DateTimeField')(
- null=True, blank=True)), ('sha_public', self.gf('django.db.models.fields.CharField')(
- max_length=80, null=True, blank=True)), ('sha_beta', self.gf('django.db.models.fields.CharField')(
- max_length=80, null=True, blank=True)), ('sha_validation', self.gf('django.db.models.fields.CharField')(
- max_length=80, null=True, blank=True)), ('sha_draft', self.gf('django.db.models.fields.CharField')(
- max_length=80, null=True, blank=True)), ('licence', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['utils.Licence'], null=True, blank=True)), ('type', self.gf('django.db.models.fields.CharField')(
- max_length=10)), ('introduction', self.gf('django.db.models.fields.CharField')(
- max_length=200, null=True, blank=True)), ('conclusion', self.gf('django.db.models.fields.CharField')(
- max_length=200, null=True, blank=True)), ('images', self.gf('django.db.models.fields.CharField')(
- max_length=200, null=True, blank=True)), ('last_note', self.gf('django.db.models.fields.related.ForeignKey')(
- blank=True, related_name='last_note', null=True, to=orm['tutorial.Note'])), ('is_locked', self.gf('django.db.models.fields.BooleanField')(
- default=False)), ))
- db.send_create_signal(u'tutorial', ['Tutorial'])
-
- # Adding M2M table for field authors on 'Tutorial'
- m2m_table_name = db.shorten_name(u'tutorial_tutorial_authors')
- db.create_table(
- m2m_table_name, (('id', models.AutoField(
- verbose_name='ID', primary_key=True, auto_created=True)), ('tutorial', models.ForeignKey(
- orm[u'tutorial.tutorial'], null=False)), ('user', models.ForeignKey(
- orm[u'auth.user'], null=False))))
- db.create_unique(m2m_table_name, ['tutorial_id', 'user_id'])
-
- # Adding M2M table for field subcategory on 'Tutorial'
- m2m_table_name = db.shorten_name(u'tutorial_tutorial_subcategory')
- db.create_table(
- m2m_table_name, (('id', models.AutoField(
- verbose_name='ID', primary_key=True, auto_created=True)), ('tutorial', models.ForeignKey(
- orm[u'tutorial.tutorial'], null=False)), ('subcategory', models.ForeignKey(
- orm[u'utils.subcategory'], null=False))))
- db.create_unique(m2m_table_name, ['tutorial_id', 'subcategory_id'])
-
- # Adding model 'Note'
- db.create_table(
- u'tutorial_note',
- ((u'comment_ptr',
- self.gf('django.db.models.fields.related.OneToOneField')(
- to=orm['utils.Comment'],
- unique=True,
- primary_key=True)),
- ('tutorial',
- self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['tutorial.Tutorial'])),
- ))
- db.send_create_signal(u'tutorial', ['Note'])
-
- # Adding model 'TutorialRead'
- db.create_table(
- u'tutorial_tutorialread', ((u'id', self.gf('django.db.models.fields.AutoField')(
- primary_key=True)), ('tutorial', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['tutorial.Tutorial'])), ('note', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['tutorial.Note'])), ('user', self.gf('django.db.models.fields.related.ForeignKey')(
- related_name='tuto_notes_read', to=orm['auth.User'])), ))
- db.send_create_signal(u'tutorial', ['TutorialRead'])
-
- # Adding model 'Part'
- db.create_table(
- u'tutorial_part',
- ((u'id',
- self.gf('django.db.models.fields.AutoField')(
- primary_key=True)),
- ('tutorial',
- self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['tutorial.Tutorial'])),
- ('position_in_tutorial',
- self.gf('django.db.models.fields.IntegerField')()),
- ('title',
- self.gf('django.db.models.fields.CharField')(
- max_length=80)),
- ('slug',
- self.gf('django.db.models.fields.SlugField')(
- max_length=80)),
- ('introduction',
- self.gf('django.db.models.fields.CharField')(
- max_length=200,
- null=True,
- blank=True)),
- ('conclusion',
- self.gf('django.db.models.fields.CharField')(
- max_length=200,
- null=True,
- blank=True)),
- ))
- db.send_create_signal(u'tutorial', ['Part'])
-
- # Adding model 'Chapter'
- db.create_table(
- u'tutorial_chapter', ((u'id', self.gf('django.db.models.fields.AutoField')(
- primary_key=True)), ('part', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['tutorial.Part'], null=True, blank=True)), ('position_in_part', self.gf('django.db.models.fields.IntegerField')(
- null=True, blank=True)), ('image', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['gallery.Image'], null=True, blank=True)), ('position_in_tutorial', self.gf('django.db.models.fields.IntegerField')(
- null=True, blank=True)), ('tutorial', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['tutorial.Tutorial'], null=True, blank=True)), ('title', self.gf('django.db.models.fields.CharField')(
- max_length=80, blank=True)), ('slug', self.gf('django.db.models.fields.SlugField')(
- max_length=80)), ('introduction', self.gf('django.db.models.fields.CharField')(
- max_length=200, null=True, blank=True)), ('conclusion', self.gf('django.db.models.fields.CharField')(
- max_length=200, null=True, blank=True)), ))
- db.send_create_signal(u'tutorial', ['Chapter'])
-
- # Adding model 'Extract'
- db.create_table(
- u'tutorial_extract',
- ((u'id',
- self.gf('django.db.models.fields.AutoField')(
- primary_key=True)),
- ('title',
- self.gf('django.db.models.fields.CharField')(
- max_length=80)),
- ('chapter',
- self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['tutorial.Chapter'])),
- ('position_in_chapter',
- self.gf('django.db.models.fields.IntegerField')()),
- ('text',
- self.gf('django.db.models.fields.CharField')(
- max_length=200,
- null=True,
- blank=True)),
- ))
- db.send_create_signal(u'tutorial', ['Extract'])
-
- # Adding model 'Validation'
- db.create_table(
- u'tutorial_validation',
- ((u'id',
- self.gf('django.db.models.fields.AutoField')(
- primary_key=True)),
- ('tutorial',
- self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['tutorial.Tutorial'],
- null=True,
- blank=True)),
- ('version',
- self.gf('django.db.models.fields.CharField')(
- max_length=80,
- null=True,
- blank=True)),
- ('date_proposition',
- self.gf('django.db.models.fields.DateTimeField')()),
- ('comment_authors',
- self.gf('django.db.models.fields.TextField')()),
- ('validator',
- self.gf('django.db.models.fields.related.ForeignKey')(
- blank=True,
- related_name='author_validations',
- null=True,
- to=orm['auth.User'])),
- ('date_reserve',
- self.gf('django.db.models.fields.DateTimeField')(
- null=True,
- blank=True)),
- ('date_validation',
- self.gf('django.db.models.fields.DateTimeField')(
- null=True,
- blank=True)),
- ('comment_validator',
- self.gf('django.db.models.fields.TextField')(
- null=True,
- blank=True)),
- ('status',
- self.gf('django.db.models.fields.CharField')(
- default='PENDING',
- max_length=10)),
- ))
- db.send_create_signal(u'tutorial', ['Validation'])
-
- def backwards(self, orm):
- # Deleting model 'Tutorial'
- db.delete_table(u'tutorial_tutorial')
-
- # Removing M2M table for field authors on 'Tutorial'
- db.delete_table(db.shorten_name(u'tutorial_tutorial_authors'))
-
- # Removing M2M table for field subcategory on 'Tutorial'
- db.delete_table(db.shorten_name(u'tutorial_tutorial_subcategory'))
-
- # Deleting model 'Note'
- db.delete_table(u'tutorial_note')
-
- # Deleting model 'TutorialRead'
- db.delete_table(u'tutorial_tutorialread')
-
- # Deleting model 'Part'
- db.delete_table(u'tutorial_part')
-
- # Deleting model 'Chapter'
- db.delete_table(u'tutorial_chapter')
-
- # Deleting model 'Extract'
- db.delete_table(u'tutorial_extract')
-
- # Deleting model 'Validation'
- db.delete_table(u'tutorial_validation')
-
- models = {
- u'auth.group': {
- 'Meta': {
- 'object_name': 'Group'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '80'}), 'permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})}, u'auth.permission': {
- 'Meta': {
- 'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, 'codename': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'content_type': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['contenttypes.ContentType']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '50'})}, u'auth.user': {
- 'Meta': {
- 'object_name': 'User'}, 'date_joined': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'email': (
- 'django.db.models.fields.EmailField', [], {
- 'max_length': '75', 'blank': 'True'}), 'first_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'groups': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'is_active': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'is_staff': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'is_superuser': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'last_login': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'last_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'password': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128'}), 'user_permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), 'username': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '30'})}, u'contenttypes.contenttype': {
- 'Meta': {
- 'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'model': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'})}, u'gallery.gallery': {
- 'Meta': {
- 'object_name': 'Gallery'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'auto_now_add': 'True', 'blank': 'True'}), 'slug': (
- 'django.db.models.fields.SlugField', [], {
- 'max_length': '80'}), 'subtitle': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'}), 'update': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'})}, u'gallery.image': {
- 'Meta': {
- 'object_name': 'Image'}, 'gallery': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['gallery.Gallery']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'legend': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80', 'null': 'True', 'blank': 'True'}), 'medium': (
- 'django.db.models.fields.files.ImageField', [], {
- 'max_length': '100', 'null': 'True', 'blank': 'True'}), 'physical': (
- 'django.db.models.fields.files.ImageField', [], {
- 'max_length': '100'}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'auto_now_add': 'True', 'blank': 'True'}), 'slug': (
- 'django.db.models.fields.SlugField', [], {
- 'max_length': '80'}), 'thumb': (
- 'django.db.models.fields.files.ImageField', [], {
- 'max_length': '100', 'null': 'True', 'blank': 'True'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80', 'null': 'True', 'blank': 'True'}), 'update': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'})}, u'tutorial.chapter': {
- 'Meta': {
- 'object_name': 'Chapter'}, 'conclusion': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200', 'null': 'True', 'blank': 'True'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'image': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['gallery.Image']", 'null': 'True', 'blank': 'True'}), 'introduction': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200', 'null': 'True', 'blank': 'True'}), 'part': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['tutorial.Part']", 'null': 'True', 'blank': 'True'}), 'position_in_part': (
- 'django.db.models.fields.IntegerField', [], {
- 'null': 'True', 'blank': 'True'}), 'position_in_tutorial': (
- 'django.db.models.fields.IntegerField', [], {
- 'null': 'True', 'blank': 'True'}), 'slug': (
- 'django.db.models.fields.SlugField', [], {
- 'max_length': '80'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80', 'blank': 'True'}), 'tutorial': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['tutorial.Tutorial']", 'null': 'True', 'blank': 'True'})}, u'tutorial.extract': {
- 'Meta': {
- 'object_name': 'Extract'}, 'chapter': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['tutorial.Chapter']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'position_in_chapter': (
- 'django.db.models.fields.IntegerField', [], {}), 'text': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200', 'null': 'True', 'blank': 'True'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'})}, u'tutorial.note': {
- 'Meta': {
- 'object_name': 'Note', '_ormbases': [u'utils.Comment']}, u'comment_ptr': (
- 'django.db.models.fields.related.OneToOneField', [], {
- 'to': u"orm['utils.Comment']", 'unique': 'True', 'primary_key': 'True'}), 'tutorial': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['tutorial.Tutorial']"})}, u'tutorial.part': {
- 'Meta': {
- 'object_name': 'Part'}, 'conclusion': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200', 'null': 'True', 'blank': 'True'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'introduction': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200', 'null': 'True', 'blank': 'True'}), 'position_in_tutorial': (
- 'django.db.models.fields.IntegerField', [], {}), 'slug': (
- 'django.db.models.fields.SlugField', [], {
- 'max_length': '80'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'}), 'tutorial': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['tutorial.Tutorial']"})}, u'tutorial.tutorial': {
- 'Meta': {
- 'object_name': 'Tutorial'}, 'authors': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'to': u"orm['auth.User']", 'symmetrical': 'False'}), 'conclusion': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200', 'null': 'True', 'blank': 'True'}), 'create_at': (
- 'django.db.models.fields.DateTimeField', [], {}), 'description': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200'}), 'gallery': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['gallery.Gallery']", 'null': 'True', 'blank': 'True'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'image': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['gallery.Image']", 'null': 'True', 'blank': 'True'}), 'images': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200', 'null': 'True', 'blank': 'True'}), 'introduction': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200', 'null': 'True', 'blank': 'True'}), 'is_locked': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'last_note': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'blank': 'True', 'related_name': "'last_note'", 'null': 'True', 'to': u"orm['tutorial.Note']"}), 'licence': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['utils.Licence']", 'null': 'True', 'blank': 'True'}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'sha_beta': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80', 'null': 'True', 'blank': 'True'}), 'sha_draft': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80', 'null': 'True', 'blank': 'True'}), 'sha_public': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80', 'null': 'True', 'blank': 'True'}), 'sha_validation': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80', 'null': 'True', 'blank': 'True'}), 'slug': (
- 'django.db.models.fields.SlugField', [], {
- 'max_length': '80'}), 'subcategory': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'to': u"orm['utils.SubCategory']", 'null': 'True', 'blank': 'True'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'}), 'type': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '10'}), 'update': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'})}, u'tutorial.tutorialread': {
- 'Meta': {
- 'object_name': 'TutorialRead'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'note': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['tutorial.Note']"}), 'tutorial': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['tutorial.Tutorial']"}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'tuto_notes_read'", 'to': u"orm['auth.User']"})}, u'tutorial.validation': {
- 'Meta': {
- 'object_name': 'Validation'}, 'comment_authors': (
- 'django.db.models.fields.TextField', [], {}), 'comment_validator': (
- 'django.db.models.fields.TextField', [], {
- 'null': 'True', 'blank': 'True'}), 'date_proposition': (
- 'django.db.models.fields.DateTimeField', [], {}), 'date_reserve': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'date_validation': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'status': (
- 'django.db.models.fields.CharField', [], {
- 'default': "'PENDING'", 'max_length': '10'}), 'tutorial': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['tutorial.Tutorial']", 'null': 'True', 'blank': 'True'}), 'validator': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'blank': 'True', 'related_name': "'author_validations'", 'null': 'True', 'to': u"orm['auth.User']"}), 'version': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80', 'null': 'True', 'blank': 'True'})}, u'utils.alert': {
- 'Meta': {
- 'object_name': 'Alert'}, 'author': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'alerts'", 'to': u"orm['auth.User']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'text': (
- 'django.db.models.fields.TextField', [], {})}, u'utils.comment': {
- 'Meta': {
- 'object_name': 'Comment'}, 'alerts': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'to': u"orm['utils.Alert']", 'null': 'True', 'blank': 'True'}), 'author': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'comments'", 'to': u"orm['auth.User']"}), 'dislike': (
- 'django.db.models.fields.IntegerField', [], {
- 'default': '0'}), 'editor': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'blank': 'True', 'related_name': "'comments-editor'", 'null': 'True', 'to': u"orm['auth.User']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'ip_address': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '15'}), 'is_visible': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'like': (
- 'django.db.models.fields.IntegerField', [], {
- 'default': '0'}), 'position': (
- 'django.db.models.fields.IntegerField', [], {}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'auto_now_add': 'True', 'blank': 'True'}), 'text': (
- 'django.db.models.fields.TextField', [], {}), 'text_hidden': (
- 'django.db.models.fields.CharField', [], {
- 'default': "''", 'max_length': '80'}), 'text_html': (
- 'django.db.models.fields.TextField', [], {}), 'update': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'})}, u'utils.licence': {
- 'Meta': {
- 'object_name': 'Licence'}, 'code': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '20'}), 'description': (
- 'django.db.models.fields.TextField', [], {}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'})}, u'utils.subcategory': {
- 'Meta': {
- 'object_name': 'SubCategory'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'image': (
- 'django.db.models.fields.files.ImageField', [], {
- 'max_length': '100', 'null': 'True', 'blank': 'True'}), 'slug': (
- 'django.db.models.fields.SlugField', [], {
- 'max_length': '80'}), 'subtitle': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'})}}
-
- complete_apps = ['tutorial']
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+import django.db.models.deletion
+from django.conf import settings
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('utils', '0001_initial'),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ('gallery', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Chapter',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('position_in_part', models.IntegerField(db_index=True, null=True, verbose_name=b'Position dans la partie', blank=True)),
+ ('position_in_tutorial', models.IntegerField(null=True, verbose_name=b'Position dans le tutoriel', blank=True)),
+ ('title', models.CharField(max_length=80, verbose_name=b'Titre', blank=True)),
+ ('slug', models.SlugField(max_length=80)),
+ ('introduction', models.CharField(max_length=200, null=True, verbose_name=b'chemin relatif introduction', blank=True)),
+ ('conclusion', models.CharField(max_length=200, null=True, verbose_name=b'chemin relatif conclusion', blank=True)),
+ ('image', models.ForeignKey(verbose_name=b'Image du chapitre', blank=True, to='gallery.Image', null=True)),
+ ],
+ options={
+ 'verbose_name': 'Chapitre',
+ 'verbose_name_plural': 'Chapitres',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='Extract',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('title', models.CharField(max_length=80, verbose_name=b'Titre')),
+ ('position_in_chapter', models.IntegerField(verbose_name=b'Position dans le chapitre', db_index=True)),
+ ('text', models.CharField(max_length=200, null=True, verbose_name=b'chemin relatif du texte', blank=True)),
+ ('chapter', models.ForeignKey(verbose_name=b'Chapitre parent', to='tutorial.Chapter')),
+ ],
+ options={
+ 'verbose_name': 'Extrait',
+ 'verbose_name_plural': 'Extraits',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='Note',
+ fields=[
+ ('comment_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='utils.Comment')),
+ ],
+ options={
+ 'verbose_name': 'note sur un tutoriel',
+ 'verbose_name_plural': 'notes sur un tutoriel',
+ },
+ bases=('utils.comment',),
+ ),
+ migrations.CreateModel(
+ name='Part',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('position_in_tutorial', models.IntegerField(verbose_name=b'Position dans le tutoriel', db_index=True)),
+ ('title', models.CharField(max_length=80, verbose_name=b'Titre')),
+ ('slug', models.SlugField(max_length=80)),
+ ('introduction', models.CharField(max_length=200, null=True, verbose_name=b'chemin relatif introduction', blank=True)),
+ ('conclusion', models.CharField(max_length=200, null=True, verbose_name=b'chemin relatif conclusion', blank=True)),
+ ],
+ options={
+ 'verbose_name': 'Partie',
+ 'verbose_name_plural': 'Parties',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='Tutorial',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('title', models.CharField(max_length=80, verbose_name=b'Titre')),
+ ('description', models.CharField(max_length=200, verbose_name=b'Description')),
+ ('source', models.CharField(max_length=200, verbose_name=b'Source')),
+ ('slug', models.SlugField(max_length=80)),
+ ('create_at', models.DateTimeField(verbose_name=b'Date de cr\xc3\xa9ation')),
+ ('pubdate', models.DateTimeField(db_index=True, null=True, verbose_name=b'Date de publication', blank=True)),
+ ('update', models.DateTimeField(null=True, verbose_name=b'Date de mise \xc3\xa0 jour', blank=True)),
+ ('sha_public', models.CharField(db_index=True, max_length=80, null=True, verbose_name=b'Sha1 de la version publique', blank=True)),
+ ('sha_beta', models.CharField(db_index=True, max_length=80, null=True, verbose_name=b'Sha1 de la version beta publique', blank=True)),
+ ('sha_validation', models.CharField(db_index=True, max_length=80, null=True, verbose_name=b'Sha1 de la version en validation', blank=True)),
+ ('sha_draft', models.CharField(db_index=True, max_length=80, null=True, verbose_name=b'Sha1 de la version de r\xc3\xa9daction', blank=True)),
+ ('type', models.CharField(db_index=True, max_length=10, choices=[(b'MINI', b'Mini-tuto'), (b'BIG', b'Big-tuto')])),
+ ('introduction', models.CharField(max_length=200, null=True, verbose_name=b'chemin relatif introduction', blank=True)),
+ ('conclusion', models.CharField(max_length=200, null=True, verbose_name=b'chemin relatif conclusion', blank=True)),
+ ('images', models.CharField(max_length=200, null=True, verbose_name=b'chemin relatif images', blank=True)),
+ ('is_locked', models.BooleanField(default=False, verbose_name=b'Est verrouill\xc3\xa9')),
+ ('js_support', models.BooleanField(default=False, verbose_name=b'Support du Javascript')),
+ ('authors', models.ManyToManyField(to=settings.AUTH_USER_MODEL, verbose_name=b'Auteurs', db_index=True)),
+ ('gallery', models.ForeignKey(verbose_name=b"Galerie d'images", blank=True, to='gallery.Gallery', null=True)),
+ ('helps', models.ManyToManyField(to='utils.HelpWriting', verbose_name=b'Aides', db_index=True)),
+ ('image', models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, verbose_name=b'Image du tutoriel', blank=True, to='gallery.Image', null=True)),
+ ('last_note', models.ForeignKey(related_name='last_note', verbose_name=b'Derniere note', blank=True, to='tutorial.Note', null=True)),
+ ('licence', models.ForeignKey(verbose_name=b'Licence', blank=True, to='utils.Licence', null=True)),
+ ('subcategory', models.ManyToManyField(db_index=True, to='utils.SubCategory', null=True, verbose_name=b'Sous-Cat\xc3\xa9gorie', blank=True)),
+ ],
+ options={
+ 'verbose_name': 'Tutoriel',
+ 'verbose_name_plural': 'Tutoriels',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='TutorialRead',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('note', models.ForeignKey(to='tutorial.Note')),
+ ('tutorial', models.ForeignKey(to='tutorial.Tutorial')),
+ ('user', models.ForeignKey(related_name='tuto_notes_read', to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'verbose_name': 'Tutoriel lu',
+ 'verbose_name_plural': 'Tutoriels lus',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='Validation',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('version', models.CharField(db_index=True, max_length=80, null=True, verbose_name=b'Sha1 de la version', blank=True)),
+ ('date_proposition', models.DateTimeField(verbose_name=b'Date de proposition', db_index=True)),
+ ('comment_authors', models.TextField(verbose_name=b"Commentaire de l'auteur")),
+ ('date_reserve', models.DateTimeField(null=True, verbose_name=b'Date de r\xc3\xa9servation', blank=True)),
+ ('date_validation', models.DateTimeField(null=True, verbose_name=b'Date de validation', blank=True)),
+ ('comment_validator', models.TextField(null=True, verbose_name=b'Commentaire du validateur', blank=True)),
+ ('status', models.CharField(default=b'PENDING', max_length=10, choices=[(b'PENDING', b"En attente d'un validateur"), (b'PENDING_V', b'En cours de validation'), (b'ACCEPT', b'Publi\xc3\xa9'), (b'REJECT', b'Rejet\xc3\xa9')])),
+ ('tutorial', models.ForeignKey(verbose_name=b'Tutoriel propos\xc3\xa9', blank=True, to='tutorial.Tutorial', null=True)),
+ ('validator', models.ForeignKey(related_name='author_validations', verbose_name=b'Validateur', blank=True, to=settings.AUTH_USER_MODEL, null=True)),
+ ],
+ options={
+ 'verbose_name': 'Validation',
+ 'verbose_name_plural': 'Validations',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.AddField(
+ model_name='part',
+ name='tutorial',
+ field=models.ForeignKey(verbose_name=b'Tutoriel parent', to='tutorial.Tutorial'),
+ preserve_default=True,
+ ),
+ migrations.AddField(
+ model_name='note',
+ name='tutorial',
+ field=models.ForeignKey(verbose_name=b'Tutoriel', to='tutorial.Tutorial'),
+ preserve_default=True,
+ ),
+ migrations.AddField(
+ model_name='chapter',
+ name='part',
+ field=models.ForeignKey(verbose_name=b'Partie parente', blank=True, to='tutorial.Part', null=True),
+ preserve_default=True,
+ ),
+ migrations.AddField(
+ model_name='chapter',
+ name='tutorial',
+ field=models.ForeignKey(verbose_name=b'Tutoriel parent', blank=True, to='tutorial.Tutorial', null=True),
+ preserve_default=True,
+ ),
+ ]
diff --git a/zds/tutorial/migrations/0002_auto__add_index_tutorial_pubdate__add_index_tutorial_sha_public__add_i.py b/zds/tutorial/migrations/0002_auto__add_index_tutorial_pubdate__add_index_tutorial_sha_public__add_i.py
deleted file mode 100644
index 6f82290777..0000000000
--- a/zds/tutorial/migrations/0002_auto__add_index_tutorial_pubdate__add_index_tutorial_sha_public__add_i.py
+++ /dev/null
@@ -1,253 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding index on 'Tutorial', fields ['pubdate']
- db.create_index(u'tutorial_tutorial', ['pubdate'])
-
- # Adding index on 'Tutorial', fields ['sha_public']
- db.create_index(u'tutorial_tutorial', ['sha_public'])
-
- # Adding index on 'Tutorial', fields ['sha_beta']
- db.create_index(u'tutorial_tutorial', ['sha_beta'])
-
- # Adding index on 'Tutorial', fields ['sha_validation']
- db.create_index(u'tutorial_tutorial', ['sha_validation'])
-
- # Adding index on 'Tutorial', fields ['sha_draft']
- db.create_index(u'tutorial_tutorial', ['sha_draft'])
-
- # Adding index on 'Tutorial', fields ['type']
- db.create_index(u'tutorial_tutorial', ['type'])
-
- # Adding index on 'Chapter', fields ['position_in_part']
- db.create_index(u'tutorial_chapter', ['position_in_part'])
-
- # Adding index on 'Extract', fields ['position_in_chapter']
- db.create_index(u'tutorial_extract', ['position_in_chapter'])
-
- # Adding index on 'Part', fields ['position_in_tutorial']
- db.create_index(u'tutorial_part', ['position_in_tutorial'])
-
- # Adding index on 'Validation', fields ['version']
- db.create_index(u'tutorial_validation', ['version'])
-
- # Adding index on 'Validation', fields ['date_proposition']
- db.create_index(u'tutorial_validation', ['date_proposition'])
-
-
- def backwards(self, orm):
- # Removing index on 'Validation', fields ['date_proposition']
- db.delete_index(u'tutorial_validation', ['date_proposition'])
-
- # Removing index on 'Validation', fields ['version']
- db.delete_index(u'tutorial_validation', ['version'])
-
- # Removing index on 'Part', fields ['position_in_tutorial']
- db.delete_index(u'tutorial_part', ['position_in_tutorial'])
-
- # Removing index on 'Extract', fields ['position_in_chapter']
- db.delete_index(u'tutorial_extract', ['position_in_chapter'])
-
- # Removing index on 'Chapter', fields ['position_in_part']
- db.delete_index(u'tutorial_chapter', ['position_in_part'])
-
- # Removing index on 'Tutorial', fields ['type']
- db.delete_index(u'tutorial_tutorial', ['type'])
-
- # Removing index on 'Tutorial', fields ['sha_draft']
- db.delete_index(u'tutorial_tutorial', ['sha_draft'])
-
- # Removing index on 'Tutorial', fields ['sha_validation']
- db.delete_index(u'tutorial_tutorial', ['sha_validation'])
-
- # Removing index on 'Tutorial', fields ['sha_beta']
- db.delete_index(u'tutorial_tutorial', ['sha_beta'])
-
- # Removing index on 'Tutorial', fields ['sha_public']
- db.delete_index(u'tutorial_tutorial', ['sha_public'])
-
- # Removing index on 'Tutorial', fields ['pubdate']
- db.delete_index(u'tutorial_tutorial', ['pubdate'])
-
-
- models = {
- u'auth.group': {
- 'Meta': {'object_name': 'Group'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'auth.permission': {
- 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'gallery.gallery': {
- 'Meta': {'object_name': 'Gallery'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'gallery.image': {
- 'Meta': {'object_name': 'Image'},
- 'gallery': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gallery.Gallery']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'legend': ('django.db.models.fields.CharField', [], {'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'medium': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
- 'physical': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'thumb': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'tutorial.chapter': {
- 'Meta': {'object_name': 'Chapter'},
- 'conclusion': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gallery.Image']", 'null': 'True', 'blank': 'True'}),
- 'introduction': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'part': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Part']", 'null': 'True', 'blank': 'True'}),
- 'position_in_part': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
- 'position_in_tutorial': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']", 'null': 'True', 'blank': 'True'})
- },
- u'tutorial.extract': {
- 'Meta': {'object_name': 'Extract'},
- 'chapter': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Chapter']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'position_in_chapter': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'text': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'tutorial.note': {
- 'Meta': {'object_name': 'Note', '_ormbases': [u'utils.Comment']},
- u'comment_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['utils.Comment']", 'unique': 'True', 'primary_key': 'True'}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']"})
- },
- u'tutorial.part': {
- 'Meta': {'object_name': 'Part'},
- 'conclusion': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'introduction': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'position_in_tutorial': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']"})
- },
- u'tutorial.tutorial': {
- 'Meta': {'object_name': 'Tutorial'},
- 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.User']", 'db_index': 'True', 'symmetrical': 'False'}),
- 'conclusion': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'create_at': ('django.db.models.fields.DateTimeField', [], {}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'gallery': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gallery.Gallery']", 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gallery.Image']", 'null': 'True', 'blank': 'True'}),
- 'images': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'introduction': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'is_locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_note': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_note'", 'null': 'True', 'to': u"orm['tutorial.Note']"}),
- 'licence': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['utils.Licence']", 'null': 'True', 'blank': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
- 'sha_beta': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'sha_draft': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'sha_public': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'sha_validation': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'subcategory': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['utils.SubCategory']", 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'type': ('django.db.models.fields.CharField', [], {'max_length': '10', 'db_index': 'True'}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'tutorial.tutorialread': {
- 'Meta': {'object_name': 'TutorialRead'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'note': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Note']"}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']"}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tuto_notes_read'", 'to': u"orm['auth.User']"})
- },
- u'tutorial.validation': {
- 'Meta': {'object_name': 'Validation'},
- 'comment_authors': ('django.db.models.fields.TextField', [], {}),
- 'comment_validator': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
- 'date_proposition': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
- 'date_reserve': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'date_validation': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'status': ('django.db.models.fields.CharField', [], {'default': "'PENDING'", 'max_length': '10'}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']", 'null': 'True', 'blank': 'True'}),
- 'validator': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'author_validations'", 'null': 'True', 'to': u"orm['auth.User']"}),
- 'version': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'})
- },
- u'utils.comment': {
- 'Meta': {'object_name': 'Comment'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': u"orm['auth.User']"}),
- 'dislike': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'editor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments-editor'", 'null': 'True', 'to': u"orm['auth.User']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'ip_address': ('django.db.models.fields.CharField', [], {'max_length': '39'}),
- 'is_visible': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'like': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'position': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {}),
- 'text_hidden': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '80'}),
- 'text_html': ('django.db.models.fields.TextField', [], {}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'utils.licence': {
- 'Meta': {'object_name': 'Licence'},
- 'code': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
- 'description': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'utils.subcategory': {
- 'Meta': {'object_name': 'SubCategory'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- }
- }
-
- complete_apps = ['tutorial']
\ No newline at end of file
diff --git a/zds/tutorial/migrations/0003_auto__chg_field_tutorial_image.py b/zds/tutorial/migrations/0003_auto__chg_field_tutorial_image.py
deleted file mode 100644
index 454501ec40..0000000000
--- a/zds/tutorial/migrations/0003_auto__chg_field_tutorial_image.py
+++ /dev/null
@@ -1,193 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
-
- # Changing field 'Tutorial.image'
- db.alter_column(u'tutorial_tutorial', 'image_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['gallery.Image'], null=True, on_delete=models.SET_NULL))
-
- def backwards(self, orm):
-
- # Changing field 'Tutorial.image'
- db.alter_column(u'tutorial_tutorial', 'image_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['gallery.Image'], null=True))
-
- models = {
- u'auth.group': {
- 'Meta': {'object_name': 'Group'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'auth.permission': {
- 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'gallery.gallery': {
- 'Meta': {'object_name': 'Gallery'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'gallery.image': {
- 'Meta': {'object_name': 'Image'},
- 'gallery': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gallery.Gallery']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'legend': ('django.db.models.fields.CharField', [], {'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'medium': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
- 'physical': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'thumb': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'tutorial.chapter': {
- 'Meta': {'object_name': 'Chapter'},
- 'conclusion': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gallery.Image']", 'null': 'True', 'blank': 'True'}),
- 'introduction': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'part': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Part']", 'null': 'True', 'blank': 'True'}),
- 'position_in_part': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
- 'position_in_tutorial': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']", 'null': 'True', 'blank': 'True'})
- },
- u'tutorial.extract': {
- 'Meta': {'object_name': 'Extract'},
- 'chapter': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Chapter']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'position_in_chapter': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'text': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'tutorial.note': {
- 'Meta': {'object_name': 'Note', '_ormbases': [u'utils.Comment']},
- u'comment_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['utils.Comment']", 'unique': 'True', 'primary_key': 'True'}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']"})
- },
- u'tutorial.part': {
- 'Meta': {'object_name': 'Part'},
- 'conclusion': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'introduction': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'position_in_tutorial': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']"})
- },
- u'tutorial.tutorial': {
- 'Meta': {'object_name': 'Tutorial'},
- 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.User']", 'db_index': 'True', 'symmetrical': 'False'}),
- 'conclusion': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'create_at': ('django.db.models.fields.DateTimeField', [], {}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'gallery': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gallery.Gallery']", 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gallery.Image']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
- 'images': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'introduction': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'is_locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_note': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_note'", 'null': 'True', 'to': u"orm['tutorial.Note']"}),
- 'licence': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['utils.Licence']", 'null': 'True', 'blank': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
- 'sha_beta': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'sha_draft': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'sha_public': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'sha_validation': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'subcategory': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['utils.SubCategory']", 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'type': ('django.db.models.fields.CharField', [], {'max_length': '10', 'db_index': 'True'}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'tutorial.tutorialread': {
- 'Meta': {'object_name': 'TutorialRead'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'note': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Note']"}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']"}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tuto_notes_read'", 'to': u"orm['auth.User']"})
- },
- u'tutorial.validation': {
- 'Meta': {'object_name': 'Validation'},
- 'comment_authors': ('django.db.models.fields.TextField', [], {}),
- 'comment_validator': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
- 'date_proposition': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
- 'date_reserve': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'date_validation': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'status': ('django.db.models.fields.CharField', [], {'default': "'PENDING'", 'max_length': '10'}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']", 'null': 'True', 'blank': 'True'}),
- 'validator': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'author_validations'", 'null': 'True', 'to': u"orm['auth.User']"}),
- 'version': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'})
- },
- u'utils.comment': {
- 'Meta': {'object_name': 'Comment'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': u"orm['auth.User']"}),
- 'dislike': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'editor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments-editor'", 'null': 'True', 'to': u"orm['auth.User']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'ip_address': ('django.db.models.fields.CharField', [], {'max_length': '39'}),
- 'is_visible': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'like': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'position': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {}),
- 'text_hidden': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '80'}),
- 'text_html': ('django.db.models.fields.TextField', [], {}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'utils.licence': {
- 'Meta': {'object_name': 'Licence'},
- 'code': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
- 'description': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'utils.subcategory': {
- 'Meta': {'object_name': 'SubCategory'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- }
- }
-
- complete_apps = ['tutorial']
\ No newline at end of file
diff --git a/zds/tutorial/migrations/0004_auto__add_field_tutorial_source.py b/zds/tutorial/migrations/0004_auto__add_field_tutorial_source.py
deleted file mode 100644
index 55152b1ad7..0000000000
--- a/zds/tutorial/migrations/0004_auto__add_field_tutorial_source.py
+++ /dev/null
@@ -1,194 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'Tutorial.source'
- db.add_column(u'tutorial_tutorial', 'source',
- self.gf('django.db.models.fields.CharField')(default='', max_length=200),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'Tutorial.source'
- db.delete_column(u'tutorial_tutorial', 'source')
-
-
- models = {
- u'auth.group': {
- 'Meta': {'object_name': 'Group'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'auth.permission': {
- 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'gallery.gallery': {
- 'Meta': {'object_name': 'Gallery'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'gallery.image': {
- 'Meta': {'object_name': 'Image'},
- 'gallery': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gallery.Gallery']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'legend': ('django.db.models.fields.CharField', [], {'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'physical': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'tutorial.chapter': {
- 'Meta': {'object_name': 'Chapter'},
- 'conclusion': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gallery.Image']", 'null': 'True', 'blank': 'True'}),
- 'introduction': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'part': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Part']", 'null': 'True', 'blank': 'True'}),
- 'position_in_part': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
- 'position_in_tutorial': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']", 'null': 'True', 'blank': 'True'})
- },
- u'tutorial.extract': {
- 'Meta': {'object_name': 'Extract'},
- 'chapter': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Chapter']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'position_in_chapter': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'text': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'tutorial.note': {
- 'Meta': {'object_name': 'Note', '_ormbases': [u'utils.Comment']},
- u'comment_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['utils.Comment']", 'unique': 'True', 'primary_key': 'True'}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']"})
- },
- u'tutorial.part': {
- 'Meta': {'object_name': 'Part'},
- 'conclusion': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'introduction': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'position_in_tutorial': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']"})
- },
- u'tutorial.tutorial': {
- 'Meta': {'object_name': 'Tutorial'},
- 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.User']", 'db_index': 'True', 'symmetrical': 'False'}),
- 'conclusion': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'create_at': ('django.db.models.fields.DateTimeField', [], {}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'gallery': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gallery.Gallery']", 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gallery.Image']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
- 'images': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'introduction': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'is_locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_note': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_note'", 'null': 'True', 'to': u"orm['tutorial.Note']"}),
- 'licence': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['utils.Licence']", 'null': 'True', 'blank': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
- 'sha_beta': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'sha_draft': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'sha_public': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'sha_validation': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'source': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'subcategory': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['utils.SubCategory']", 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'type': ('django.db.models.fields.CharField', [], {'max_length': '10', 'db_index': 'True'}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'tutorial.tutorialread': {
- 'Meta': {'object_name': 'TutorialRead'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'note': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Note']"}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']"}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tuto_notes_read'", 'to': u"orm['auth.User']"})
- },
- u'tutorial.validation': {
- 'Meta': {'object_name': 'Validation'},
- 'comment_authors': ('django.db.models.fields.TextField', [], {}),
- 'comment_validator': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
- 'date_proposition': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
- 'date_reserve': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'date_validation': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'status': ('django.db.models.fields.CharField', [], {'default': "'PENDING'", 'max_length': '10'}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']", 'null': 'True', 'blank': 'True'}),
- 'validator': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'author_validations'", 'null': 'True', 'to': u"orm['auth.User']"}),
- 'version': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'})
- },
- u'utils.comment': {
- 'Meta': {'object_name': 'Comment'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': u"orm['auth.User']"}),
- 'dislike': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'editor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments-editor'", 'null': 'True', 'to': u"orm['auth.User']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'ip_address': ('django.db.models.fields.CharField', [], {'max_length': '39'}),
- 'is_visible': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'like': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'position': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {}),
- 'text_hidden': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '80'}),
- 'text_html': ('django.db.models.fields.TextField', [], {}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'utils.licence': {
- 'Meta': {'object_name': 'Licence'},
- 'code': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
- 'description': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'utils.subcategory': {
- 'Meta': {'object_name': 'SubCategory'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- }
- }
-
- complete_apps = ['tutorial']
\ No newline at end of file
diff --git a/zds/tutorial/migrations/0005_auto.py b/zds/tutorial/migrations/0005_auto.py
deleted file mode 100644
index ad0ae067ba..0000000000
--- a/zds/tutorial/migrations/0005_auto.py
+++ /dev/null
@@ -1,207 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding M2M table for field helps on 'Tutorial'
- m2m_table_name = db.shorten_name(u'tutorial_tutorial_helps')
- db.create_table(m2m_table_name, (
- ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
- ('tutorial', models.ForeignKey(orm[u'tutorial.tutorial'], null=False)),
- ('helpwriting', models.ForeignKey(orm[u'utils.helpwriting'], null=False))
- ))
- db.create_unique(m2m_table_name, ['tutorial_id', 'helpwriting_id'])
-
-
- def backwards(self, orm):
- # Removing M2M table for field helps on 'Tutorial'
- db.delete_table(db.shorten_name(u'tutorial_tutorial_helps'))
-
-
- models = {
- u'auth.group': {
- 'Meta': {'object_name': 'Group'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'auth.permission': {
- 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'gallery.gallery': {
- 'Meta': {'object_name': 'Gallery'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'gallery.image': {
- 'Meta': {'object_name': 'Image'},
- 'gallery': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gallery.Gallery']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'legend': ('django.db.models.fields.CharField', [], {'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'physical': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'tutorial.chapter': {
- 'Meta': {'object_name': 'Chapter'},
- 'conclusion': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gallery.Image']", 'null': 'True', 'blank': 'True'}),
- 'introduction': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'part': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Part']", 'null': 'True', 'blank': 'True'}),
- 'position_in_part': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
- 'position_in_tutorial': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']", 'null': 'True', 'blank': 'True'})
- },
- u'tutorial.extract': {
- 'Meta': {'object_name': 'Extract'},
- 'chapter': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Chapter']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'position_in_chapter': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'text': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'tutorial.note': {
- 'Meta': {'object_name': 'Note', '_ormbases': [u'utils.Comment']},
- u'comment_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['utils.Comment']", 'unique': 'True', 'primary_key': 'True'}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']"})
- },
- u'tutorial.part': {
- 'Meta': {'object_name': 'Part'},
- 'conclusion': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'introduction': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'position_in_tutorial': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']"})
- },
- u'tutorial.tutorial': {
- 'Meta': {'object_name': 'Tutorial'},
- 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.User']", 'db_index': 'True', 'symmetrical': 'False'}),
- 'conclusion': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'create_at': ('django.db.models.fields.DateTimeField', [], {}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'gallery': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gallery.Gallery']", 'null': 'True', 'blank': 'True'}),
- 'helps': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['utils.HelpWriting']", 'db_index': 'True', 'symmetrical': 'False'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gallery.Image']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
- 'images': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'introduction': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'is_locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_note': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_note'", 'null': 'True', 'to': u"orm['tutorial.Note']"}),
- 'licence': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['utils.Licence']", 'null': 'True', 'blank': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
- 'sha_beta': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'sha_draft': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'sha_public': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'sha_validation': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'source': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'subcategory': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['utils.SubCategory']", 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'type': ('django.db.models.fields.CharField', [], {'max_length': '10', 'db_index': 'True'}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'tutorial.tutorialread': {
- 'Meta': {'object_name': 'TutorialRead'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'note': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Note']"}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']"}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tuto_notes_read'", 'to': u"orm['auth.User']"})
- },
- u'tutorial.validation': {
- 'Meta': {'object_name': 'Validation'},
- 'comment_authors': ('django.db.models.fields.TextField', [], {}),
- 'comment_validator': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
- 'date_proposition': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
- 'date_reserve': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'date_validation': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'status': ('django.db.models.fields.CharField', [], {'default': "'PENDING'", 'max_length': '10'}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']", 'null': 'True', 'blank': 'True'}),
- 'validator': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'author_validations'", 'null': 'True', 'to': u"orm['auth.User']"}),
- 'version': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'})
- },
- u'utils.comment': {
- 'Meta': {'object_name': 'Comment'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': u"orm['auth.User']"}),
- 'dislike': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'editor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments-editor'", 'null': 'True', 'to': u"orm['auth.User']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'ip_address': ('django.db.models.fields.CharField', [], {'max_length': '39'}),
- 'is_visible': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'like': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'position': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {}),
- 'text_hidden': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '80'}),
- 'text_html': ('django.db.models.fields.TextField', [], {}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'utils.helpwriting': {
- 'Meta': {'object_name': 'HelpWriting'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '20'}),
- 'tablelabel': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '20'})
- },
- u'utils.licence': {
- 'Meta': {'object_name': 'Licence'},
- 'code': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
- 'description': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'utils.subcategory': {
- 'Meta': {'object_name': 'SubCategory'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- }
- }
-
- complete_apps = ['tutorial']
\ No newline at end of file
diff --git a/zds/tutorial/migrations/0005_auto__add_field_tutorial_js_support.py b/zds/tutorial/migrations/0005_auto__add_field_tutorial_js_support.py
deleted file mode 100644
index 20a5216f02..0000000000
--- a/zds/tutorial/migrations/0005_auto__add_field_tutorial_js_support.py
+++ /dev/null
@@ -1,195 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'Tutorial.js_support'
- db.add_column(u'tutorial_tutorial', 'js_support',
- self.gf('django.db.models.fields.BooleanField')(default=False),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'Tutorial.js_support'
- db.delete_column(u'tutorial_tutorial', 'js_support')
-
-
- models = {
- u'auth.group': {
- 'Meta': {'object_name': 'Group'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'auth.permission': {
- 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'gallery.gallery': {
- 'Meta': {'object_name': 'Gallery'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'gallery.image': {
- 'Meta': {'object_name': 'Image'},
- 'gallery': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gallery.Gallery']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'legend': ('django.db.models.fields.CharField', [], {'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'physical': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'tutorial.chapter': {
- 'Meta': {'object_name': 'Chapter'},
- 'conclusion': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gallery.Image']", 'null': 'True', 'blank': 'True'}),
- 'introduction': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'part': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Part']", 'null': 'True', 'blank': 'True'}),
- 'position_in_part': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
- 'position_in_tutorial': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']", 'null': 'True', 'blank': 'True'})
- },
- u'tutorial.extract': {
- 'Meta': {'object_name': 'Extract'},
- 'chapter': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Chapter']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'position_in_chapter': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'text': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'tutorial.note': {
- 'Meta': {'object_name': 'Note', '_ormbases': [u'utils.Comment']},
- u'comment_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['utils.Comment']", 'unique': 'True', 'primary_key': 'True'}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']"})
- },
- u'tutorial.part': {
- 'Meta': {'object_name': 'Part'},
- 'conclusion': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'introduction': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'position_in_tutorial': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']"})
- },
- u'tutorial.tutorial': {
- 'Meta': {'object_name': 'Tutorial'},
- 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.User']", 'db_index': 'True', 'symmetrical': 'False'}),
- 'conclusion': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'create_at': ('django.db.models.fields.DateTimeField', [], {}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'gallery': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gallery.Gallery']", 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gallery.Image']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
- 'images': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'introduction': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'is_locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'js_support': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_note': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_note'", 'null': 'True', 'to': u"orm['tutorial.Note']"}),
- 'licence': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['utils.Licence']", 'null': 'True', 'blank': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
- 'sha_beta': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'sha_draft': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'sha_public': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'sha_validation': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'source': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'subcategory': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['utils.SubCategory']", 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'type': ('django.db.models.fields.CharField', [], {'max_length': '10', 'db_index': 'True'}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'tutorial.tutorialread': {
- 'Meta': {'object_name': 'TutorialRead'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'note': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Note']"}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']"}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tuto_notes_read'", 'to': u"orm['auth.User']"})
- },
- u'tutorial.validation': {
- 'Meta': {'object_name': 'Validation'},
- 'comment_authors': ('django.db.models.fields.TextField', [], {}),
- 'comment_validator': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
- 'date_proposition': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
- 'date_reserve': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'date_validation': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'status': ('django.db.models.fields.CharField', [], {'default': "'PENDING'", 'max_length': '10'}),
- 'tutorial': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tutorial.Tutorial']", 'null': 'True', 'blank': 'True'}),
- 'validator': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'author_validations'", 'null': 'True', 'to': u"orm['auth.User']"}),
- 'version': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '80', 'null': 'True', 'blank': 'True'})
- },
- u'utils.comment': {
- 'Meta': {'object_name': 'Comment'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': u"orm['auth.User']"}),
- 'dislike': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'editor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments-editor'", 'null': 'True', 'to': u"orm['auth.User']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'ip_address': ('django.db.models.fields.CharField', [], {'max_length': '39'}),
- 'is_visible': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'like': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'position': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {}),
- 'text_hidden': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '80'}),
- 'text_html': ('django.db.models.fields.TextField', [], {}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'utils.licence': {
- 'Meta': {'object_name': 'Licence'},
- 'code': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
- 'description': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'utils.subcategory': {
- 'Meta': {'object_name': 'SubCategory'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- }
- }
-
- complete_apps = ['tutorial']
\ No newline at end of file
diff --git a/zds/tutorial/models.py b/zds/tutorial/models.py
index 1a784d2d7a..4baf6a225f 100644
--- a/zds/tutorial/models.py
+++ b/zds/tutorial/models.py
@@ -135,9 +135,9 @@ def get_absolute_url_online(self):
def get_absolute_url_beta(self):
if self.sha_beta is not None:
- return reverse('zds.tutorial.views.view_tutorial', args=[
+ return reverse('zds.tutorial.views.view_tutorial_beta', args=[
self.pk, slugify(self.title)
- ]) + '?version=' + self.sha_beta
+ ])
else:
return self.get_absolute_url()
@@ -234,9 +234,8 @@ def load_dic(self, mandata, sha=None):
if self.in_beta():
mandata['get_absolute_url_beta'] = reverse(
- 'zds.tutorial.views.view_tutorial',
- args=[self.pk, mandata['slug']]
- ) + '?version=' + self.sha_beta
+ 'zds.tutorial.views.view_tutorial_beta',
+ args=[self.pk, mandata['slug']])
else:
mandata['get_absolute_url_beta'] = reverse(
@@ -591,6 +590,14 @@ def get_absolute_url(self):
self.slug,
])
+ def get_absolute_url_beta(self):
+ return reverse('zds.tutorial.views.view_part_beta', args=[
+ self.tutorial.pk,
+ self.tutorial.slug,
+ self.pk,
+ self.slug,
+ ])
+
def get_absolute_url_online(self):
return reverse('zds.tutorial.views.view_part_online', args=[
self.tutorial.pk,
@@ -757,6 +764,12 @@ def get_absolute_url(self):
else:
return reverse('zds.tutorial.views.index')
+ def get_absolute_url_beta(self):
+ if self.tutorial:
+ return self.tutorial.get_absolute_url_beta()
+ elif self.part:
+ return self.part.get_absolute_url_beta() + '{0}/{1}/'.format(self.pk, self.slug)
+
def get_absolute_url_online(self):
if self.tutorial:
return self.tutorial.get_absolute_url_online()
@@ -968,6 +981,13 @@ def get_absolute_url(self):
slugify(self.title)
)
+ def get_absolute_url_beta(self):
+ return '{0}#{1}-{2}'.format(
+ self.chapter.get_absolute_url_beta(),
+ self.position_in_chapter,
+ slugify(self.title)
+ )
+
def get_absolute_url_online(self):
return '{0}#{1}-{2}'.format(
self.chapter.get_absolute_url_online(),
diff --git a/zds/tutorial/tests/tests.py b/zds/tutorial/tests/tests.py
index 0ef2404daf..22f73e50c0 100644
--- a/zds/tutorial/tests/tests.py
+++ b/zds/tutorial/tests/tests.py
@@ -28,7 +28,7 @@
from zds.gallery.factories import UserGalleryFactory, ImageFactory
from zds.mp.models import PrivateTopic
from zds.forum.models import Topic
-from zds.settings import SITE_ROOT
+from zds.settings import BASE_DIR
from zds.tutorial.factories import BigTutorialFactory, MiniTutorialFactory, PartFactory, \
ChapterFactory, NoteFactory, SubCategoryFactory, LicenceFactory
from zds.gallery.factories import GalleryFactory
@@ -39,12 +39,12 @@
overrided_zds_app = settings.ZDS_APP
-overrided_zds_app['tutorial']['repo_path'] = os.path.join(SITE_ROOT, 'tutoriels-private-test')
-overrided_zds_app['tutorial']['repo_public_path'] = os.path.join(SITE_ROOT, 'tutoriels-public-test')
-overrided_zds_app['article']['repo_path'] = os.path.join(SITE_ROOT, 'article-data-test')
+overrided_zds_app['tutorial']['repo_path'] = os.path.join(BASE_DIR, 'tutoriels-private-test')
+overrided_zds_app['tutorial']['repo_public_path'] = os.path.join(BASE_DIR, 'tutoriels-public-test')
+overrided_zds_app['article']['repo_path'] = os.path.join(BASE_DIR, 'article-data-test')
-@override_settings(MEDIA_ROOT=os.path.join(SITE_ROOT, 'media-test'))
+@override_settings(MEDIA_ROOT=os.path.join(BASE_DIR, 'media-test'))
@override_settings(ZDS_APP=overrided_zds_app)
class BigTutorialTests(TestCase):
@@ -709,7 +709,7 @@ def test_import_tuto(self):
{
'file': open(
os.path.join(
- settings.SITE_ROOT,
+ settings.BASE_DIR,
'fixtures',
'tuto',
'temps-reel-avec-irrlicht',
@@ -717,7 +717,7 @@ def test_import_tuto(self):
'r'),
'images': open(
os.path.join(
- settings.SITE_ROOT,
+ settings.BASE_DIR,
'fixtures',
'tuto',
'temps-reel-avec-irrlicht',
@@ -1456,25 +1456,25 @@ def test_workflow_tuto(self):
# deleted part and section HAVE TO be accessible on beta (get 200)
result = self.client.get(
reverse(
- 'zds.tutorial.views.view_part',
+ 'zds.tutorial.views.view_part_beta',
args=[
tuto.pk,
tuto.slug,
p1.pk,
- p1.slug]) + '?version={}'.format(sha_beta),
+ p1.slug]),
follow=True)
self.assertEqual(result.status_code, 200)
result = self.client.get(
reverse(
- 'zds.tutorial.views.view_chapter',
+ 'zds.tutorial.views.view_chapter_beta',
args=[
tuto.pk,
tuto.slug,
p2.pk,
p2.slug,
c3.pk,
- c3.slug]) + '?version={}'.format(sha_beta),
+ c3.slug]),
follow=True)
self.assertEqual(result.status_code, 200)
@@ -1587,25 +1587,25 @@ def test_workflow_tuto(self):
# deleted part and section still accessible on beta (get 200)
result = self.client.get(
reverse(
- 'zds.tutorial.views.view_part',
+ 'zds.tutorial.views.view_part_beta',
args=[
tuto.pk,
tuto.slug,
p1.pk,
- p1.slug]) + '?version={}'.format(sha_beta),
+ p1.slug]),
follow=True)
self.assertEqual(result.status_code, 200)
result = self.client.get(
reverse(
- 'zds.tutorial.views.view_chapter',
+ 'zds.tutorial.views.view_chapter_beta',
args=[
tuto.pk,
tuto.slug,
p2.pk,
p2.slug,
c3.pk,
- c3.slug]) + '?version={}'.format(sha_beta),
+ c3.slug]),
follow=True)
self.assertEqual(result.status_code, 200)
@@ -2064,7 +2064,7 @@ def test_delete_image_tutorial(self):
# Delete the image of the bigtuto.
response = self.client.post(
- reverse('zds.gallery.views.delete_image'),
+ reverse('gallery-image-delete'),
{
'gallery': self.bigtuto.gallery.pk,
'delete_multi': '',
@@ -2208,11 +2208,10 @@ def test_workflow_beta_tuto(self):
follow=False
)
self.assertEqual(302, response.status_code)
- old_url = url
url = Tutorial.objects.get(pk=self.bigtuto.pk).get_absolute_url_beta()
# test access to new beta url (get 200) :
self.assertEqual(
- self.client.get(old_url).status_code,
+ self.client.get(url).status_code,
200)
# test access for random user to new url (get 200) and old (get 403)
self.assertEqual(
@@ -2223,9 +2222,6 @@ def test_workflow_beta_tuto(self):
self.assertEqual(
self.client.get(url).status_code,
200)
- self.assertEqual(
- self.client.get(old_url).status_code,
- 403)
# then desactive beta :
self.assertEqual(
@@ -2919,7 +2915,7 @@ def test_warn_typo(self):
sent_pm = PrivateTopic.objects.filter(author=self.user.pk).last()
self.assertIn(self.user_author, sent_pm.participants.all()) # author is in participants
self.assertIn(typo_text, sent_pm.last_message.text) # typo is in message
- self.assertIn(Chapter.objects.get(pk=self.chapter1_1.pk).get_absolute_url() + '?version=' + sha_beta,
+ self.assertIn(Chapter.objects.get(pk=self.chapter1_1.pk).get_absolute_url_beta(),
sent_pm.last_message.text) # public url is in message
def tearDown(self):
@@ -2933,7 +2929,7 @@ def tearDown(self):
shutil.rmtree(settings.MEDIA_ROOT)
-@override_settings(MEDIA_ROOT=os.path.join(SITE_ROOT, 'media-test'))
+@override_settings(MEDIA_ROOT=os.path.join(BASE_DIR, 'media-test'))
@override_settings(ZDS_APP=overrided_zds_app)
class MiniTutorialTests(TestCase):
@@ -3416,7 +3412,7 @@ def test_import_tuto(self):
{
'file': open(
os.path.join(
- settings.SITE_ROOT,
+ settings.BASE_DIR,
'fixtures',
'tuto',
'securisez-vos-mots-de-passe-avec-lastpass',
@@ -3424,7 +3420,7 @@ def test_import_tuto(self):
'r'),
'images': open(
os.path.join(
- settings.SITE_ROOT,
+ settings.BASE_DIR,
'fixtures',
'tuto',
'securisez-vos-mots-de-passe-avec-lastpass',
@@ -3673,7 +3669,7 @@ def test_delete_image_tutorial(self):
# Delete the image of the minituto.
response = self.client.post(
- reverse('zds.gallery.views.delete_image'),
+ reverse('gallery-image-delete'),
{
'gallery': self.minituto.gallery.pk,
'delete_multi': '',
@@ -3900,11 +3896,10 @@ def test_workflow_beta_tuto(self):
follow=False
)
self.assertEqual(302, response.status_code)
- old_url = url
url = Tutorial.objects.get(pk=self.minituto.pk).get_absolute_url_beta()
# test access to new beta url (get 200) :
self.assertEqual(
- self.client.get(old_url).status_code,
+ self.client.get(url).status_code,
200)
# test access for random user to new url (get 200) and old (get 403)
self.assertEqual(
@@ -3915,9 +3910,6 @@ def test_workflow_beta_tuto(self):
self.assertEqual(
self.client.get(url).status_code,
200)
- self.assertEqual(
- self.client.get(old_url).status_code,
- 403)
# then desactive beta :
self.assertEqual(
diff --git a/zds/tutorial/tests/tests_feeds.py b/zds/tutorial/tests/tests_feeds.py
index 0a70f8bb6c..887b22c39e 100644
--- a/zds/tutorial/tests/tests_feeds.py
+++ b/zds/tutorial/tests/tests_feeds.py
@@ -11,7 +11,7 @@
from zds.gallery.factories import GalleryFactory
from zds.member.factories import ProfileFactory, StaffProfileFactory
-from zds.settings import SITE_ROOT
+from zds.settings import BASE_DIR
from zds.tutorial.factories import MiniTutorialFactory, ChapterFactory, \
SubCategoryFactory, LicenceFactory
from zds.tutorial.feeds import LastTutorialsFeedRSS, LastTutorialsFeedATOM
@@ -19,12 +19,12 @@
overrided_zds_app = settings.ZDS_APP
-overrided_zds_app['tutorial']['repo_path'] = os.path.join(SITE_ROOT, 'tutoriels-private-test')
-overrided_zds_app['tutorial']['repo_public_path'] = os.path.join(SITE_ROOT, 'tutoriels-public-test')
-overrided_zds_app['article']['repo_path'] = os.path.join(SITE_ROOT, 'article-data-test')
+overrided_zds_app['tutorial']['repo_path'] = os.path.join(BASE_DIR, 'tutoriels-private-test')
+overrided_zds_app['tutorial']['repo_public_path'] = os.path.join(BASE_DIR, 'tutoriels-public-test')
+overrided_zds_app['article']['repo_path'] = os.path.join(BASE_DIR, 'article-data-test')
-@override_settings(MEDIA_ROOT=os.path.join(SITE_ROOT, 'media-test'))
+@override_settings(MEDIA_ROOT=os.path.join(BASE_DIR, 'media-test'))
@override_settings(ZDS_APP=overrided_zds_app)
class LastTutorialsFeedRSSTest(TestCase):
diff --git a/zds/tutorial/urls.py b/zds/tutorial/urls.py
index ade90fccb2..7236d298d4 100644
--- a/zds/tutorial/urls.py
+++ b/zds/tutorial/urls.py
@@ -25,6 +25,18 @@
url(r'^off/(?P\d+)/(?P.+)/$',
'zds.tutorial.views.view_tutorial'),
+ # Beta URLs
+ url(r'^beta/(?P\d+)/(?P.+)/(?P\d+)/(?P.+)/(?P\d+)/(?P.+)/$',
+ 'zds.tutorial.views.view_chapter_beta',
+ name="view-chapter-url-beta"),
+
+ url(r'^beta/(?P\d+)/(?P.+)/(?P\d+)/(?P.+)/$',
+ 'zds.tutorial.views.view_part_beta',
+ name="view-part-url-beta"),
+
+ url(r'^beta/(?P\d+)/(?P.+)/$',
+ 'zds.tutorial.views.view_tutorial_beta'),
+
# View online
url(r'^(?P\d+)/(?P.+)/(?P\d+)/(?P.+)/(?P\d+)/(?P.+)/$',
'zds.tutorial.views.view_chapter_online',
diff --git a/zds/tutorial/views.py b/zds/tutorial/views.py
index ce7a50d62f..b537e6e019 100644
--- a/zds/tutorial/views.py
+++ b/zds/tutorial/views.py
@@ -348,9 +348,12 @@ def valid_tutorial(request):
version=tutorial.sha_validation).latest("date_proposition")
if request.user == validation.validator:
- (output, err) = mep(tutorial, tutorial.sha_validation)
- messages.info(request, output)
- messages.error(request, err)
+ try:
+ mep(tutorial, tutorial.sha_validation)
+ except UnicodeErrorInTutorial as e:
+ messages.error(request, e)
+ return redirect(tutorial.get_absolute_url() + "?version=" + validation.version)
+
validation.comment_validator = request.POST["text"]
validation.status = "ACCEPT"
validation.date_validation = datetime.now()
@@ -408,7 +411,7 @@ def valid_tutorial(request):
def invalid_tutorial(request, tutorial_pk):
"""Staff invalid tutorial of an author."""
- # Retrieve current tutorial
+ # Retrieve current tutorials
tutorial = get_object_or_404(Tutorial, pk=tutorial_pk)
un_mep(tutorial)
@@ -669,7 +672,7 @@ def modify_tutorial(request):
)
return redirect(redirect_url)
- elif "activ_beta" in request.POST:
+ elif ("activ_beta" in request.POST) or ("update_beta" in request.POST):
if "version" in request.POST:
tutorial.sha_beta = request.POST['version']
tutorial.save()
@@ -688,7 +691,6 @@ def modify_tutorial(request):
settings.ZDS_APP['site']['url'] + tutorial.get_absolute_url_beta()))
if topic is None:
forum = get_object_or_404(Forum, pk=settings.ZDS_APP['forum']['beta_forum_id'])
-
create_topic(author=request.user,
forum=forum,
title=_(u"[beta][tutoriel]{0}").format(tutorial.title),
@@ -696,82 +698,51 @@ def modify_tutorial(request):
text=msg,
key=tutorial.pk
)
- tp = Topic.objects.get(key=tutorial.pk)
- bot = get_object_or_404(User, username=settings.ZDS_APP['member']['bot_account'])
- private_mp = \
- (_(u'Bonjour {},\n\n'
- u'Vous venez de mettre votre tutoriel **{}** en beta. La communauté '
- u'pourra le consulter afin de vous faire des retours '
- u'constructifs avant sa soumission en validation.\n\n'
- u'Un sujet dédié pour la beta de votre tutoriel a été '
- u'crée dans le forum et est accessible [ici]({})').format(
- request.user.username,
- tutorial.title,
- settings.ZDS_APP['site']['url'] + tp.get_absolute_url()))
- send_mp(
- bot,
- [request.user],
- _(u"Tutoriel en beta : {0}").format(tutorial.title),
- "",
- private_mp,
- False,
- )
+ if "activ_beta" in request.POST:
+ tp = Topic.objects.get(key=tutorial.pk)
+ bot = get_object_or_404(User, username=settings.ZDS_APP['member']['bot_account'])
+ private_mp = \
+ (_(u'Bonjour {},\n\n'
+ u'Vous venez de mettre votre tutoriel **{}** en beta. La communauté '
+ u'pourra le consulter afin de vous faire des retours '
+ u'constructifs avant sa soumission en validation.\n\n'
+ u'Un sujet dédié pour la beta de votre tutoriel a été '
+ u'crée dans le forum et est accessible [ici]({})').format(
+ request.user.username,
+ tutorial.title,
+ settings.ZDS_APP['site']['url'] + tp.get_absolute_url()))
+ send_mp(
+ bot,
+ [request.user],
+ _(u"Tutoriel en beta : {0}").format(tutorial.title),
+ "",
+ private_mp,
+ False,
+ )
else:
- msg_up = \
- (_(u'Bonjour,\n\n'
- u'La beta du tutoriel est de nouveau active.'
- u'\n\n-> [Lien de la beta du tutoriel : {0}]({1}) <-\n\n'
- u'\n\nMerci pour vos relectures').format(tutorial.title,
- settings.ZDS_APP['site']['url'] +
- tutorial.get_absolute_url_beta()))
- unlock_topic(topic, msg)
+ if "activ_beta" in request.POST:
+ msg_up = \
+ (_(u'Bonjour,\n\n'
+ u'La beta du tutoriel est de nouveau active.'
+ u'\n\n-> [Lien de la beta du tutoriel : {0}]({1}) <-\n\n'
+ u'\n\nMerci pour vos relectures').format(tutorial.title,
+ settings.ZDS_APP['site']['url'] +
+ tutorial.get_absolute_url_beta()))
+ messages.success(request, _(u"La BETA sur ce tutoriel est bien activée."))
+ elif "update_beta" in request.POST:
+ msg_up = \
+ (_(u'Bonjour à tous !\n\n'
+ u'La beta du tutoriel a été mise à jour.'
+ u'\n\n-> [Lien de la beta du tutoriel : {0}]({1}) <-\n\n'
+ u'\n\nMerci pour vos relectures').format(tutorial.title,
+ settings.ZDS_APP['site']['url'] +
+ tutorial.get_absolute_url_beta()))
+ messages.success(request, _(u"La BETA sur ce tutoriel a bien été mise à jour."))
+ unlock_topic(topic)
send_post(topic, msg_up)
-
- messages.success(request, _(u"La BETA sur ce tutoriel est bien activée."))
else:
messages.error(request, _(u"La BETA sur ce tutoriel n'a malheureusement pas pu être activée."))
return redirect(tutorial.get_absolute_url_beta())
- elif "update_beta" in request.POST:
- if "version" in request.POST:
- tutorial.sha_beta = request.POST['version']
- tutorial.save()
- topic = Topic.objects.filter(key=tutorial.pk,
- forum__pk=settings.ZDS_APP['forum']['beta_forum_id']).first()
- msg = \
- (_(u'Bonjour à tous,\n\n'
- u'J\'ai commencé ({0}) la rédaction d\'un tutoriel dont l\'intitulé est **{1}**.\n\n'
- u'J\'aimerai obtenir un maximum de retour sur celui-ci, sur le fond ainsi que '
- u'sur la forme, afin de proposer en validation un texte de qualité.'
- u'\n\nSi vous êtes intéressé, cliquez ci-dessous '
- u'\n\n-> [Lien de la beta du tutoriel : {1}]({2}) <-\n\n'
- u'\n\nMerci d\'avance pour votre aide').format(
- naturaltime(tutorial.create_at),
- tutorial.title,
- settings.ZDS_APP['site']['url'] + tutorial.get_absolute_url_beta()))
- if topic is None:
- forum = get_object_or_404(Forum, pk=settings.ZDS_APP['forum']['beta_forum_id'])
-
- create_topic(author=request.user,
- forum=forum,
- title=u"[beta][tutoriel]{0}".format(tutorial.title),
- subtitle=u"{}".format(tutorial.description),
- text=msg,
- key=tutorial.pk
- )
- else:
- msg_up = \
- (_(u'Bonjour à tous !\n\n'
- u'La beta du tutoriel a été mise à jour.'
- u'\n\n-> [Lien de la beta du tutoriel : {0}]({1}) <-\n\n'
- u'\n\nMerci pour vos relectures').format(tutorial.title,
- settings.ZDS_APP['site']['url'] +
- tutorial.get_absolute_url_beta()))
- unlock_topic(topic, msg)
- send_post(topic, msg_up)
- messages.success(request, _(u"La BETA sur ce tutoriel a bien été mise à jour."))
- else:
- messages.error(request, _(u"La BETA sur ce tutoriel n'a malheureusement pas pu être mise à jour."))
- return redirect(tutorial.get_absolute_url_beta())
elif "desactiv_beta" in request.POST:
tutorial.sha_beta = None
tutorial.save()
@@ -787,15 +758,11 @@ def modify_tutorial(request):
return redirect(tutorial.get_absolute_url())
# No action performed, raise 403
-
raise PermissionDenied
-# Tutorials.
-
-
@login_required
-def view_tutorial(request, tutorial_pk, tutorial_slug):
+def view_tutorial(request, tutorial_pk, tutorial_slug, sha=None):
"""Show the given offline tutorial if exists."""
tutorial = get_object_or_404(Tutorial, pk=tutorial_pk)
@@ -803,13 +770,17 @@ def view_tutorial(request, tutorial_pk, tutorial_slug):
# Retrieve sha given by the user. This sha must to be exist. If it doesn't
# exist, we take draft version of the article.
- try:
- sha = request.GET["version"]
- except KeyError:
- sha = tutorial.sha_draft
+ if sha is None:
+ try:
+ sha = request.GET["version"]
+ except KeyError:
+ sha = tutorial.sha_draft
is_beta = sha == tutorial.sha_beta and tutorial.in_beta()
+ if request.path.startswith("/tutoriels/off") and is_beta:
+ return redirect(tutorial.get_absolute_url_beta())
+
# Only authors of the tutorial and staff can view tutorial in offline.
if request.user not in tutorial.authors.all() and not is_beta:
@@ -911,6 +882,12 @@ def view_tutorial(request, tutorial_pk, tutorial_slug):
})
+@login_required
+def view_tutorial_beta(request, tutorial_pk, tutorial_slug):
+ tutorial = get_object_or_404(Tutorial, pk=tutorial_pk)
+ return view_tutorial(request, tutorial_pk, tutorial_slug, sha=tutorial.sha_beta)
+
+
def view_tutorial_online(request, tutorial_pk, tutorial_slug):
"""Display a tutorial."""
@@ -1287,14 +1264,16 @@ def view_part(
tutorial_slug,
part_pk,
part_slug,
+ sha=None,
):
"""Display a part."""
tutorial = get_object_or_404(Tutorial, pk=tutorial_pk)
- try:
- sha = request.GET["version"]
- except KeyError:
- sha = tutorial.sha_draft
+ if sha is None:
+ try:
+ sha = request.GET["version"]
+ except KeyError:
+ sha = tutorial.sha_draft
is_beta = sha == tutorial.sha_beta and tutorial.in_beta()
@@ -1342,6 +1321,12 @@ def view_part(
part["intro"] = get_blob(repo.commit(sha).tree, part["introduction"])
part["conclu"] = get_blob(repo.commit(sha).tree, part["conclusion"])
final_part = part
+ if request.path.startswith("/tutoriels/off") and is_beta:
+ return redirect(reverse('zds.tutorial.views.view_part_beta', args=[
+ tutorial_pk,
+ tutorial_slug,
+ part_pk,
+ part_slug]))
cpt_p += 1
# if part can't find
@@ -1360,6 +1345,18 @@ def view_part(
"is_js": is_js})
+@login_required
+def view_part_beta(
+ request,
+ tutorial_pk,
+ tutorial_slug,
+ part_pk,
+ part_slug,
+):
+ tutorial = get_object_or_404(Tutorial, pk=tutorial_pk)
+ return view_part(request, tutorial_pk, tutorial_slug, part_pk, part_slug, sha=tutorial.sha_beta)
+
+
def view_part_online(
request,
tutorial_pk,
@@ -1631,15 +1628,17 @@ def view_chapter(
part_slug,
chapter_pk,
chapter_slug,
+ sha=None,
):
"""View chapter."""
tutorial = get_object_or_404(Tutorial, pk=tutorial_pk)
- try:
- sha = request.GET["version"]
- except KeyError:
- sha = tutorial.sha_draft
+ if sha is None:
+ try:
+ sha = request.GET["version"]
+ except KeyError:
+ sha = tutorial.sha_draft
is_beta = sha == tutorial.sha_beta and tutorial.in_beta()
@@ -1701,6 +1700,15 @@ def view_chapter(
if chapter_pk == str(chapter["pk"]):
final_chapter = chapter
final_position = len(chapter_tab) - 1
+
+ if request.path.startswith("/tutoriels/off") and is_beta:
+ return redirect(reverse('zds.tutorial.views.view_chapter_beta', args=[
+ tutorial_pk,
+ tutorial_slug,
+ part_pk,
+ part_slug,
+ chapter_pk,
+ chapter_slug]))
cpt_c += 1
cpt_p += 1
@@ -1726,6 +1734,27 @@ def view_chapter(
})
+@login_required
+def view_chapter_beta(
+ request,
+ tutorial_pk,
+ tutorial_slug,
+ part_pk,
+ part_slug,
+ chapter_pk,
+ chapter_slug,
+):
+ tutorial = get_object_or_404(Tutorial, pk=tutorial_pk)
+ return view_chapter(request,
+ tutorial_pk,
+ tutorial_slug,
+ part_pk,
+ part_slug,
+ chapter_pk,
+ chapter_slug,
+ sha=tutorial.sha_beta)
+
+
def view_chapter_online(
request,
tutorial_pk,
@@ -3059,7 +3088,7 @@ def get_url_images(md_text, pt):
"""find images urls in markdown text and download this."""
regex = ur"(!\[.*?\]\()(.+?)(\))"
- unknow_path = os.path.join(settings.SITE_ROOT, "fixtures", "noir_black.png")
+ unknow_path = os.path.join(settings.BASE_DIR, "fixtures", "noir_black.png")
# if text is empty don't download
@@ -3083,6 +3112,7 @@ def get_url_images(md_text, pt):
os.makedirs(os.path.join(pt, "images"))
# download image
+ filename = filename.decode('utf-8')
down_path = os.path.abspath(os.path.join(pt, "images", filename))
try:
urlretrieve(real_url, down_path)
@@ -3103,7 +3133,7 @@ def get_url_images(md_text, pt):
pass
else:
# relative link
- srcfile = settings.SITE_ROOT + real_url
+ srcfile = settings.BASE_DIR + real_url
if os.path.isfile(srcfile):
dstroot = pt + real_url
dstdir = os.path.dirname(dstroot)
@@ -3162,8 +3192,13 @@ def markdown_to_out(md_text):
md_text)
+class UnicodeErrorInTutorial(Exception):
+
+ def __init__(self, *args, **kwargs):
+ super(UnicodeErrorInTutorial, self).__init__(*args, **kwargs)
+
+
def mep(tutorial, sha):
- (output, err) = (None, None)
repo = Repo(tutorial.get_path())
manifest = get_blob(repo.commit(sha).tree, "manifest.json")
tutorial_version = json_reader.loads(manifest)
@@ -3211,7 +3246,7 @@ def mep(tutorial, sha):
# download images
- get_url_images(md_file_contenu, prod_path)
+ get_url_images(md_file_contenu.encode('utf-8'), prod_path)
# convert to out format
out_file = open(os.path.join(prod_path, fichier), "w")
@@ -3233,7 +3268,12 @@ def mep(tutorial, sha):
else:
is_js = ""
if md_file_contenu is not None:
- html_file.write(emarkdown(md_file_contenu, is_js))
+ try:
+ html_file.write(emarkdown(md_file_contenu, is_js))
+ except (UnicodeEncodeError, UnicodeError):
+ raise UnicodeErrorInTutorial(_(u'Une erreur est survenue lors de la génération du HTML à partir '
+ u'du fichier « {} », vérifiez que le code markdown correspondant ne '
+ u'contient pas d\'erreurs'.format(fichier)))
html_file.close()
# load markdown out
@@ -3265,8 +3305,7 @@ def mep(tutorial, sha):
os.path.join(prod_path, tutorial.slug) +
".md -o " + os.path.join(prod_path,
tutorial.slug) + ".epub" + pandoc_debug_str)
- os.chdir(settings.SITE_ROOT)
- return (output, err)
+ os.chdir(settings.BASE_DIR)
def un_mep(tutorial):
@@ -3726,12 +3765,10 @@ def warn_typo(request, obj_type, obj_pk):
msg += _(u'La correction concerne le chapitre [{}]({}) de la partie [{}]({}).\n\n').format(
chapter.title,
settings.ZDS_APP['site']['url'] +
- chapter.get_absolute_url() +
- '?version=' + tutorial.sha_beta,
+ chapter.get_absolute_url_beta(),
chapter.part.title,
settings.ZDS_APP['site']['url'] +
- chapter.part.get_absolute_url() +
- '?version=' + tutorial.sha_beta
+ chapter.part.get_absolute_url_beta()
)
msg += _(u'Voici son message :\n\n{}').format(explanation)
@@ -3755,7 +3792,7 @@ def warn_typo(request, obj_type, obj_pk):
if is_on_line:
return redirect(chapter.get_absolute_url_online())
elif is_beta:
- return redirect(chapter.get_absolute_url() + '?version=' + tutorial.sha_beta)
+ return redirect(chapter.get_absolute_url_beta())
def help_tutorial(request):
diff --git a/zds/utils/articles.py b/zds/utils/articles.py
index 1f373c8081..bcef13072b 100644
--- a/zds/utils/articles.py
+++ b/zds/utils/articles.py
@@ -8,6 +8,7 @@
# Export-to-dict functions
def export_article(article):
"""Export an article to a dict."""
+ # TODO: Thank you, Captain Obvious... WHY this export?!
dct = OrderedDict()
dct['title'] = article.title
dct['description'] = article.description
@@ -20,6 +21,7 @@ def export_article(article):
def get_blob(tree, chemin):
+
for bl in tree.blobs:
if os.path.abspath(bl.path) == os.path.abspath(chemin):
data = bl.data_stream.read()
diff --git a/zds/utils/context_processor.py b/zds/utils/context_processor.py
index cf860396c4..984263c358 100644
--- a/zds/utils/context_processor.py
+++ b/zds/utils/context_processor.py
@@ -10,7 +10,7 @@ def get_git_version():
Get the git version of the site.
"""
try:
- repo = Repo(settings.SITE_ROOT)
+ repo = Repo(settings.BASE_DIR)
branch = repo.active_branch
commit = repo.head.commit.hexsha
v = u'{0}/{1}'.format(branch, commit[:7])
diff --git a/zds/utils/factories.py b/zds/utils/factories.py
index a9ca50ea93..495fc92964 100644
--- a/zds/utils/factories.py
+++ b/zds/utils/factories.py
@@ -1,7 +1,7 @@
# coding: utf-8
from zds.utils.models import HelpWriting
from zds.utils import slugify
-from zds.settings import SITE_ROOT, MEDIA_ROOT
+from zds.settings import BASE_DIR, MEDIA_ROOT
from shutil import copyfile
from os.path import basename, join
@@ -11,7 +11,7 @@
class HelpWritingFactory(factory.DjangoModelFactory):
FACTORY_FOR = HelpWriting
- title = factory.Sequence(lambda n: u"titre de l\'image {0}".format(n))
+ title = factory.Sequence(u"titre de l\'image {0}".format)
slug = factory.LazyAttribute(lambda o: "{0}".format(slugify(o.title)))
tablelabel = factory.LazyAttribute(lambda n: u"Besoin de " + n.title)
@@ -22,7 +22,7 @@ def _prepare(cls, create, **kwargs):
fixture_image_path = kwargs.pop('fixture_image_path', None)
if fixture_image_path is not None:
- image_path = join(SITE_ROOT, "fixtures", fixture_image_path)
+ image_path = join(BASE_DIR, "fixtures", fixture_image_path)
if image_path is not None:
copyfile(image_path, join(MEDIA_ROOT, basename(image_path)))
diff --git a/zds/utils/forums.py b/zds/utils/forums.py
index 1abd0151cd..1644429860 100644
--- a/zds/utils/forums.py
+++ b/zds/utils/forums.py
@@ -67,12 +67,6 @@ def lock_topic(topic):
topic.save()
-def unlock_topic(topic, msg):
+def unlock_topic(topic):
topic.is_locked = False
- main = Post.objects.filter(topic__pk=topic.pk, position=1).first()
- main.text = msg
- main.text_html = emarkdown(msg)
- main.editor = topic.author
- main.update = datetime.now()
- main.save()
topic.save()
diff --git a/zds/utils/migrations/0001_initial.py b/zds/utils/migrations/0001_initial.py
index 972722d55a..ea662a7404 100644
--- a/zds/utils/migrations/0001_initial.py
+++ b/zds/utils/migrations/0001_initial.py
@@ -1,327 +1,178 @@
# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding model 'Alert'
- db.create_table(
- u'utils_alert',
- ((u'id',
- self.gf('django.db.models.fields.AutoField')(
- primary_key=True)),
- ('author',
- self.gf('django.db.models.fields.related.ForeignKey')(
- related_name='alerts',
- to=orm['auth.User'])),
- ('text',
- self.gf('django.db.models.fields.TextField')()),
- ('pubdate',
- self.gf('django.db.models.fields.DateTimeField')(
- null=True,
- blank=True)),
- ))
- db.send_create_signal(u'utils', ['Alert'])
-
- # Adding model 'Category'
- db.create_table(
- u'utils_category',
- ((u'id',
- self.gf('django.db.models.fields.AutoField')(
- primary_key=True)),
- ('title',
- self.gf('django.db.models.fields.CharField')(
- max_length=80)),
- ('description',
- self.gf('django.db.models.fields.TextField')()),
- ('slug',
- self.gf('django.db.models.fields.SlugField')(
- max_length=80)),
- ))
- db.send_create_signal(u'utils', ['Category'])
-
- # Adding model 'SubCategory'
- db.create_table(
- u'utils_subcategory', ((u'id', self.gf('django.db.models.fields.AutoField')(
- primary_key=True)), ('title', self.gf('django.db.models.fields.CharField')(
- max_length=80)), ('subtitle', self.gf('django.db.models.fields.CharField')(
- max_length=200)), ('image', self.gf('django.db.models.fields.files.ImageField')(
- max_length=100, null=True, blank=True)), ('slug', self.gf('django.db.models.fields.SlugField')(
- max_length=80)), ))
- db.send_create_signal(u'utils', ['SubCategory'])
-
- # Adding model 'CategorySubCategory'
- db.create_table(
- u'utils_categorysubcategory', ((u'id', self.gf('django.db.models.fields.AutoField')(
- primary_key=True)), ('category', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['utils.Category'])), ('subcategory', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['utils.SubCategory'])), ('is_main', self.gf('django.db.models.fields.BooleanField')(
- default=True)), ))
- db.send_create_signal(u'utils', ['CategorySubCategory'])
-
- # Adding model 'Licence'
- db.create_table(
- u'utils_licence', ((u'id', self.gf('django.db.models.fields.AutoField')(
- primary_key=True)), ('code', self.gf('django.db.models.fields.CharField')(
- max_length=20)), ('title', self.gf('django.db.models.fields.CharField')(
- max_length=80)), ('description', self.gf('django.db.models.fields.TextField')()), ))
- db.send_create_signal(u'utils', ['Licence'])
-
- # Adding model 'Comment'
- db.create_table(
- u'utils_comment',
- ((u'id',
- self.gf('django.db.models.fields.AutoField')(
- primary_key=True)),
- ('author',
- self.gf('django.db.models.fields.related.ForeignKey')(
- related_name='comments',
- to=orm['auth.User'])),
- ('editor',
- self.gf('django.db.models.fields.related.ForeignKey')(
- blank=True,
- related_name='comments-editor',
- null=True,
- to=orm['auth.User'])),
- ('ip_address',
- self.gf('django.db.models.fields.CharField')(
- max_length=15)),
- ('position',
- self.gf('django.db.models.fields.IntegerField')()),
- ('text',
- self.gf('django.db.models.fields.TextField')()),
- ('text_html',
- self.gf('django.db.models.fields.TextField')()),
- ('like',
- self.gf('django.db.models.fields.IntegerField')(
- default=0)),
- ('dislike',
- self.gf('django.db.models.fields.IntegerField')(
- default=0)),
- ('pubdate',
- self.gf('django.db.models.fields.DateTimeField')(
- auto_now_add=True,
- blank=True)),
- ('update',
- self.gf('django.db.models.fields.DateTimeField')(
- null=True,
- blank=True)),
- ('is_visible',
- self.gf('django.db.models.fields.BooleanField')(
- default=True)),
- ('text_hidden',
- self.gf('django.db.models.fields.CharField')(
- default='',
- max_length=80)),
- ))
- db.send_create_signal(u'utils', ['Comment'])
-
- # Adding M2M table for field alerts on 'Comment'
- m2m_table_name = db.shorten_name(u'utils_comment_alerts')
- db.create_table(
- m2m_table_name, (('id', models.AutoField(
- verbose_name='ID', primary_key=True, auto_created=True)), ('comment', models.ForeignKey(
- orm[u'utils.comment'], null=False)), ('alert', models.ForeignKey(
- orm[u'utils.alert'], null=False))))
- db.create_unique(m2m_table_name, ['comment_id', 'alert_id'])
-
- # Adding model 'CommentLike'
- db.create_table(
- u'utils_commentlike', ((u'id', self.gf('django.db.models.fields.AutoField')(
- primary_key=True)), ('comments', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['utils.Comment'])), ('user', self.gf('django.db.models.fields.related.ForeignKey')(
- related_name='post_liked', to=orm['auth.User'])), ))
- db.send_create_signal(u'utils', ['CommentLike'])
-
- # Adding model 'CommentDislike'
- db.create_table(
- u'utils_commentdislike', ((u'id', self.gf('django.db.models.fields.AutoField')(
- primary_key=True)), ('comments', self.gf('django.db.models.fields.related.ForeignKey')(
- to=orm['utils.Comment'])), ('user', self.gf('django.db.models.fields.related.ForeignKey')(
- related_name='post_disliked', to=orm['auth.User'])), ))
- db.send_create_signal(u'utils', ['CommentDislike'])
-
- def backwards(self, orm):
- # Deleting model 'Alert'
- db.delete_table(u'utils_alert')
-
- # Deleting model 'Category'
- db.delete_table(u'utils_category')
-
- # Deleting model 'SubCategory'
- db.delete_table(u'utils_subcategory')
-
- # Deleting model 'CategorySubCategory'
- db.delete_table(u'utils_categorysubcategory')
-
- # Deleting model 'Licence'
- db.delete_table(u'utils_licence')
-
- # Deleting model 'Comment'
- db.delete_table(u'utils_comment')
-
- # Removing M2M table for field alerts on 'Comment'
- db.delete_table(db.shorten_name(u'utils_comment_alerts'))
-
- # Deleting model 'CommentLike'
- db.delete_table(u'utils_commentlike')
-
- # Deleting model 'CommentDislike'
- db.delete_table(u'utils_commentdislike')
-
- models = {
- u'auth.group': {
- 'Meta': {
- 'object_name': 'Group'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '80'}), 'permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})}, u'auth.permission': {
- 'Meta': {
- 'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, 'codename': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'content_type': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['contenttypes.ContentType']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '50'})}, u'auth.user': {
- 'Meta': {
- 'object_name': 'User'}, 'date_joined': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'email': (
- 'django.db.models.fields.EmailField', [], {
- 'max_length': '75', 'blank': 'True'}), 'first_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'groups': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'is_active': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'is_staff': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'is_superuser': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'last_login': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'last_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'password': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128'}), 'user_permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), 'username': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '30'})}, u'contenttypes.contenttype': {
- 'Meta': {
- 'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'model': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'})}, u'utils.alert': {
- 'Meta': {
- 'object_name': 'Alert'}, 'author': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'alerts'", 'to': u"orm['auth.User']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'}), 'text': (
- 'django.db.models.fields.TextField', [], {})}, u'utils.category': {
- 'Meta': {
- 'object_name': 'Category'}, 'description': (
- 'django.db.models.fields.TextField', [], {}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'slug': (
- 'django.db.models.fields.SlugField', [], {
- 'max_length': '80'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'})}, u'utils.categorysubcategory': {
- 'Meta': {
- 'object_name': 'CategorySubCategory'}, 'category': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['utils.Category']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'is_main': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'subcategory': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['utils.SubCategory']"})}, u'utils.comment': {
- 'Meta': {
- 'object_name': 'Comment'}, 'alerts': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'to': u"orm['utils.Alert']", 'null': 'True', 'blank': 'True'}), 'author': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'comments'", 'to': u"orm['auth.User']"}), 'dislike': (
- 'django.db.models.fields.IntegerField', [], {
- 'default': '0'}), 'editor': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'blank': 'True', 'related_name': "'comments-editor'", 'null': 'True', 'to': u"orm['auth.User']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'ip_address': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '15'}), 'is_visible': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'like': (
- 'django.db.models.fields.IntegerField', [], {
- 'default': '0'}), 'position': (
- 'django.db.models.fields.IntegerField', [], {}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'auto_now_add': 'True', 'blank': 'True'}), 'text': (
- 'django.db.models.fields.TextField', [], {}), 'text_hidden': (
- 'django.db.models.fields.CharField', [], {
- 'default': "''", 'max_length': '80'}), 'text_html': (
- 'django.db.models.fields.TextField', [], {}), 'update': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'})}, u'utils.commentdislike': {
- 'Meta': {
- 'object_name': 'CommentDislike'}, 'comments': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['utils.Comment']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'post_disliked'", 'to': u"orm['auth.User']"})}, u'utils.commentlike': {
- 'Meta': {
- 'object_name': 'CommentLike'}, 'comments': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['utils.Comment']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'post_liked'", 'to': u"orm['auth.User']"})}, u'utils.licence': {
- 'Meta': {
- 'object_name': 'Licence'}, 'code': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '20'}), 'description': (
- 'django.db.models.fields.TextField', [], {}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'})}, u'utils.subcategory': {
- 'Meta': {
- 'object_name': 'SubCategory'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'image': (
- 'django.db.models.fields.files.ImageField', [], {
- 'max_length': '100', 'null': 'True', 'blank': 'True'}), 'slug': (
- 'django.db.models.fields.SlugField', [], {
- 'max_length': '80'}), 'subtitle': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'})}}
-
- complete_apps = ['utils']
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+import easy_thumbnails.fields
+from django.conf import settings
+import zds.utils.models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Alert',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('scope', models.CharField(db_index=True, max_length=1, choices=[(b'A', b"Commentaire d'article"), (b'F', b'Forum'), (b'T', b'Commentaire de tuto')])),
+ ('text', models.TextField(verbose_name=b"Texte d'alerte")),
+ ('pubdate', models.DateTimeField(verbose_name=b'Date de publication', db_index=True)),
+ ('author', models.ForeignKey(related_name='alerts', verbose_name=b'Auteur', to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'verbose_name': 'Alerte',
+ 'verbose_name_plural': 'Alertes',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='Category',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('title', models.CharField(max_length=80, verbose_name=b'Titre')),
+ ('description', models.TextField(verbose_name=b'Description')),
+ ('position', models.IntegerField(default=0, verbose_name=b'Position')),
+ ('slug', models.SlugField(max_length=80)),
+ ],
+ options={
+ 'verbose_name': 'Categorie',
+ 'verbose_name_plural': 'Categories',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='CategorySubCategory',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('is_main', models.BooleanField(default=True, db_index=True, verbose_name=b'Est la cat\xc3\xa9gorie principale')),
+ ('category', models.ForeignKey(verbose_name=b'Cat\xc3\xa9gorie', to='utils.Category')),
+ ],
+ options={
+ 'verbose_name': 'Hierarchie cat\xe9gorie',
+ 'verbose_name_plural': 'Hierarchies cat\xe9gories',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='Comment',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('ip_address', models.CharField(max_length=39, verbose_name=b"Adresse IP de l'auteur ")),
+ ('position', models.IntegerField(verbose_name=b'Position', db_index=True)),
+ ('text', models.TextField(verbose_name=b'Texte')),
+ ('text_html', models.TextField(verbose_name=b'Texte en Html')),
+ ('like', models.IntegerField(default=0, verbose_name=b'Likes')),
+ ('dislike', models.IntegerField(default=0, verbose_name=b'Dislikes')),
+ ('pubdate', models.DateTimeField(auto_now_add=True, verbose_name=b'Date de publication', db_index=True)),
+ ('update', models.DateTimeField(null=True, verbose_name=b"Date d'\xc3\xa9dition", blank=True)),
+ ('is_visible', models.BooleanField(default=True, verbose_name=b'Est visible')),
+ ('text_hidden', models.CharField(default=b'', max_length=80, verbose_name=b'Texte de masquage ')),
+ ('author', models.ForeignKey(related_name='comments', verbose_name=b'Auteur', to=settings.AUTH_USER_MODEL)),
+ ('editor', models.ForeignKey(related_name='comments-editor', verbose_name=b'Editeur', blank=True, to=settings.AUTH_USER_MODEL, null=True)),
+ ],
+ options={
+ 'verbose_name': 'Commentaire',
+ 'verbose_name_plural': 'Commentaires',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='CommentDislike',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('comments', models.ForeignKey(to='utils.Comment')),
+ ('user', models.ForeignKey(related_name='post_disliked', to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'verbose_name': 'Ce message est inutile',
+ 'verbose_name_plural': 'Ces messages sont inutiles',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='CommentLike',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('comments', models.ForeignKey(to='utils.Comment')),
+ ('user', models.ForeignKey(related_name='post_liked', to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'verbose_name': 'Ce message est utile',
+ 'verbose_name_plural': 'Ces messages sont utiles',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='HelpWriting',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('title', models.CharField(max_length=20, verbose_name=b'Name')),
+ ('slug', models.SlugField(max_length=20)),
+ ('tablelabel', models.CharField(max_length=150, verbose_name=b'TableLabel')),
+ ('image', easy_thumbnails.fields.ThumbnailerImageField(upload_to=zds.utils.models.image_path_help)),
+ ],
+ options={
+ 'verbose_name': 'Aide \xe0 la r\xe9daction',
+ 'verbose_name_plural': 'Aides \xe0 la r\xe9daction',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='Licence',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('code', models.CharField(max_length=20, verbose_name=b'Code')),
+ ('title', models.CharField(max_length=80, verbose_name=b'Titre')),
+ ('description', models.TextField(verbose_name=b'Description')),
+ ],
+ options={
+ 'verbose_name': 'Licence',
+ 'verbose_name_plural': 'Licences',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='SubCategory',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('title', models.CharField(max_length=80, verbose_name=b'Titre')),
+ ('subtitle', models.CharField(max_length=200, verbose_name=b'Sous-titre')),
+ ('image', models.ImageField(null=True, upload_to=zds.utils.models.image_path_category, blank=True)),
+ ('slug', models.SlugField(max_length=80)),
+ ],
+ options={
+ 'verbose_name': 'Sous-categorie',
+ 'verbose_name_plural': 'Sous-categories',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='Tag',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('title', models.CharField(max_length=20, verbose_name=b'Titre')),
+ ('slug', models.SlugField(max_length=20)),
+ ],
+ options={
+ 'verbose_name': 'Tag',
+ 'verbose_name_plural': 'Tags',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.AddField(
+ model_name='categorysubcategory',
+ name='subcategory',
+ field=models.ForeignKey(verbose_name=b'Sous-Cat\xc3\xa9gorie', to='utils.SubCategory'),
+ preserve_default=True,
+ ),
+ migrations.AddField(
+ model_name='alert',
+ name='comment',
+ field=models.ForeignKey(related_name='alerts', verbose_name=b'Commentaire', to='utils.Comment'),
+ preserve_default=True,
+ ),
+ ]
diff --git a/zds/utils/migrations/0002_auto__add_field_alert_comment__add_field_alert_scope__chg_field_alert_.py b/zds/utils/migrations/0002_auto__add_field_alert_comment__add_field_alert_scope__chg_field_alert_.py
deleted file mode 100644
index 08be15c8bc..0000000000
--- a/zds/utils/migrations/0002_auto__add_field_alert_comment__add_field_alert_scope__chg_field_alert_.py
+++ /dev/null
@@ -1,220 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Removing M2M table for field alerts on 'Comment'
- db.delete_table(db.shorten_name(u'utils_comment_alerts'))
-
- # Adding field 'Alert.comment'
- db.add_column(
- u'utils_alert',
- 'comment',
- self.gf('django.db.models.fields.related.ForeignKey')(
- default=1,
- related_name='comments',
- to=orm['utils.Comment']),
- keep_default=False)
-
- # Adding field 'Alert.scope'
- db.add_column(
- u'utils_alert',
- 'scope',
- self.gf('django.db.models.fields.CharField')(
- default='F',
- max_length=1),
- keep_default=False)
-
- # Changing field 'Alert.pubdate'
- db.alter_column(
- u'utils_alert',
- 'pubdate',
- self.gf('django.db.models.fields.DateTimeField')(
- default=datetime.datetime(
- 2014,
- 5,
- 10,
- 0,
- 0)))
-
- def backwards(self, orm):
- # Adding M2M table for field alerts on 'Comment'
- m2m_table_name = db.shorten_name(u'utils_comment_alerts')
- db.create_table(
- m2m_table_name, (('id', models.AutoField(
- verbose_name='ID', primary_key=True, auto_created=True)), ('comment', models.ForeignKey(
- orm[u'utils.comment'], null=False)), ('alert', models.ForeignKey(
- orm[u'utils.alert'], null=False))))
- db.create_unique(m2m_table_name, ['comment_id', 'alert_id'])
-
- # Deleting field 'Alert.comment'
- db.delete_column(u'utils_alert', 'comment_id')
-
- # Deleting field 'Alert.scope'
- db.delete_column(u'utils_alert', 'scope')
-
- # Changing field 'Alert.pubdate'
- db.alter_column(
- u'utils_alert',
- 'pubdate',
- self.gf('django.db.models.fields.DateTimeField')(
- null=True))
-
- models = {
- u'auth.group': {
- 'Meta': {
- 'object_name': 'Group'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '80'}), 'permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})}, u'auth.permission': {
- 'Meta': {
- 'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, 'codename': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'content_type': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['contenttypes.ContentType']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '50'})}, u'auth.user': {
- 'Meta': {
- 'object_name': 'User'}, 'date_joined': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'email': (
- 'django.db.models.fields.EmailField', [], {
- 'max_length': '75', 'blank': 'True'}), 'first_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'groups': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'is_active': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'is_staff': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'is_superuser': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'last_login': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'last_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'password': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128'}), 'user_permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), 'username': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '30'})}, u'contenttypes.contenttype': {
- 'Meta': {
- 'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'model': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'})}, u'utils.alert': {
- 'Meta': {
- 'object_name': 'Alert'}, 'author': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'alerts'", 'to': u"orm['auth.User']"}), 'comment': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'comments'", 'to': u"orm['utils.Comment']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {}), 'scope': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '1'}), 'text': (
- 'django.db.models.fields.TextField', [], {})}, u'utils.category': {
- 'Meta': {
- 'object_name': 'Category'}, 'description': (
- 'django.db.models.fields.TextField', [], {}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'slug': (
- 'django.db.models.fields.SlugField', [], {
- 'max_length': '80'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'})}, u'utils.categorysubcategory': {
- 'Meta': {
- 'object_name': 'CategorySubCategory'}, 'category': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['utils.Category']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'is_main': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'subcategory': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['utils.SubCategory']"})}, u'utils.comment': {
- 'Meta': {
- 'object_name': 'Comment'}, 'author': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'comments'", 'to': u"orm['auth.User']"}), 'dislike': (
- 'django.db.models.fields.IntegerField', [], {
- 'default': '0'}), 'editor': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'blank': 'True', 'related_name': "'comments-editor'", 'null': 'True', 'to': u"orm['auth.User']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'ip_address': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '15'}), 'is_visible': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'like': (
- 'django.db.models.fields.IntegerField', [], {
- 'default': '0'}), 'position': (
- 'django.db.models.fields.IntegerField', [], {}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'auto_now_add': 'True', 'blank': 'True'}), 'text': (
- 'django.db.models.fields.TextField', [], {}), 'text_hidden': (
- 'django.db.models.fields.CharField', [], {
- 'default': "''", 'max_length': '80'}), 'text_html': (
- 'django.db.models.fields.TextField', [], {}), 'update': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'})}, u'utils.commentdislike': {
- 'Meta': {
- 'object_name': 'CommentDislike'}, 'comments': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['utils.Comment']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'post_disliked'", 'to': u"orm['auth.User']"})}, u'utils.commentlike': {
- 'Meta': {
- 'object_name': 'CommentLike'}, 'comments': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['utils.Comment']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'post_liked'", 'to': u"orm['auth.User']"})}, u'utils.licence': {
- 'Meta': {
- 'object_name': 'Licence'}, 'code': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '20'}), 'description': (
- 'django.db.models.fields.TextField', [], {}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'})}, u'utils.subcategory': {
- 'Meta': {
- 'object_name': 'SubCategory'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'image': (
- 'django.db.models.fields.files.ImageField', [], {
- 'max_length': '100', 'null': 'True', 'blank': 'True'}), 'slug': (
- 'django.db.models.fields.SlugField', [], {
- 'max_length': '80'}), 'subtitle': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'})}}
-
- complete_apps = ['utils']
diff --git a/zds/utils/migrations/0003_auto__add_tag.py b/zds/utils/migrations/0003_auto__add_tag.py
deleted file mode 100644
index 55389fc98f..0000000000
--- a/zds/utils/migrations/0003_auto__add_tag.py
+++ /dev/null
@@ -1,183 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding model 'Tag'
- db.create_table(
- u'utils_tag', ((u'id', self.gf('django.db.models.fields.AutoField')(
- primary_key=True)), ('title', self.gf('django.db.models.fields.CharField')(
- max_length=20)), ('slug', self.gf('django.db.models.fields.SlugField')(
- max_length=20)), ))
- db.send_create_signal(u'utils', ['Tag'])
-
- def backwards(self, orm):
- # Deleting model 'Tag'
- db.delete_table(u'utils_tag')
-
- models = {
- u'auth.group': {
- 'Meta': {
- 'object_name': 'Group'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '80'}), 'permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})}, u'auth.permission': {
- 'Meta': {
- 'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, 'codename': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'content_type': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['contenttypes.ContentType']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '50'})}, u'auth.user': {
- 'Meta': {
- 'object_name': 'User'}, 'date_joined': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'email': (
- 'django.db.models.fields.EmailField', [], {
- 'max_length': '75', 'blank': 'True'}), 'first_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'groups': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'is_active': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'is_staff': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'is_superuser': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'False'}), 'last_login': (
- 'django.db.models.fields.DateTimeField', [], {
- 'default': 'datetime.datetime.now'}), 'last_name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '30', 'blank': 'True'}), 'password': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '128'}), 'user_permissions': (
- 'django.db.models.fields.related.ManyToManyField', [], {
- 'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), 'username': (
- 'django.db.models.fields.CharField', [], {
- 'unique': 'True', 'max_length': '30'})}, u'contenttypes.contenttype': {
- 'Meta': {
- 'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'model': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'}), 'name': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '100'})}, u'utils.alert': {
- 'Meta': {
- 'object_name': 'Alert'}, 'author': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'alerts'", 'to': u"orm['auth.User']"}), 'comment': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'alerts'", 'to': u"orm['utils.Comment']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {}), 'scope': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '1'}), 'text': (
- 'django.db.models.fields.TextField', [], {})}, u'utils.category': {
- 'Meta': {
- 'object_name': 'Category'}, 'description': (
- 'django.db.models.fields.TextField', [], {}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'slug': (
- 'django.db.models.fields.SlugField', [], {
- 'max_length': '80'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'})}, u'utils.categorysubcategory': {
- 'Meta': {
- 'object_name': 'CategorySubCategory'}, 'category': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['utils.Category']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'is_main': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'subcategory': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['utils.SubCategory']"})}, u'utils.comment': {
- 'Meta': {
- 'object_name': 'Comment'}, 'author': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'comments'", 'to': u"orm['auth.User']"}), 'dislike': (
- 'django.db.models.fields.IntegerField', [], {
- 'default': '0'}), 'editor': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'blank': 'True', 'related_name': "'comments-editor'", 'null': 'True', 'to': u"orm['auth.User']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'ip_address': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '15'}), 'is_visible': (
- 'django.db.models.fields.BooleanField', [], {
- 'default': 'True'}), 'like': (
- 'django.db.models.fields.IntegerField', [], {
- 'default': '0'}), 'position': (
- 'django.db.models.fields.IntegerField', [], {}), 'pubdate': (
- 'django.db.models.fields.DateTimeField', [], {
- 'auto_now_add': 'True', 'blank': 'True'}), 'text': (
- 'django.db.models.fields.TextField', [], {}), 'text_hidden': (
- 'django.db.models.fields.CharField', [], {
- 'default': "''", 'max_length': '80'}), 'text_html': (
- 'django.db.models.fields.TextField', [], {}), 'update': (
- 'django.db.models.fields.DateTimeField', [], {
- 'null': 'True', 'blank': 'True'})}, u'utils.commentdislike': {
- 'Meta': {
- 'object_name': 'CommentDislike'}, 'comments': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['utils.Comment']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'post_disliked'", 'to': u"orm['auth.User']"})}, u'utils.commentlike': {
- 'Meta': {
- 'object_name': 'CommentLike'}, 'comments': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'to': u"orm['utils.Comment']"}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'user': (
- 'django.db.models.fields.related.ForeignKey', [], {
- 'related_name': "'post_liked'", 'to': u"orm['auth.User']"})}, u'utils.licence': {
- 'Meta': {
- 'object_name': 'Licence'}, 'code': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '20'}), 'description': (
- 'django.db.models.fields.TextField', [], {}), u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'})}, u'utils.subcategory': {
- 'Meta': {
- 'object_name': 'SubCategory'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'image': (
- 'django.db.models.fields.files.ImageField', [], {
- 'max_length': '100', 'null': 'True', 'blank': 'True'}), 'slug': (
- 'django.db.models.fields.SlugField', [], {
- 'max_length': '80'}), 'subtitle': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '200'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '80'})}, u'utils.tag': {
- 'Meta': {
- 'object_name': 'Tag'}, u'id': (
- 'django.db.models.fields.AutoField', [], {
- 'primary_key': 'True'}), 'slug': (
- 'django.db.models.fields.SlugField', [], {
- 'max_length': '20'}), 'title': (
- 'django.db.models.fields.CharField', [], {
- 'max_length': '20'})}}
-
- complete_apps = ['utils']
diff --git a/zds/utils/migrations/0004_auto__chg_field_comment_ip_address.py b/zds/utils/migrations/0004_auto__chg_field_comment_ip_address.py
deleted file mode 100644
index ba3a809d32..0000000000
--- a/zds/utils/migrations/0004_auto__chg_field_comment_ip_address.py
+++ /dev/null
@@ -1,131 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
-
- # Changing field 'Comment.ip_address'
- db.alter_column(u'utils_comment', 'ip_address', self.gf('django.db.models.fields.CharField')(max_length=39))
-
- def backwards(self, orm):
-
- # Changing field 'Comment.ip_address'
- db.alter_column(u'utils_comment', 'ip_address', self.gf('django.db.models.fields.CharField')(max_length=15))
-
- models = {
- u'auth.group': {
- 'Meta': {'object_name': 'Group'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'auth.permission': {
- 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'utils.alert': {
- 'Meta': {'object_name': 'Alert'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'alerts'", 'to': u"orm['auth.User']"}),
- 'comment': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'alerts'", 'to': u"orm['utils.Comment']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {}),
- 'scope': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'utils.category': {
- 'Meta': {'object_name': 'Category'},
- 'description': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'utils.categorysubcategory': {
- 'Meta': {'object_name': 'CategorySubCategory'},
- 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['utils.Category']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_main': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'subcategory': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['utils.SubCategory']"})
- },
- u'utils.comment': {
- 'Meta': {'object_name': 'Comment'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': u"orm['auth.User']"}),
- 'dislike': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'editor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments-editor'", 'null': 'True', 'to': u"orm['auth.User']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'ip_address': ('django.db.models.fields.CharField', [], {'max_length': '39'}),
- 'is_visible': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'like': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'position': ('django.db.models.fields.IntegerField', [], {}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {}),
- 'text_hidden': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '80'}),
- 'text_html': ('django.db.models.fields.TextField', [], {}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'utils.commentdislike': {
- 'Meta': {'object_name': 'CommentDislike'},
- 'comments': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['utils.Comment']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'post_disliked'", 'to': u"orm['auth.User']"})
- },
- u'utils.commentlike': {
- 'Meta': {'object_name': 'CommentLike'},
- 'comments': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['utils.Comment']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'post_liked'", 'to': u"orm['auth.User']"})
- },
- u'utils.licence': {
- 'Meta': {'object_name': 'Licence'},
- 'code': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
- 'description': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'utils.subcategory': {
- 'Meta': {'object_name': 'SubCategory'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'utils.tag': {
- 'Meta': {'object_name': 'Tag'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '20'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '20'})
- }
- }
-
- complete_apps = ['utils']
\ No newline at end of file
diff --git a/zds/utils/migrations/0005_auto__add_index_categorysubcategory_is_main__add_index_alert_pubdate__.py b/zds/utils/migrations/0005_auto__add_index_categorysubcategory_is_main__add_index_alert_pubdate__.py
deleted file mode 100644
index 276e367f0c..0000000000
--- a/zds/utils/migrations/0005_auto__add_index_categorysubcategory_is_main__add_index_alert_pubdate__.py
+++ /dev/null
@@ -1,155 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding index on 'CategorySubCategory', fields ['is_main']
- db.create_index(u'utils_categorysubcategory', ['is_main'])
-
- # Adding index on 'Alert', fields ['pubdate']
- db.create_index(u'utils_alert', ['pubdate'])
-
- # Adding index on 'Alert', fields ['scope']
- db.create_index(u'utils_alert', ['scope'])
-
- # Adding index on 'Comment', fields ['pubdate']
- db.create_index(u'utils_comment', ['pubdate'])
-
- # Adding index on 'Comment', fields ['position']
- db.create_index(u'utils_comment', ['position'])
-
-
- def backwards(self, orm):
- # Removing index on 'Comment', fields ['position']
- db.delete_index(u'utils_comment', ['position'])
-
- # Removing index on 'Comment', fields ['pubdate']
- db.delete_index(u'utils_comment', ['pubdate'])
-
- # Removing index on 'Alert', fields ['scope']
- db.delete_index(u'utils_alert', ['scope'])
-
- # Removing index on 'Alert', fields ['pubdate']
- db.delete_index(u'utils_alert', ['pubdate'])
-
- # Removing index on 'CategorySubCategory', fields ['is_main']
- db.delete_index(u'utils_categorysubcategory', ['is_main'])
-
-
- models = {
- u'auth.group': {
- 'Meta': {'object_name': 'Group'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'auth.permission': {
- 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'utils.alert': {
- 'Meta': {'object_name': 'Alert'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'alerts'", 'to': u"orm['auth.User']"}),
- 'comment': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'alerts'", 'to': u"orm['utils.Comment']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
- 'scope': ('django.db.models.fields.CharField', [], {'max_length': '1', 'db_index': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'utils.category': {
- 'Meta': {'object_name': 'Category'},
- 'description': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'utils.categorysubcategory': {
- 'Meta': {'object_name': 'CategorySubCategory'},
- 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['utils.Category']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_main': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}),
- 'subcategory': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['utils.SubCategory']"})
- },
- u'utils.comment': {
- 'Meta': {'object_name': 'Comment'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': u"orm['auth.User']"}),
- 'dislike': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'editor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments-editor'", 'null': 'True', 'to': u"orm['auth.User']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'ip_address': ('django.db.models.fields.CharField', [], {'max_length': '39'}),
- 'is_visible': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'like': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'position': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {}),
- 'text_hidden': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '80'}),
- 'text_html': ('django.db.models.fields.TextField', [], {}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'utils.commentdislike': {
- 'Meta': {'object_name': 'CommentDislike'},
- 'comments': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['utils.Comment']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'post_disliked'", 'to': u"orm['auth.User']"})
- },
- u'utils.commentlike': {
- 'Meta': {'object_name': 'CommentLike'},
- 'comments': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['utils.Comment']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'post_liked'", 'to': u"orm['auth.User']"})
- },
- u'utils.licence': {
- 'Meta': {'object_name': 'Licence'},
- 'code': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
- 'description': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'utils.subcategory': {
- 'Meta': {'object_name': 'SubCategory'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'utils.tag': {
- 'Meta': {'object_name': 'Tag'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '20'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '20'})
- }
- }
-
- complete_apps = ['utils']
\ No newline at end of file
diff --git a/zds/utils/migrations/0006_auto__add_field_category_position.py b/zds/utils/migrations/0006_auto__add_field_category_position.py
deleted file mode 100644
index a501c29f64..0000000000
--- a/zds/utils/migrations/0006_auto__add_field_category_position.py
+++ /dev/null
@@ -1,134 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'Category.position'
- db.add_column(u'utils_category', 'position',
- self.gf('django.db.models.fields.IntegerField')(default=0),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'Category.position'
- db.delete_column(u'utils_category', 'position')
-
-
- models = {
- u'auth.group': {
- 'Meta': {'object_name': 'Group'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'auth.permission': {
- 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'utils.alert': {
- 'Meta': {'object_name': 'Alert'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'alerts'", 'to': u"orm['auth.User']"}),
- 'comment': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'alerts'", 'to': u"orm['utils.Comment']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
- 'scope': ('django.db.models.fields.CharField', [], {'max_length': '1', 'db_index': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'utils.category': {
- 'Meta': {'object_name': 'Category'},
- 'description': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'position': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'utils.categorysubcategory': {
- 'Meta': {'object_name': 'CategorySubCategory'},
- 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['utils.Category']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_main': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}),
- 'subcategory': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['utils.SubCategory']"})
- },
- u'utils.comment': {
- 'Meta': {'object_name': 'Comment'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': u"orm['auth.User']"}),
- 'dislike': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'editor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments-editor'", 'null': 'True', 'to': u"orm['auth.User']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'ip_address': ('django.db.models.fields.CharField', [], {'max_length': '39'}),
- 'is_visible': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'like': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'position': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {}),
- 'text_hidden': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '80'}),
- 'text_html': ('django.db.models.fields.TextField', [], {}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'utils.commentdislike': {
- 'Meta': {'object_name': 'CommentDislike'},
- 'comments': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['utils.Comment']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'post_disliked'", 'to': u"orm['auth.User']"})
- },
- u'utils.commentlike': {
- 'Meta': {'object_name': 'CommentLike'},
- 'comments': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['utils.Comment']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'post_liked'", 'to': u"orm['auth.User']"})
- },
- u'utils.licence': {
- 'Meta': {'object_name': 'Licence'},
- 'code': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
- 'description': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'utils.subcategory': {
- 'Meta': {'object_name': 'SubCategory'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'utils.tag': {
- 'Meta': {'object_name': 'Tag'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '20'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '20'})
- }
- }
-
- complete_apps = ['utils']
\ No newline at end of file
diff --git a/zds/utils/migrations/0006_auto__add_helpwriting.py b/zds/utils/migrations/0006_auto__add_helpwriting.py
deleted file mode 100644
index 23d128dcbb..0000000000
--- a/zds/utils/migrations/0006_auto__add_helpwriting.py
+++ /dev/null
@@ -1,146 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding model 'HelpWriting'
- db.create_table(u'utils_helpwriting', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('title', self.gf('django.db.models.fields.CharField')(max_length=20)),
- ('slug', self.gf('django.db.models.fields.SlugField')(max_length=20)),
- ('tablelabel', self.gf('django.db.models.fields.CharField')(max_length=150)),
- ('image', self.gf('django.db.models.fields.files.ImageField')(max_length=100)),
- ))
- db.send_create_signal(u'utils', ['HelpWriting'])
-
-
- def backwards(self, orm):
- # Deleting model 'HelpWriting'
- db.delete_table(u'utils_helpwriting')
-
-
- models = {
- u'auth.group': {
- 'Meta': {'object_name': 'Group'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'auth.permission': {
- 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- u'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- u'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'utils.alert': {
- 'Meta': {'object_name': 'Alert'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'alerts'", 'to': u"orm['auth.User']"}),
- 'comment': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'alerts'", 'to': u"orm['utils.Comment']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
- 'scope': ('django.db.models.fields.CharField', [], {'max_length': '1', 'db_index': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'utils.category': {
- 'Meta': {'object_name': 'Category'},
- 'description': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'utils.categorysubcategory': {
- 'Meta': {'object_name': 'CategorySubCategory'},
- 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['utils.Category']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_main': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}),
- 'subcategory': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['utils.SubCategory']"})
- },
- u'utils.comment': {
- 'Meta': {'object_name': 'Comment'},
- 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': u"orm['auth.User']"}),
- 'dislike': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'editor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments-editor'", 'null': 'True', 'to': u"orm['auth.User']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'ip_address': ('django.db.models.fields.CharField', [], {'max_length': '39'}),
- 'is_visible': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'like': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'position': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
- 'pubdate': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'text': ('django.db.models.fields.TextField', [], {}),
- 'text_hidden': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '80'}),
- 'text_html': ('django.db.models.fields.TextField', [], {}),
- 'update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
- },
- u'utils.commentdislike': {
- 'Meta': {'object_name': 'CommentDislike'},
- 'comments': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['utils.Comment']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'post_disliked'", 'to': u"orm['auth.User']"})
- },
- u'utils.commentlike': {
- 'Meta': {'object_name': 'CommentLike'},
- 'comments': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['utils.Comment']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'post_liked'", 'to': u"orm['auth.User']"})
- },
- u'utils.helpwriting': {
- 'Meta': {'object_name': 'HelpWriting'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '20'}),
- 'tablelabel': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '20'})
- },
- u'utils.licence': {
- 'Meta': {'object_name': 'Licence'},
- 'code': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
- 'description': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'utils.subcategory': {
- 'Meta': {'object_name': 'SubCategory'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '80'}),
- 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '80'})
- },
- u'utils.tag': {
- 'Meta': {'object_name': 'Tag'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '20'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '20'})
- }
- }
-
- complete_apps = ['utils']
\ No newline at end of file
diff --git a/zds/wsgi.py b/zds/wsgi.py
index 84e045d519..dc0178fc6d 100644
--- a/zds/wsgi.py
+++ b/zds/wsgi.py
@@ -1,29 +1,17 @@
# coding: utf-8
-"""WSGI config for lbp project.
-
-This module contains the WSGI application used by Django's development
-server and any production WSGI deployments. It should expose a module-
-level variable named ``application``. Django's ``runserver`` and
-``runfcgi`` commands discover this application via the
-``WSGI_APPLICATION`` setting. Usually you will have the standard Django
-WSGI application here, but it also might make sense to replace the whole
-Django WSGI application with a custom one that later delegates to the
-Django one. For example, you could introduce WSGI middleware here, or
-combine a Django application with an application of another framework.
+import os
+from django.core.wsgi import get_wsgi_application
"""
-from django.core.wsgi import get_wsgi_application
-import os
+WSGI config for zds project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+For more information on this file, see
+https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/
+"""
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "zds.settings")
-# This application object is used by any WSGI server configured to use this
-# file. This includes Django's development server, if the WSGI_APPLICATION
-# setting points here.
application = get_wsgi_application()
-
-# Apply WSGI middleware here.
-# from helloworld.wsgi import HelloWorldApplication
-# application = HelloWorldApplication(application)