4
votes

Administrateur Django: __str__ a renvoyé une non-chaîne (type int)

Je travaille sur un devoir pour créer une API dans Django. J'obtiens l'erreur suivante sur deux de mes modèles lorsque je clique sur le lien dans le framework d'administration Django:

class SubscriberSerializer(serializers.ModelSerializer):
    class Meta:
        model = Subscriber
        fields = '__all__'

class TransferredSubscriptionSerializer(serializers.ModelSerializer):
    class Meta:
        model = TransferredSubscription
        fields = '__all__'

class OfficerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Officer
        fields = '__all__'

Mes autres modèles semblent fonctionner correctement. Voici un code de models.py:

admin.site.register(Subscriber)
admin.site.register(TransferredSubscription)
admin.site.register(Officer)

TransferredSubscription fonctionne bien. J'ai essayé d'ajouter return str (self.officecode) et cela donne toujours la même erreur.

Une idée pourquoi cela peut se produire?

EDIT: Ajout du suivi des erreurs par requête:

router.register('subscriber', views.SubscriberView)
router.register('transferredsubscription', views.TransferredSubscriptionView)
router.register('officer', views.OfficerView)

EDIT 2: Ajout de plus de code views.py

class SubscriberView(viewsets.ModelViewSet):
    queryset = Subscriber.objects.all()
    serializer_class = SubscriberSerializer

class TransferredSubscriptionView(viewsets.ModelViewSet):
    queryset = TransferredSubscription.objects.all()
    serializer_class = TransferredSubscriptionSerializer

class OfficerView(viewsets.ModelViewSet):
    queryset = Officer.objects.all()
    serializer_class = OfficerSerializer

urls.py

Environment:


Request Method: GET
Request URL: http://127.0.0.1:8000/officer/

