イメージジェネレータ


あなたがmockupsの特に顔を持つランダムに生成された人々を持つ必要があるWeb開発に共通の問題があります.私はdjangoアプリを作るとき、先日、この問題に乗り込みました.それを知るhttps://thispersondoesnotexist.com/ ことは、そのサイトからイメージを取り込む人モデルと管理者を書くことに決めました.以下にその機能を紹介します.
  • Django管理インターフェイスで生成されたイメージをプレビューする方法です.
  • 私が生成された最初のものが好きでないならば、管理者インターフェースで新しいイメージを生成する方法.
  • モデルの作成と削除のイメージファイルの保存と削除を処理する方法です.
  • それで、それに飛び込みましょう!

    プロジェクト設定


    人アプリでdjangoプロジェクトを作成します.
    pip install Django Pillow requests
    django-admin startproject project .
    cd project
    django-admin startapp persons
    
    必ず加えるpersons アプリケーションをInstalldCloseにproject/settings.py .
    INSTALLED_APPS = [
        ...
        'project.persons'
    ]
    
    下にproject/settings.py 我々は画像を保存されるメディアの設定を追加します.
    MEDIA_ROOT = BASE_DIR / "media"
    MEDIA_URL = "/media/"
    
    プロジェクトのルートでメディアディレクトリを作成します.画像を保存するmedia/persons/ .
    media/
      persons/
    project/ # our Django project
      persons/ # our Django app
      ...
    ...
    

    イメージダウンローダ


    ビューを作成するpersons/views.py これはリクエストライブラリを使用してから画像をダウンロードするhttps://thispersondoesnotexist.com/image . 我々は、後に我々の人管理者からこの見解を取り戻しています.
    from django.http import JsonResponse
    from django.conf.global_settings import MEDIA_URL
    import requests
    
    def generate_image(request):
        # Use this site to generate an image file of a person
        url = 'https://thispersondoesnotexist.com/image'
        req = requests.get(url)
        # Adjust the names and paths below to fit your project
        filename = '/persons/tmp.jpg'
        with open("media" + filename, "wb+") as f:
            f.write(req.content)
    
        return JsonResponse(data={
            "path": MEDIA_URL + filename
        })
    
    ビューとメディア静的サーバーを追加しますurls.py .
    from django.conf import settings
    from django.conf.urls.static import static
    from django.contrib import admin
    from django.urls import path
    from project.persons.views import generate_image
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('generate-image/', generate_image, name="generate-image")
    ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    
    訪問するcurl http://127.0.0.1:8000/generate-image/ それが動作することを確認します.

    モデルと管理


    モデルを作成するpersons/models.py . The save() デフォルトで保存されたイメージを確認するために、メソッドを上書きします
    (生成された画像)自身のファイルとして保存されます.ピローライブラリによる画像処理は、画像のサイズを変更します.The delete() メソッドは、イメージファイルがモデルとともに削除されることを確認するために上書きされます.これらのメソッドをオーバーライドするにはhere .
    from django.db import models
    from shutil import copy2
    from datetime import datetime
    import os
    from PIL import Image  
    
    MEDIA_LOCATION = "persons"
    DEFAULT = "tmp.jpg"
    class Person(models.Model):
        name = models.CharField(max_length=100)
        image = models.ImageField(upload_to=MEDIA_LOCATION, default=f"{MEDIA_LOCATION}/{DEFAULT}")
    
        def save(self, *args, **kwargs):
            if DEFAULT in self.image.url:
                # Copy image to a new, unique file related to the person's name and the time of download
                new_filename = f"{self.name[:10]}-{datetime.now().isoformat()}"
                new_filename = "".join([c for c in new_filename if c.isalpha() or c.isdigit()]).rstrip() + ".jpg"
                copy2(f"media/{MEDIA_LOCATION}/{DEFAULT}", f"media/{MEDIA_LOCATION}/{new_filename}")
            self.image = f"{MEDIA_LOCATION}/{new_filename}"
            # Save the image and resize it
            super(Person, self).save(*args, **kwargs) 
            # The [1:] slice is to remove the / in front of /media/persons/...
            im = Image.open(self.image.url[1:])  
            if im.width > 150: 
                im = im.resize((150, 150))
                im.save(self.image.url[1:])
    
        def delete(self, *args, **kwargs):
            # Delete the image file along with the model
            try:
                os.remove(self.image.url[1:])
            except:
                pass
            super(Person, self).delete(*args, **kwargs)
    
        def __str__(self):
            return f"Person {self.id}: {self.name}"
    
    モデルを登録するpersons/admin.py . 我々は、我々はプレビューすることができます画像を生成するカスタムウィジェットを使用して少し管理のカスタマイズを行うつもりです.ウィジェットの詳細についてはhere .
    from django.contrib import admin
    from django.db import models
    from django.forms.widgets import ClearableFileInput 
    
    from project.persons.models import Person
    
    class ImageWidget(ClearableFileInput):
        template_name = "image_widget.html"
    
    class PersonAdmin(admin.ModelAdmin):
        formfield_overrides = {
            models.ImageField: {'widget': ImageWidget},
        }
    
    admin.site.register(Person, PersonAdmin)
    
    ここにテンプレートと一緒に行きます.に入れるpersons/templates/image_widget.html
    {% include "django/forms/widgets/clearable_file_input.html" %}
    
    {% if widget.value %}
      {% comment %} This is for when you are changing a person {% endcomment %}
      <img src="{{ widget.value.url }}" id="currentImage" width="100" alt="current image">
    {% else %}
      {% comment %} This is for when you are adding a person {% endcomment %}
      <div>
        <h5>If no file above, this generated image will be used</h5>
        <img id="generatedImage" width="100">
        <button id="newImage">Get New Image</button>
        <span id="loading" style="display: none;">Loading...</span>
      </div>
      <script>
        function loadImage() {
          // The date thingy at the end is prevent image caching
          document.getElementById("generatedImage").setAttribute("src", "/media/persons/tmp.jpg?"+new Date().toISOString())
        }
        loadImage()
        async function getNewImage(e) {
          const loading = document.getElementById("loading")
          loading.style.display = "inline"
          e.preventDefault()
          await fetch('{% url "generate-image" %}').then(() => {
            loadImage()
            loading.style.display = "none"
          })
        }
        document.getElementById("newImage").onclick = getNewImage
      </script>
    {% endif %}
    
    必ずデータベースを移行してください.私はちょうど設定からSQLiteデータベースのデフォルトを使用しています.アドミンにログインするためにスーパーユーザも作成します.
    python3 manage.py makemigrations
    python3 manage.py migrate
    python3 manage.py createsuperuser
    
    一旦それらのものがセットアップされるならば、サーバーと訪問を実行してください127.0.0.1:8000/admin/ 人を追加しようとする.次のように表示されます.

    ページ管理者追加


    をクリックして存在しない別の人を取得するgenerate-image 我々が以前に書いた見解.

    変更人管理ページ


    ちょうど人のイメージのプレビューを示しています.

    終わり


    そして、それ!この投稿用のコードはGitHub . グッドラック!