Les relations dans Creme [résolu]
#1
Bonjour,

Décidément, je reviens souvent sur ce forum. Il faut dire que les réponses apportées permettent réellement d'avancer Wink

Aujourd'hui, c'est pour un problème lors de l'enregistrement d'un formulaire.

En effet, j'ai créé un modèle (checkup) supplémentaire dans le module activities avec son propre formulaire et ses vues (création, liste, édition). Je voudrais que ce modèle soit lié à une activité en particulier ainsi qu'à un contact (participant de cette activité).

Voilà ce que j'ai essayé en m'inspirant de ce que vous avez développé pour ActivityCreateForm :

dans le formulaire créé (forms/checkup.py) j'ai défini une fonction save(self) en pensant qu'elle allait créer ces relations, mais il n'en est rien...
Code :
...
participant = MultiCremeEntityField(label=_(u'Participant'), model=Contact, required=False)
...
def save(self):
    create_relation = partial(Relation.objects.create, object_entity=self.checkup,
                              type_id=REL_OBJ_PART_2_CHECKUP, user=self.user
                             )

    for entity in self.cleaned_data['participant']:
        create_relation(object_entity=entity)
Avez-vous une idée ? J'obtiens une erreur 404 avec le message suivant :
Code :
CremeEntity.get_credentials(): Cache HIT for id=25 user=jerome
Error in creme_core.Relation.save(): (1048, "Column 'subject_entity_id' cannot be null")
et le chemin qu'il tente d'afficher est /activities/checkup/None. Sans la fonction, tout fonctionne bien mais la relation ne s'établit évidemment pas.

NB J'ai par ailleurs bien défini une relation entre « REL_OBJ_PART_2_CHECKUP » et une relation créée via Creme (« creme_config-object_userrelationtype2 »).

