ref(admin_action): supprime la generation pdf
La generation pdf est cassee dans la mise a jour elle est peu ou plus utilisée et s'il fallait la remettre on passerait par un système de templates à la weasyprintpull/48/head
Parent
fb45a583d4
révision
6d18b5ca40
|
@ -17,7 +17,6 @@ Production:
|
|||
|
||||
* gnu make
|
||||
* django >= 1.4
|
||||
* reportlab >= 2.4
|
||||
* basket (librairie interne au projet)
|
||||
* un serveur web capable de faire du wsgi
|
||||
* Acces a une base de donnee via (au choix)
|
||||
|
@ -39,8 +38,6 @@ Installation
|
|||
* télécharger basket:
|
||||
* get clone http://depot.interne.cliss21.org/django_app/basket (fixme)
|
||||
* installer le maximum de dependances via votre systeme de paquet
|
||||
* reportlab
|
||||
* ...
|
||||
* installer les dependances restantes via pip
|
||||
* faire en sorte que les dependances soient dans le chemin du projet
|
||||
* les paquets du systeme le sont par defaut
|
||||
|
|
|
@ -583,7 +583,6 @@ class AdminPersonne(
|
|||
list_display_links = ('nom', 'prenom', 'structure')
|
||||
list_filter = ('structure__type_pm', 'structure__statut')
|
||||
actions = (
|
||||
admv.gen_etiquettes,
|
||||
admv.gen_mailto,
|
||||
admv.gen_csv_publipostage,
|
||||
admv.gen_csv_complet,
|
||||
|
@ -653,7 +652,6 @@ class AdminStructure(
|
|||
'commune__arrondissement',
|
||||
)
|
||||
actions = (
|
||||
admv.gen_etiquettes,
|
||||
admv.gen_mailto,
|
||||
admv.gen_mailto_sympa,
|
||||
admv.gen_csv_publipostage_pphy,
|
||||
|
|
|
@ -27,27 +27,6 @@ except ImportError:
|
|||
|
||||
|
||||
# ## admin_actions
|
||||
def gen_etiquettes(model_admin, request, queryset):
|
||||
"Générer des étiquettes"
|
||||
liste_contacts = []
|
||||
for contact in queryset:
|
||||
liste_contacts.append(contact)
|
||||
for pers_associees in contact.liste_contacts_associes():
|
||||
if pers_associees.courrier_structure:
|
||||
liste_contacts.append(pers_associees)
|
||||
if len(liste_contacts) == 0:
|
||||
raise http.Http404("Aucun contact n'a été trouvé !")
|
||||
# Génération et renvoi du document
|
||||
buffer = StringIO()
|
||||
pdfdoc = contacts_utils.EtiquettesPDF(buffer)
|
||||
pdfdoc.build(liste_contacts)
|
||||
response = http.HttpResponse(content_type='application/pdf')
|
||||
response['Content-Disposition'] = 'attachment; filename=etiquettes.pdf'
|
||||
response.write(buffer.getvalue())
|
||||
buffer.close()
|
||||
return response
|
||||
|
||||
|
||||
def _gen_mailto(queryset, sympa=False):
|
||||
"shared code between full views and admin_action"
|
||||
adresses = []
|
||||
|
|
|
@ -353,19 +353,6 @@ class Structure(models.Model):
|
|||
args=[self.pk],
|
||||
)
|
||||
|
||||
def contenu_etiquette(self):
|
||||
"""
|
||||
Retourne le contenu à afficher dans l'étiquette sous forme de liste
|
||||
dont chaque élément représente une ligne.
|
||||
"""
|
||||
contenu = []
|
||||
# On doit remplacer & par & à cause d'un problème dans reportlab
|
||||
# qui génère une erreur XML lorsque le nom contient un "&"
|
||||
contenu.append(str(self).replace("&", "&")) # noqa F821
|
||||
contenu.extend(self.adresse.split('\n'))
|
||||
contenu.append("%s %s" % (self.code_postal or '', self.ville or ''))
|
||||
return contenu
|
||||
|
||||
def liste_contacts_associes(self):
|
||||
"""
|
||||
Surcharge de la méthode de Contact.
|
||||
|
@ -1723,19 +1710,6 @@ class Personne(models.Model):
|
|||
"""
|
||||
return "%s %s" % (self.nom.upper(), self.prenom)
|
||||
|
||||
def contenu_etiquette(self):
|
||||
"""
|
||||
Retourne le contenu à afficher dans l'étiquette sous forme de liste
|
||||
dont chaque élément représente une ligne.
|
||||
"""
|
||||
contenu = []
|
||||
# On doit remplacer & par & à cause d'un problème dans reportlab
|
||||
# qui génère une erreur XML lorsque le nom contient un "&"
|
||||
contenu.append(self.nom_prenom().replace("&", "&"))
|
||||
contenu.extend(self.adresse.split('\n'))
|
||||
contenu.append("%s %s" % (self.code_postal or '', self.ville or ''))
|
||||
return contenu
|
||||
|
||||
def adresse_electronique(self):
|
||||
"""
|
||||
Retourne une liste de 2 éléments:
|
||||
|
|
|
@ -5,7 +5,7 @@ from django.urls import reverse
|
|||
|
||||
from contacts import models as cm
|
||||
from contacts.settings_messages import AVERTISSEMENT_MESSAGE as w_msg
|
||||
from contacts.tests.utils import cfty, mfty
|
||||
from contacts.tests.utils import cfty
|
||||
from references import models as rm
|
||||
|
||||
|
||||
|
@ -65,33 +65,4 @@ class ValPersonne(TestCase):
|
|||
msg = [elm.message for elm in response.context['messages']]
|
||||
self.assertIn(w_msg["pers_af_agri_sans_date_naiss"], msg)
|
||||
|
||||
def test_personne_etiquette(self):
|
||||
"""L'étiquette sous forme de liste doit contenir le nom_prenom
|
||||
avec les & remplacés par &, chaque ligne de l'adresse et
|
||||
l'association du code postal et de la ville"""
|
||||
# Une personne avec nom, prenom et adresse
|
||||
struc = cfty(cm.Structure, self.i_pm, type_pm=0)
|
||||
personne = mfty(cm.Personne, self.i_p, structure=struc)
|
||||
personne.nom = "test&nom"
|
||||
personne.adresse = "62 rue des \n Cacahuètes"
|
||||
etiquette = personne.contenu_etiquette()
|
||||
self.assertEqual(
|
||||
etiquette,
|
||||
["TEST&NOM testprenom", "62 rue des ", " Cacahuètes", " "],
|
||||
)
|
||||
# Une personne avec nom, prenom, adresse, code postal et ville
|
||||
personne.ville = "Canarville"
|
||||
personne.code_postal = "10000"
|
||||
etiquette = personne.contenu_etiquette()
|
||||
self.assertEqual(
|
||||
etiquette,
|
||||
[
|
||||
"TEST&NOM testprenom",
|
||||
"62 rue des ",
|
||||
" Cacahuètes",
|
||||
"10000 Canarville",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
# EOF
|
||||
|
|
|
@ -86,44 +86,6 @@ class ValStructure(TestCase):
|
|||
structure.f_juridique = self.fjur
|
||||
structure.full_clean()
|
||||
|
||||
def test_structure_etiquette(self):
|
||||
"""L'etiquette sous forme de liste doit contenir la designation
|
||||
avec les & remplacés par &, chaque ligne de l'adresse et
|
||||
l'association du code postal et de la ville"""
|
||||
# Une structure avec adresse
|
||||
structure = cfty(cm.Structure, self.i_pm, type_pm=0)
|
||||
structure.designation = None
|
||||
structure.adresse = "62 rue des \n Cacahuètes"
|
||||
etiquette = structure.contenu_etiquette()
|
||||
self.assertEqual(
|
||||
etiquette, ["Structure (#1)", "62 rue des ", " Cacahuètes", " "]
|
||||
)
|
||||
# Une structure avec personne et adresse
|
||||
cfty(cm.Personne, self.i_p, structure=structure)
|
||||
etiquette = structure.contenu_etiquette()
|
||||
self.assertEqual(
|
||||
etiquette, ["testons testin", "62 rue des ", " Cacahuètes", " "]
|
||||
)
|
||||
# Une structure avec designation et adresse
|
||||
structure.designation = "test&testin"
|
||||
etiquette = structure.contenu_etiquette()
|
||||
self.assertEqual(
|
||||
etiquette, ["test&testin", "62 rue des ", " Cacahuètes", " "]
|
||||
)
|
||||
# Une structure avec designation, adresse, code postal et ville
|
||||
structure.ville = "Canarville"
|
||||
structure.code_postal = "10000"
|
||||
etiquette = structure.contenu_etiquette()
|
||||
self.assertEqual(
|
||||
etiquette,
|
||||
[
|
||||
"test&testin",
|
||||
"62 rue des ",
|
||||
" Cacahuètes",
|
||||
"10000 Canarville",
|
||||
],
|
||||
)
|
||||
|
||||
def test_structure_liste_contact(self):
|
||||
"""La méthode liste_contacts_associes doit retourner la liste
|
||||
des personnes associées"""
|
||||
|
|
|
@ -7,13 +7,6 @@ from django.conf import settings
|
|||
from django.core import exceptions
|
||||
|
||||
import model_walk
|
||||
import reportlab
|
||||
import reportlab.lib.styles as rlstyles
|
||||
import reportlab.platypus as rlp
|
||||
from reportlab.lib.units import cm
|
||||
|
||||
PAGE_HEIGHT = reportlab.rl_config.defaultPageSize[1]
|
||||
PAGE_WIDTH = reportlab.rl_config.defaultPageSize[0]
|
||||
|
||||
REPR_MTX = {
|
||||
'ManyRelatedManager': lambda x: ', '.join(
|
||||
|
@ -34,122 +27,6 @@ def repr_obj(obj):
|
|||
return REPR_MTX.get(class_name, lambda x: x)(obj)
|
||||
|
||||
|
||||
# ## ---------------------------------------------------------------------------
|
||||
# Étiquettes en PDF
|
||||
#
|
||||
|
||||
|
||||
class EtiquettesPDF:
|
||||
"""
|
||||
Classe permettant la génération simple de pages d'étiquettes d'adresses
|
||||
pour les modèles fournissant la méthode contenu_etiquette() retournant
|
||||
la liste des lignes constituant l'étiquette.
|
||||
"""
|
||||
|
||||
# Marges de la page
|
||||
margin_top = 0 * cm
|
||||
margin_left = 0 * cm
|
||||
margin_right = 0 * cm
|
||||
margin_bottom = 0 * cm
|
||||
# Dimensions des étiquettes (représentées par des frames)
|
||||
frame_width = 7.00 * cm
|
||||
frame_height = 3.71 * cm
|
||||
# Nombre de colonnes et lignes de frames par page
|
||||
frames_cols = int((PAGE_WIDTH - margin_left - margin_right) / frame_width)
|
||||
frames_rows = int(
|
||||
(PAGE_HEIGHT - margin_top - margin_bottom) / frame_height
|
||||
)
|
||||
# Nombre de frames (donc d'étiquettes) par page
|
||||
fpp = frames_cols * frames_rows
|
||||
# Bricolage sur la hauteur des étiquettes pour régler un problème
|
||||
# sur l'étiquette du bas qui est trop haute sur les feuilles d'étiquettes
|
||||
# utilisees. (Fait ici pour ne pas impacter fpp)
|
||||
# On rajoute cette hauteur à chaque étiquette.
|
||||
frame_height += 0.04 * cm
|
||||
# Le padding des frames, dans l'ordre demandé par rlp.Frame(),
|
||||
# c'est à dire left, bottom, right, top
|
||||
frame_padding = (10, 5, 5, 5)
|
||||
# Dessiner les bords des frames ?
|
||||
show_frame_boundary = 0
|
||||
# Première ligne des frames
|
||||
top_y = PAGE_HEIGHT - margin_top
|
||||
titre = "Étiquettes"
|
||||
auteur = ""
|
||||
|
||||
def __init__(self, file):
|
||||
"""
|
||||
Calcule quelques informations avant sur le document à générer.
|
||||
"""
|
||||
# Le fichier (ou l'objet émulant un fichier) où écrire
|
||||
self.file = file
|
||||
# Style des étiquettes
|
||||
self.style = rlstyles.getSampleStyleSheet()["Normal"]
|
||||
self.style.fontName = "Helvetica"
|
||||
self.style.fontSize = 11
|
||||
|
||||
def build(self, objets):
|
||||
"""
|
||||
Génère le document et l'écrit dans self.file.
|
||||
"""
|
||||
# Création du Canvas
|
||||
self.canv = reportlab.pdfgen.canvas.Canvas(self.file)
|
||||
self.canv.setTitle(self.titre)
|
||||
self.canv.setAuthor(self.auteur)
|
||||
# Get on with it !
|
||||
page_frames = None
|
||||
for i in range(0, len(objets)):
|
||||
if i % self.fpp == 0: # On entame une nouvelle page
|
||||
if i != 0: # On génère la page qui vient d'être remplie
|
||||
self.canv.showPage()
|
||||
# On crée la liste des frames de la nouvelle page
|
||||
page_frames = self._mk_page_frames(i // self.fpp)
|
||||
# On écrit l'étiquette dans la frame en cours
|
||||
page_frames[i % self.fpp].addFromList(
|
||||
self._contenu_etiquette(objets[i]), self.canv
|
||||
)
|
||||
# Génération de la dernière page
|
||||
self.canv.showPage()
|
||||
# Génération du document
|
||||
self.canv.save()
|
||||
|
||||
def _mk_page_frames(self, page_id):
|
||||
"""
|
||||
Retourne une liste de frames pour une page.
|
||||
.
|
||||
page_id est le numéro de la page permettant d'assigner une identifiant
|
||||
unique à chaque frame, composé du numéro de page et du numéro de la
|
||||
frame dans cette page (même si ça n'est pas vraiment utilisé ensuite!).
|
||||
"""
|
||||
frames = []
|
||||
for i in range(0, self.fpp):
|
||||
# remarque: *self.frame_padding ne fonctionne pas sous python2.5
|
||||
f = rlp.Frame(
|
||||
self.margin_left + (i % self.frames_cols * self.frame_width),
|
||||
self.top_y - (i / self.frames_cols + 1) * self.frame_height,
|
||||
self.frame_width,
|
||||
self.frame_height,
|
||||
self.frame_padding[0],
|
||||
self.frame_padding[1],
|
||||
self.frame_padding[2],
|
||||
self.frame_padding[3],
|
||||
id="%s%s" % (page_id, i),
|
||||
showBoundary=self.show_frame_boundary,
|
||||
)
|
||||
frames.append(f)
|
||||
return frames
|
||||
|
||||
def _contenu_etiquette(self, objet):
|
||||
"""
|
||||
Retourne sous forme de listes de paragraphes le texte d'une étiquette
|
||||
qui sera écrit dans une frame.
|
||||
"""
|
||||
return [
|
||||
rlp.Paragraph(ligne, self.style)
|
||||
for ligne in objet.contenu_etiquette()
|
||||
if ligne
|
||||
]
|
||||
|
||||
|
||||
# ## ---------------------------------------------------------------------------
|
||||
# Base pour l'export CSV
|
||||
#
|
||||
|
|
Chargement…
Référencer dans un nouveau ticket