Django Version: 3.0.4
Python Version: 3.7.5
Installed Applications:
['synerd',
 'backend',
 'rest_framework',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']


Template error:
In template /usr/local/lib/python3.7/dist-packages/rest_framework/templates/rest_framework/horizontal/select.html, error at line 15
   __str__ returned non-string (type int)
   5 :     <label class="col-sm-2 control-label {% if style.hide_label %}sr-only{% endif %}">
   6 :       {{ field.label }}
   7 :     </label>
   8 :   {% endif %}
   9 : 
   10 :   <div class="col-sm-10">
   11 :     <select class="form-control" name="{{ field.name }}">
   12 :       {% if field.allow_null or field.allow_blank %}
   13 :         <option value="" {% if not field.value %}selected{% endif %}>--------</option>
   14 :       {% endif %}
   15 :        {% for select in field.iter_options %} 
   16 :           {% if select.start_option_group %}
   17 :             <optgroup label="{{ select.label }}">
   18 :           {% elif select.end_option_group %}
   19 :             </optgroup>
   20 :           {% else %}
   21 :             <option value="{{ select.value }}" {% if select.value|as_string == field.value|as_string %}selected{% endif %} {% if select.disabled %}disabled{% endif %}>{{ select.display_text }}</option>
   22 :           {% endif %}
   23 :       {% endfor %}
   24 :     </select>
   25 : 


Traceback (most recent call last):
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/core/handlers/base.py", line 145, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/core/handlers/base.py", line 143, in _get_response
    response = response.render()
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/template/response.py", line 105, in render
    self.content = self.rendered_content
  File "/usr/local/lib/python3.7/dist-packages/rest_framework/response.py", line 70, in rendered_content
    ret = renderer.render(self.data, accepted_media_type, context)
  File "/usr/local/lib/python3.7/dist-packages/rest_framework/renderers.py", line 724, in render
    context = self.get_context(data, accepted_media_type, renderer_context)
  File "/usr/local/lib/python3.7/dist-packages/rest_framework/renderers.py", line 696, in get_context
    'post_form': self.get_rendered_html_form(data, view, 'POST', request),
  File "/usr/local/lib/python3.7/dist-packages/rest_framework/renderers.py", line 511, in get_rendered_html_form
    return self.render_form_for_serializer(serializer)
  File "/usr/local/lib/python3.7/dist-packages/rest_framework/renderers.py", line 521, in render_form_for_serializer
    {'style': {'template_pack': 'rest_framework/horizontal'}}
  File "/usr/local/lib/python3.7/dist-packages/rest_framework/renderers.py", line 372, in render
    return template.render(context)
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/template/base.py", line 171, in render
    return self._render(context)
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/template/base.py", line 163, in _render
    return self.nodelist.render(context)
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/template/base.py", line 936, in render
    bit = node.render_annotated(context)
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/template/base.py", line 903, in render_annotated
    return self.render(context)
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/template/defaulttags.py", line 209, in render
    nodelist.append(node.render_annotated(context))
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/template/base.py", line 903, in render_annotated
    return self.render(context)
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/template/defaulttags.py", line 309, in render
    return nodelist.render(context)
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/template/base.py", line 936, in render
    bit = node.render_annotated(context)
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/template/base.py", line 903, in render_annotated
    return self.render(context)
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/template/library.py", line 192, in render
    output = self.func(*resolved_args, **resolved_kwargs)
  File "/usr/local/lib/python3.7/dist-packages/rest_framework/templatetags/rest_framework.py", line 87, in render_field
    return renderer.render_field(field, style)
  File "/usr/local/lib/python3.7/dist-packages/rest_framework/renderers.py", line 351, in render_field
    return template.render(context)
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/template/base.py", line 171, in render
    return self._render(context)
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/template/base.py", line 163, in _render
    return self.nodelist.render(context)
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/template/base.py", line 936, in render
    bit = node.render_annotated(context)
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/template/base.py", line 903, in render_annotated
    return self.render(context)
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/template/defaulttags.py", line 161, in render
    values = self.sequence.resolve(context, ignore_failures=True)
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/template/base.py", line 670, in resolve
    obj = self.var.resolve(context)
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/template/base.py", line 795, in resolve
    value = self._resolve_lookup(context)
  File "/home/ubuntu/.local/lib/python3.7/site-packages/django/template/base.py", line 857, in _resolve_lookup
    current = current()
  File "/usr/local/lib/python3.7/dist-packages/rest_framework/relations.py", line 215, in iter_options
    self.get_choices(cutoff=self.html_cutoff),
  File "/usr/local/lib/python3.7/dist-packages/rest_framework/relations.py", line 202, in get_choices
    for item in queryset
  File "/usr/local/lib/python3.7/dist-packages/rest_framework/relations.py", line 202, in <listcomp>
    for item in queryset
  File "/usr/local/lib/python3.7/dist-packages/rest_framework/relations.py", line 221, in display_value
    return str(instance)

Exception Type: TypeError at /officer/
Exception Value: __str__ returned non-string (type int)

admin.py

class Subscriber(models.Model):
    subscriberID = models.IntegerField(primary_key=True)
    username = models.ForeignKey(UserInfo, on_delete=models.CASCADE)
    subscriptiontypecode = models.ForeignKey(SubscriptionType, on_delete=models.CASCADE)
    servicecode = models.ForeignKey(Service, on_delete=models.CASCADE)
    requestdate = models.DateField()
    startdate = models.DateField()
    enddate = models.DateField()
    motifofcancellation = models.CharField(max_length=64)
    beneficiaryID = models.IntegerField()

    def __str__(self):
        return self.subscriberID

class TransferredSubscription(models.Model):
    transferID = models.IntegerField(primary_key=True)
    transferfrom = models.CharField(max_length=64)
    transferto = models.CharField(max_length=64)
    requestdate = models.DateField()
    transferdate = models.DateField()
    subscriberID = models.ForeignKey(Subscriber, on_delete=models.CASCADE)

    def __str__(self):
        return self.transferID

class Officer(models.Model):
    officecode = models.ForeignKey(Office, on_delete=models.CASCADE)
    subscriberID = models.ForeignKey(Subscriber, on_delete=models.CASCADE)
    startdate = models.DateField()
    enddate = models.DateField()

    def __str__(self):
        return self.officecode

serializers.py

TypeError at /officer/
__str__ returned non-string (type int)

Request Method:     GET
Request URL:    http://127.0.0.1:8000/officer/
Django Version:     3.0.4
Exception Type:     TypeError
Exception Value:    

__str__ returned non-string (type int)

Exception Location:     /usr/local/lib/python3.7/dist-packages/rest_framework/relations.py in display_value, line 221
Python Executable:  /usr/bin/python3
Python Version:     3.7.5
Python Path: 

Error during template rendering

In template /usr/local/lib/python3.7/dist-packages/rest_framework/templates/rest_framework/horizontal/select.html, error at line 15
__str__ returned non-string (type int)


8 commentaires

pouvez-vous afficher la vue correspondante?


Ajout de quelques extraits de views.py, urls.py, admin.py, serializers.py


return str (self.transferId) et transtyper les entiers en chaînes.


Pourquoi définir des méthodes str comme celle-ci sur les objets? Vous fiez-vous à ce comportement d'une manière ou d'une autre et que se passe-t-il avec un nouvel objet qui a "Aucun" pour l'ID?


@AndrewBacker J'ai parcouru et commenté la def __str __ (self): sur les modèles d'abonnés et de bureau, et j'avais toujours le même problème ... puis je suis allé et j'ai fait cela à TOUS mes modèles, et maintenant tout fonctionne - merci !


@AndrewBacker à ajouter ... J'ai eu tous mes modèles retournant INT sous la méthode str , mais avec vos conseils, j'ai pu modifier chacun pour renvoyer une chaîne (c'est-à-dire nom d'utilisateur au lieu d'ID utilisateur #) et maintenant tout s'affiche correctement dans l'API. Merci encore


Super, heureux qui a fonctionné! À mon avis, str () ne devrait vraiment être appelé que sur un modèle soit volontairement, soit en sortie de débogage. Cela fonctionne bien dans l'administrateur en tant que rapide et sale, mais vous voulez probablement avoir une fonction personnalisée dans votre administrateur qui donne des informations meilleures / plus claires. En tant que base, mon str est juste f"ModelName({self.name})" ou tout aussi simple, mais la valeur par défaut fonctionne également.


Si vous répondez à votre question, veuillez cocher l'une des réponses ci-dessous comme acceptée.


3 Réponses :


2
votes

Vous ne nous avez pas montré votre modèle Office . Étant donné que officecode est un objet Office , assurez-vous d'avoir défini la __str__() dans le modèle Office . Vous pouvez le convertir en un int au cas où.

class Office(models.Model):
    officecode = models.IntegerField(primary_key=True)
    ....
    def __str__(self):
        return str(self.officecode)

La méthode str () est appelée chaque fois que vous appelez str () sur un objet.


0 commentaires

0
votes

Répondre à vos commentaires:

Je ne peux pas dire exactement pourquoi le problème se produit à partir de la seule trace de la pile, en regardant le code source. L'autre réponse mentionne appeler str sur le pk, mais cela n'a pas fonctionné. Pour le déboguer, vous devez placer un point d'arrêt à l'endroit où l'exception se produit et remonter la trace de la pile pour voir quelles sont les valeurs.

def __str__(self):
    return "%s(%s)" % (self.__class__.__name__, self.pk)

Ma meilleure hypothèse est qu'il récupère quelque chose qui ressemble à un nombre et génère une erreur.

1) Essayez de supprimer toutes les implémentations __str__ pour les modèles. Ils ne sont pas vraiment nécessaires car la classe de base fait quelque chose d'assez bon, à moins que vous ne vouliez la rendre plus attrayante

2) Essayez de renvoyer plus d'un str(int) là-dedans, donc il ne peut pas être mal interprété:

  File "/usr/local/lib/python3.7/dist-packages/rest_framework/relations.py", line 221, in display_value
    return str(instance)

Je ne trouve cette erreur spécifique nulle part dans django ou drf, donc sans le déboguer directement, je n'ai plus de suggestions.


0 commentaires

0
votes

your Subscriber.__str__ renvoie également un int. changement:

def __str__(self):
    return str(self.subscriberID)

à

def __str__(self):
    return self.subscriberID


0 commentaires