2 questions subsidiaires toujours liées à ce modèle Checkup :
  • - j'ai créé des champs manytomanyfields. Dans le formulaire, ils apparaissent bien, dans la base, ils sont bien remplis avec les bonnes relations mais quand je demande la vue en détail, ce sont les seuls à ne pas apparaître.
  • - la vue en liste ne fonctionne pas, l'erreur est la suivante
    Code :
    FieldError: Cannot resolve keyword 'd' into field. Choices are:
    puis viennent toutes les variables définies dans le modèle. J'ai pourtant suivi le carnet du développeur de modules Creme, j'ai bien eu l'étape ou j'ai dû choisir les éléments à afficher, mais c'est suite à cela que l'erreur est apparue. Depuis, pas moyen de réinitialiser mon choix (or c'est peut-être là que j'ai fait une erreur), ou de le modifier manuellement.[/*]
Merci d'avance pour votre aide précieuse.
  Répondre
#2
Citation :Error in creme_core.Relation.save(): (1048, "Column 'subject_entity_id' cannot be null")

L'erreur est assez limpide : vous essayez de créer une instance de Relation dont l'attribut 'subject_entity' est à None. En effet dans le partial et dans son appel, vous définissez 2 fois 'object_entity', mais avec 2 valeurs différentes, mais jamais 'subject_entity' (il est donc à None), ce qui me fait dire qu'un des 2 devrait être le subject_entity (mais pas au hasard hein, cela dépend de la définition de votre RelationType).

Citation :NB J'ai par ailleurs bien défini une relation entre « REL_OBJ_PART_2_CHECKUP » et une relation créée via Creme (« creme_config-object_userrelationtype2 »).

Je n'ai pas compris ce que vous voulez dire. Une Relation est créée entre 2 CremeEntity. REL_OBJ_PART_2_CHECKUP n'en est sûrement pas une (j'imagine que c'est une string) et une Relation n'est pas une CremeEntity non plus. Donc créer une Relation entre 2 choses qui ne peuvent être reliées, je ne vois pas.

Citation :j'ai créé des champs manytomanyfields. Dans le formulaire, ils apparaissent bien, dans la base, ils sont bien remplis avec les bonnes relations mais quand je demande la vue en détail, ce sont les seuls à ne pas apparaître.

En effet le bloc objet par défaut n'affiche pas les ManyToManyFields. En effet, en générale on va plutôt mettre dans la vue en détail un bloc correspondant à ce M2M, avec la possibilité d'enlever et d'ajouter des éléments (voir les MailingLists dans les Campagnes d'Emails pour l'exemple) ; le M2M est alors aussi enlevé du formulaire d'édition, afin de gérer des grands nombres d'éléments sans surcharger le formulaire d'édition. Après vous avez aussi le choix de surcharger le bloc objet (voir Contact et Ticket dans les blocks.py idoines), afin d'afficher le M2M dans le template associé au bloc.

Citation :j'ai bien eu l'étape ou j'ai dû choisir les éléments à afficher, mais c'est suite à cela que l'erreur est apparue. Depuis, pas moyen de réinitialiser mon choix (or c'est peut-être là que j'ai fait une erreur), ou de le modifier manuellement.

Difficile de dire où se situe le problème avec si peu d'informations. Vous pouvez supprimer des colonnes de la vue en liste en allant supprimer dans la base de donnée (avec l'outil adéquat, par exemple PHPMyAdmin avec MySQL, ou avec le shell django) les instances gênantes de HeaderFilterItem (table creme_core_headerfilteritem) associées à votre vue de liste ; voire toute la vue en liste gênante (HeaderFilter, table creme_core_headerfilter) correspondant à votre ContentType checkup.
  Répondre
#3
Un grand merci pour vos réponses et vos conseils. Ils sont très précieux.

Bon, j'ai quasiment réglé tous les problèmes — non sans mal pour les relations : j'ai tout repris à zéro — reste l'erreur liée à ma vue en liste pour ma classe Checkup que je pensais pourtant pouvoir facilement résoudre.

Voici l'erreur 500 dans son ensemble :
Citation :Internal Server Error: /activities/checkups
Traceback (most recent call last):
File "/usr/local/lib/python2.6/dist-packages/django/core/handlers/base.py", line 111, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python2.6/dist-packages/django/contrib/auth/decorators.py", line 23, in _wrapped_view
return view_func(request, *args, **kwargs)
File "/usr/local/lib/python2.6/dist-packages/django/contrib/auth/decorators.py", line 23, in _wrapped_view
return view_func(request, *args, **kwargs)
File "/home/jerome/public_html/gst09/creme/activities/views/checkup.py", line 33, in listview
return list_view(request, Checkup)
File "/home/jerome/public_html/gst09/creme/creme_core/views/generic/listview.py", line 175, in list_view
template_name, template_dict = list_view_content(request, model, *args, **kwargs)
File "/home/jerome/public_html/gst09/creme/creme_core/views/generic/listview.py", line 168, in list_view_content
hf.populate_entities(entities.object_list, request.user)
File "/home/jerome/public_html/gst09/creme/creme_core/models/header_filter.py", line 155, in populate_entities
CremeEntity.populate_credentials(entities, user)
File "/home/jerome/public_html/gst09/creme/creme_core/models/entity.py", line 165, in populate_credentials
creds_map = EntityCredentials.get_creds_map(user, entities)
File "/home/jerome/public_html/gst09/creme/creme_core/models/auth.py", line 171, in get_creds_map
if not entities:
File "/usr/local/lib/python2.6/dist-packages/django/db/models/query.py", line 113, in __nonzero__
iter(self).next()
File "/usr/local/lib/python2.6/dist-packages/django/db/models/query.py", line 107, in _result_iter
self._fill_cache()
File "/usr/local/lib/python2.6/dist-packages/django/db/models/query.py", line 772, in _fill_cache
self._result_cache.append(self._iter.next())
File "/usr/local/lib/python2.6/dist-packages/django/db/models/query.py", line 273, in iterator
for row in compiler.results_iter():
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/compiler.py", line 680, in results_iter
for rows in self.execute_sql(MULTI):
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/compiler.py", line 725, in execute_sql
sql, params = self.as_sql()
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/compiler.py", line 60, in as_sql
ordering, ordering_group_by = self.get_ordering()
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/compiler.py", line 349, in get_ordering
self.query.model._meta, default_order=asc):
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/compiler.py", line 378, in find_ordering_name
opts, alias, False)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/query.py", line 1260, in setup_joins
"Choices are: %s" % (name, ", ".join(names)))
FieldError: Cannot resolve keyword 'd' into field. Choices are: ability, albumin, audiotest, cardiovascular, created, credentials, cremeentity_ptr, customfieldboolean, customfielddatetime, customfieldenum, customfieldfloat, customfieldinteger, customfieldmultienum, customfieldstring, day, diet, digestive, dither, endocrin, entity_type, entityasdata, feedback, filespe, genuri, header_filter_search_field, hearing, height, hematopoietic, history, historyline, id, instanceblockconfigitem, integument, is_actived, is_deleted, lastevents, medfindings, modified, mover, name, nervous, ocular, origin, otherexam, otherfindings, outcome, pressuremax, pressuremin, properties, psyche, pulmonary, pulse, radio, radiology, received_lw_mails, relations, relations_where_is_object, respiratory, risknature, rootnode, semifixedrelationtype, specialist, specialty, spirometry, sugar, suppexa, tiredness, user, varices, visiotest, weight, workstation

Je ne sais pas d'où cela peut provenir.

J'ai bien effacé les instances liées à ma vue dans la base, puis la vue elle-même. Creme me demande à nouveau de choisir les colonnes à afficher, et même en les limitant au maximum, ça ne fonctionne pas : même message après validation.
  Répondre
#4
J'ai aussi testé cela :
Code :
def listview(request):
    latest_checkups = Checkup.objects.all().order_by('-day')
    output = ', '.join([p.name for p in latest_checkups])
    return HttpResponse(output)
qui fonctionne bien (affichage de mes objets sans aucune mise en page). Je ne sais pas si cela peut vous aider à y voir plus clair.
  Répondre
#5
Non désolé, mais l'erreur est plus subtile que les autres fois, et juste avec une stacktrace il m'est difficile de comprendre ce qui cloche.

Il semble que le code suivant fonctionne :
Citation :list(Checkup.objects.all())

En revanche votre stacktrace semble indiquer que le code suivant ne fonctionnera pas (mais peut-être faut il compliquer la requête pour que votre problème apparaisse) :
Citation :bool(Checkup.objects.all()[:25])

Ce qui ne change pas grand chose à votre problème je vous l'accorde ; malheureusement je ne suis pas capable avec ces quelques informations d'aller plus loin que ça. Même s'il s'agissait d'un bug dans Creme (peut-être faites vous des choses singulières qui font que cela ne s'est jamais manifesté chez nous - la listview étant quand même très utilisée), il me faudrait le code minimal faisant apparaître ce bug pour le corriger.

PS: la fonction qui fait apparaître le problème chez vous (CremeEntity.populate_credentials) a disparu dans les versions de développement de Creme depuis quelques temps ; d'un autre côté elle ne fait sûrement que mettre en lumière un problème, qui réapparaîtra probablement ailleurs même en updatant votre version (il me semble que vous étiez déjà sur une version de dev).
  Répondre
#6
Le problème s'est solutionné un peu tout seul, sans que je le comprenne en tout cas. J'ai vidé toutes les bases et ai tout repris dans l'ordre : création d'un contact, puis d'une activité et enfin d'un examen (ma classe Checkup). Toutes les vues sont maintenant correctes. Je pense que comme le modèle examen intervient dans les relations avec les contacts et les activités, le fait de faire des tests un peu dans le désordre a dû sérieusement compromettre la base.

Pour info, les 2 fonctions que vous m'indiquiez semblaient fonctionner :
Citation : list(Checkup.objects.all())
me renvoyait bien la bonne liste et
Citation : bool(Checkup.objects.all()[:25])
la valeur True.

Je vais tout de même surveiller les prochains affichages des vues avant de crier victoire et surtout être plus strict dans mes séquences de test. En attendant, je vous remercie encore pour votre aide !
  Répondre


Atteindre :


Utilisateur(s) parcourant ce sujet : 1 visiteur(s)