Image de profile pour les gymnastes #6

Closed
opened 2021-12-21 09:06:19 +01:00 by Sulley · 12 comments
Owner

Yo mec !

J'ai voulu ajouter la possibilité de mettre une photo de profil pour les gymnates (branche gymnast_picture).
J'ai quasi tout fait mais quelques petites choses coincent encore :

  • la config
  • le formulaire HTML qui se semble pas vouloir entrer dans le template (du moins, j'y suis pas encore arrivé)
  • et l'envoie du formulaire n'upload pas le fichier :'(
  • ...

La config

J'ai voulu que les images aillent se mettre dans /static/img/gymnast/, ca me semblait logique/cohérent. Sauf que Django n'aime pas ca :

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/threading.py", line 1009, in _bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/threading.py", line 946, in run
    self._target(*self._args, **self._kwargs)
  File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/utils/autoreload.py", line 64, in wrapper
    fn(*args, **kwargs)
  File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/core/management/commands/runserver.py", line 138, in inner_run
    handler = self.get_handler(*args, **options)
  File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/contrib/staticfiles/management/commands/runserver.py", line 31, in get_handler
    return StaticFilesHandler(handler)
  File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/contrib/staticfiles/handlers.py", line 71, in __init__
    self.base_url = urlparse(self.get_base_url())
  File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/contrib/staticfiles/handlers.py", line 29, in get_base_url
    utils.check_settings()
  File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/contrib/staticfiles/utils.py", line 57, in check_settings
    raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: runserver can't serve media if MEDIA_URL is within STATIC_URL.

J'en conclus que je devrait pas définir mon MEDIA_URL/ROOT a l'instérieur de /static/ mais ou alors (pour rester logique et cohérent) ?

(on verra pour les autre problèmes après, si ca se trouvent ils découlent de celui-ci)

Yo mec ! J'ai voulu ajouter la possibilité de mettre une photo de profil pour les gymnates (branche `gymnast_picture`). J'ai quasi tout fait mais quelques petites choses coincent encore : - la config - le formulaire HTML qui se semble pas vouloir entrer dans le template (du moins, j'y suis pas encore arrivé) - et l'envoie du formulaire n'upload pas le fichier :'( - ... ## La config J'ai voulu que les images aillent se mettre dans `/static/img/gymnast/`, ca me semblait logique/cohérent. Sauf que Django n'aime pas ca : ``` Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/threading.py", line 1009, in _bootstrap_inner self.run() File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/threading.py", line 946, in run self._target(*self._args, **self._kwargs) File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/utils/autoreload.py", line 64, in wrapper fn(*args, **kwargs) File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/core/management/commands/runserver.py", line 138, in inner_run handler = self.get_handler(*args, **options) File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/contrib/staticfiles/management/commands/runserver.py", line 31, in get_handler return StaticFilesHandler(handler) File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/contrib/staticfiles/handlers.py", line 71, in __init__ self.base_url = urlparse(self.get_base_url()) File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/contrib/staticfiles/handlers.py", line 29, in get_base_url utils.check_settings() File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/contrib/staticfiles/utils.py", line 57, in check_settings raise ImproperlyConfigured( django.core.exceptions.ImproperlyConfigured: runserver can't serve media if MEDIA_URL is within STATIC_URL. ``` J'en conclus que je devrait pas définir mon MEDIA_URL/ROOT a l'instérieur de /static/ mais ou alors (pour rester logique et cohérent) ? (on verra pour les autre problèmes après, si ca se trouvent ils découlent de celui-ci)
Sulley added the
bug
label 2021-12-21 09:06:19 +01:00
Fred was assigned by Sulley 2021-12-21 09:06:19 +01:00
Fred removed their assignment 2021-12-21 09:35:52 +01:00
Collaborator

A l'extérieur des fichiers statiques (genre, dans /media 😜 )

Les fichiers statiques servent à proposer les fichiers CSS et JS; dans un mode de déploiement (automatique ou manuel), Django va vider ce répertoire pour le remplacer par les nouvelles versions des fichiers.

Dans ce cadre-là, si tu mets tes fichiers media à l'intérieur du répertoire static, tu vas un touuuut petit problème rapidement (à la prochaine version 👊 )

A l'extérieur des fichiers statiques (genre, dans `/media` 😜 ) Les fichiers statiques servent à proposer les fichiers CSS et JS; dans un mode de déploiement (automatique ou manuel), Django va vider ce répertoire pour le remplacer par les nouvelles versions des fichiers. Dans ce cadre-là, si tu mets tes fichiers media à l'intérieur du répertoire static, tu vas un touuuut petit problème rapidement (à la prochaine version 👊 )
Author
Owner

Ok… J'ai donc changé la config et j'ai plus l'erreur django. Ca c'est cool 👍

J'en reviens donc à mon 3ème point : l'envoie du formulaire n'upload pas le fichier :'(

Voici le print de mon formulaire lors de son envoie :

<tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" value="Gilles" class="form-control" placeholder="Lastname" maxlength="40" required id="id_last_name"></td></tr>
<tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" value="Stéphane" class="form-control" placeholder="Firstname" maxlength="25" required id="id_first_name"></td></tr>
<tr><th><label for="id_birthdate">Date de naissance:</label></th><td><input type="text" name="birthdate" value="2000-01-30" class="form-control datepicker" required id="id_birthdate"></td></tr>
<tr><th><label for="id_gender">Sexe:</label></th><td><select name="gender" class="form-control" required id="id_gender">
  <option value="">---------</option>
  <option value="0" selected>Male</option>
  <option value="1">Female</option>
</select></td></tr>
<tr><th><label for="id_is_active">Active:</label></th><td><input type="checkbox" name="is_active" id="id_is_active"></td></tr>
<tr><th><label for="id_trainings_by_week"># Training by week:</label></th><td><input type="text" name="trainings_by_week" value="2" class="form-control" placeholder="5" required id="id_trainings_by_week"></td></tr>
<tr><th><label for="id_hours_by_week"># Hours by week:</label></th><td><input type="text" name="hours_by_week" value="4" class="form-control" placeholder="11,5" required id="id_hours_by_week"></td></tr>
<tr><th><label for="id_picture">Picture:</label></th><td><input type="file" name="picture" accept="image/*" id="id_picture"></td></tr>
<tr><th><label for="id_club_related">Club related:</label></th><td><input type="text" name="club_related" value="Flying Acrobatics Trampoline (Lillois-Witterzée)" class="form-control" placeholder="Searching club…" data-ref="#id_club" required id="id_club_related"><input type="hidden" name="club" value="1" id="id_club"></td></tr>

Le champs picture semble vide, pourtant je lui fourni bien un fichier !
Je suis perplexe… Une/des idée(s) ?

Ok… J'ai donc changé la config et j'ai plus l'erreur django. Ca c'est cool 👍 J'en reviens donc à mon 3ème point : l'envoie du formulaire n'upload pas le fichier :'( Voici le print de mon formulaire lors de son envoie : ``` <tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" value="Gilles" class="form-control" placeholder="Lastname" maxlength="40" required id="id_last_name"></td></tr> <tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" value="Stéphane" class="form-control" placeholder="Firstname" maxlength="25" required id="id_first_name"></td></tr> <tr><th><label for="id_birthdate">Date de naissance:</label></th><td><input type="text" name="birthdate" value="2000-01-30" class="form-control datepicker" required id="id_birthdate"></td></tr> <tr><th><label for="id_gender">Sexe:</label></th><td><select name="gender" class="form-control" required id="id_gender"> <option value="">---------</option> <option value="0" selected>Male</option> <option value="1">Female</option> </select></td></tr> <tr><th><label for="id_is_active">Active:</label></th><td><input type="checkbox" name="is_active" id="id_is_active"></td></tr> <tr><th><label for="id_trainings_by_week"># Training by week:</label></th><td><input type="text" name="trainings_by_week" value="2" class="form-control" placeholder="5" required id="id_trainings_by_week"></td></tr> <tr><th><label for="id_hours_by_week"># Hours by week:</label></th><td><input type="text" name="hours_by_week" value="4" class="form-control" placeholder="11,5" required id="id_hours_by_week"></td></tr> <tr><th><label for="id_picture">Picture:</label></th><td><input type="file" name="picture" accept="image/*" id="id_picture"></td></tr> <tr><th><label for="id_club_related">Club related:</label></th><td><input type="text" name="club_related" value="Flying Acrobatics Trampoline (Lillois-Witterzée)" class="form-control" placeholder="Searching club…" data-ref="#id_club" required id="id_club_related"><input type="hidden" name="club" value="1" id="id_club"></td></tr> ``` Le champs picture semble vide, pourtant je lui fourni bien un fichier ! Je suis perplexe… Une/des idée(s) ?
Fred was assigned by Sulley 2021-12-21 12:57:43 +01:00
Fred removed their assignment 2021-12-21 13:19:49 +01:00
Collaborator

(évite les attributions de ticket 😉 sauf si on en a parlé ensemble et que je t'ai dit que je m'en occuperais)

  • A quel endroit fais-tu le print du formulaire ?
  • Quelle URL est appelée ?
  • A quoi ressemble le modèle ? Est-ce que tu as fait une ForeignKey ? Si je ne dis pas de bêtise, tu dois pouvoir accéder aux fichiers envoyés via request.FILES

La documentation parle de la gestion des formulaires accompagnés de fichiers (https://docs.djangoproject.com/en/4.0/topics/http/file-uploads/):

from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import ModelFormWithFileField

def upload_file(request):
    if request.method == 'POST':
        **form = ModelFormWithFileField(request.POST, request.FILES)**
        if form.is_valid():
            # file is saved
            form.save()
            return HttpResponseRedirect('/success/url/')
    else:
        form = ModelFormWithFileField()
    return render(request, 'upload.html', {'form': form})
(évite les attributions de ticket 😉 sauf si on en a parlé ensemble et que je t'ai dit que je m'en occuperais) * A quel endroit fais-tu le print du formulaire ? * Quelle URL est appelée ? * A quoi ressemble le modèle ? Est-ce que tu as fait une ForeignKey ? Si je ne dis pas de bêtise, tu dois pouvoir accéder aux fichiers envoyés via `request.FILES` La documentation parle de la gestion des formulaires accompagnés de fichiers (https://docs.djangoproject.com/en/4.0/topics/http/file-uploads/): ```python from django.http import HttpResponseRedirect from django.shortcuts import render from .forms import ModelFormWithFileField def upload_file(request): if request.method == 'POST': **form = ModelFormWithFileField(request.POST, request.FILES)** if form.is_valid(): # file is saved form.save() return HttpResponseRedirect('/success/url/') else: form = ModelFormWithFileField() return render(request, 'upload.html', {'form': form}) ```
Author
Owner

Ok. Si je ne t'assigne pas un ticket, comment sais-tu que j'ai besoin de ton aide et que c'est pas juste un ticket que je mets pour moi ?

J'ai lu la doc (j'avais pas encore lu cette partie là), j'ai changer pas mal de truc et ca avance ;-)

Le fichier est up dans le bon dossier et l'adresse de l'image est dans le bon dossier… mais l'image ne s'affiche pas dans le template. Une idée ?

Ok. Si je ne t'assigne pas un ticket, comment sais-tu que j'ai besoin de ton aide et que c'est pas juste un ticket que je mets pour moi ? J'ai lu la doc (j'avais pas encore lu cette partie là), j'ai changer pas mal de truc et ca avance ;-) Le fichier est up dans le bon dossier et l'adresse de l'image est dans le bon dossier… mais l'image ne s'affiche pas dans le template. Une idée ?
Collaborator

Bah techniquement, j'y répondrai si je peux y répondre.
A partir du moment où tu poses un ticket, c'est généralement que tu as besoin d'un avis.
Mais au final, c'est quand même toi qui fera l'implémentation 😜

Pour tes média, j'ai l'impression que tu as un clash entre l'URL (/media) et le dossier (que tu sembles avoir mis à la racine de ton disque, et qui ne sera en fait pas accessible à tous).

Tu pourrais poster ta configuration ?

Bah techniquement, j'y répondrai si je peux y répondre. A partir du moment où tu poses un ticket, c'est généralement que tu as besoin d'un avis. Mais au final, c'est quand même toi qui fera l'implémentation 😜 Pour tes média, j'ai l'impression que tu as un clash entre l'URL (`/media`) et le dossier (que tu sembles avoir mis à la racine de ton disque, et qui ne sera en fait pas accessible à tous). Tu pourrais poster ta configuration ?
Author
Owner
https://sources.grimbox.be/Sulley/Ultron/src/branch/gymnast_picture/config/settings.py#L139
Collaborator

(c/c 22/12/2021)

J'ai lu la doc (j'avais pas encore lu cette partie là), j'ai changer pas mal de truc et ca avance. Mais j'ai un souci d'OS :

Traceback (most recent call last):
  File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/views/decorators/http.py", line 40, in inner
    return func(request, *args, **kwargs)
  File "/Users/redj/Sites/Personnal/Ultron/ultron/people/views.py", line 350, in gymnast_create_or_update
    gymnast = gymnast_form.save()
  File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/forms/models.py", line 468, in save
    self.instance.save()
  File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/db/models/base.py", line 726, in save
    self.save_base(using=using, force_insert=force_insert,
  File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/db/models/base.py", line 763, in save_base
    updated = self._save_table(
  File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/db/models/base.py", line 842, in _save_table
    values = [(f, None, (getattr(self, f.attname) if raw else f.pre_save(self, False)))
  File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/db/models/base.py", line 842, in <listcomp>
    values = [(f, None, (getattr(self, f.attname) if raw else f.pre_save(self, False)))
  File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/db/models/fields/files.py", line 302, in pre_save
    file.save(file.name, file.file, save=False)
  File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/db/models/fields/files.py", line 89, in save
    self.name = self.storage.save(name, content, max_length=self.field.max_length)
  File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/core/files/storage.py", line 54, in save
    return self._save(name, content)
  File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/core/files/storage.py", line 255, in _save
    os.makedirs(directory, exist_ok=True)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/os.py", line 215, in makedirs
    makedirs(head, exist_ok=exist_ok)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/os.py", line 215, in makedirs
    makedirs(head, exist_ok=exist_ok)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/os.py", line 215, in makedirs
    makedirs(head, exist_ok=exist_ok)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/os.py", line 225, in makedirs
    mkdir(name, mode)

Exception Type: OSError at /gymnast/edit/4/
Exception Value: [Errno 30] Read-only file system: '/media'

SAUF QUE : mes dossier /media et /media/gymnast sont tous les deux en R+W pour tous. Je ne comprends pas d'ou vient l'erreur et Google ne m'aide pas pour l'instant :'(

(c/c 22/12/2021) J'ai lu la doc (j'avais pas encore lu cette partie là), j'ai changer pas mal de truc et ca avance. Mais j'ai un souci d'OS : ``` Traceback (most recent call last): File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/core/handlers/exception.py", line 47, in inner response = get_response(request) File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/core/handlers/base.py", line 181, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view return view_func(request, *args, **kwargs) File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/views/decorators/http.py", line 40, in inner return func(request, *args, **kwargs) File "/Users/redj/Sites/Personnal/Ultron/ultron/people/views.py", line 350, in gymnast_create_or_update gymnast = gymnast_form.save() File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/forms/models.py", line 468, in save self.instance.save() File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/db/models/base.py", line 726, in save self.save_base(using=using, force_insert=force_insert, File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/db/models/base.py", line 763, in save_base updated = self._save_table( File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/db/models/base.py", line 842, in _save_table values = [(f, None, (getattr(self, f.attname) if raw else f.pre_save(self, False))) File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/db/models/base.py", line 842, in <listcomp> values = [(f, None, (getattr(self, f.attname) if raw else f.pre_save(self, False))) File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/db/models/fields/files.py", line 302, in pre_save file.save(file.name, file.file, save=False) File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/db/models/fields/files.py", line 89, in save self.name = self.storage.save(name, content, max_length=self.field.max_length) File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/core/files/storage.py", line 54, in save return self._save(name, content) File "/Users/redj/Dev/.virtualenvs/ultron/lib/python3.10/site-packages/django/core/files/storage.py", line 255, in _save os.makedirs(directory, exist_ok=True) File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/os.py", line 215, in makedirs makedirs(head, exist_ok=exist_ok) File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/os.py", line 215, in makedirs makedirs(head, exist_ok=exist_ok) File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/os.py", line 215, in makedirs makedirs(head, exist_ok=exist_ok) File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/os.py", line 225, in makedirs mkdir(name, mode) Exception Type: OSError at /gymnast/edit/4/ Exception Value: [Errno 30] Read-only file system: '/media' ``` SAUF QUE : mes dossier /media et /media/gymnast sont tous les deux en R+W pour tous. Je ne comprends pas d'ou vient l'erreur et Google ne m'aide pas pour l'instant :'(
Collaborator

@Sulley Tu pourrais mettre un chemin absolu pour la configuration de la propriété MEDIA_ROOT ? Genre /home/Sulley/... ?

@Sulley Tu pourrais mettre un chemin absolu pour la configuration de la propriété `MEDIA_ROOT` ? Genre `/home/Sulley/...` ?
Author
Owner

Mais ca ne merchera plus sur Heroku alors... :-/

Mais j'ai plus de soucis de read-only (c'est pour ca que j'ai effacer le message)

Maintenant mon image est bien la dans le dossier. Et le lien généré semble OK.

<img src="/media/gymnast/Macaca_nigra_self-portrait_large_wY0HBBY.jpg" alt="Gilles, Stéphane" class="avatar">

Sauf que l'image ne se charge pas avec l'erreur suivante : Failed to load resource: the server responded with a status of 404 (Not Found)

Mais ca ne merchera plus sur Heroku alors... :-/ Mais j'ai plus de soucis de read-only (c'est pour ca que j'ai effacer le message) Maintenant mon image est bien la dans le dossier. Et le lien généré semble OK. ``` <img src="/media/gymnast/Macaca_nigra_self-portrait_large_wY0HBBY.jpg" alt="Gilles, Stéphane" class="avatar"> ``` Sauf que l'image ne se charge pas avec l'erreur suivante : `Failed to load resource: the server responded with a status of 404 (Not Found)`
Collaborator

Aoutch...

https://stackoverflow.com/questions/41474150/using-heroku-for-django-media-files

Heroku runs your application on dynos and dynos go to sleep after 30 minutes if there is not request comes, this makes Heroku not preserve user upload media files between dynos restart.

Bref... S3. 😜

Aoutch... https://stackoverflow.com/questions/41474150/using-heroku-for-django-media-files > Heroku runs your application on dynos and dynos go to sleep after 30 minutes if there is not request comes, this makes Heroku not preserve user upload media files between dynos restart. Bref... S3. 😜
Author
Owner

Ok. Je prends note... Mais la, je suis toujours local hein ! J'ai pas encore up sur heroku.

Et j'ai mis cela dans une branche. Donc pour l'instant, rien avoir avec Heroku et je le déploirai sur S3 ou tout ce que tu veux plus tard. Faisons le d'abord fonctionner en local avant d'envisager le reste.

Ok. Je prends note... Mais la, je suis toujours local hein ! J'ai pas encore up sur heroku. Et j'ai mis cela dans une branche. Donc pour l'instant, rien avoir avec Heroku et je le déploirai sur S3 ou tout ce que tu veux plus tard. Faisons le d'abord fonctionner en local avant d'envisager le reste.
Author
Owner

OK OK ! Ca marche !!!!!

OK OK ! Ca marche !!!!!
Sign in to join this conversation.
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: Sulley/Ultron#6
No description provided.