0

I have a django app that saves games and screenshots. When I save a game I download the screenshots and save them:

class ImageModel(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    img = models.ImageField()

class Game(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    screenshots = models.ManyToManyField(ImageModel)
    screenshots_urls = models.JSONField()

When the game is saved a directory like /games/<game_uuid>/ and /games/<game_uuid>/screenshots/ are created.

Then the screenshots are downloaded and saved in the DB.

Next to display them in a view I was thinking of adding something like this to settings:

GAMES_FOLDER = Path('/games/')
STATIC_URL = 'static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
VENV_PATH = os.path.dirname(BASE_DIR)
STATIC_ROOT = os.path.join(VENV_PATH, 'static_root')
SCREENSHOTS_URL = GAMES_FOLDER / "GAME_UUID" / "screenshots" / "IMAGE_UUID.png"
SCREENSHOTS_ROOT = ""

urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.SCREENSHOTS_URL, document_root=settings.SCREENSHOTS_ROOT)

Then adding a custom tag for screenshots urls since they're not in the common static folder.

Am I complicating this too much?

Do I even need ImageModel if I'm just saving the images to disk, can't I just make game.screenshots an array of image filenames?

Or is there a reason why I might want images saved as ImageModel?

Edit:

I think what I'm looking for is something like

urlpatterns += static(settings.SCREENSHOTS_URL+'<uuid:game_id>/<uuid:image_id>.png', document_root=settings.SCREENSHOTS_ROOT)

Could I work with that to make django search the image in the correct folder?

Daviid
  • 630
  • 4
  • 17

2 Answers2

1

The approach you outlined in the settings file seems reasonable to display the screenshots in a view. Regarding the usage of ImageModel, its purpose may depend on the specific requirements of your application. If you only need to save the image filenames and are confident in managing them on disk, you could consider storing them directly in the Game model. However, using ImageModel provides flexibility if you have additional image-related metadata or if you want to perform specific operations on the images in the future, such as resizing or processing.

Edit In your views.py,

from django.http import HttpResponse
from django.views import View
from django.conf import settings
import os

class CustomImageView(View):
    def get(self, request, game_id, image_id):
        image_path = os.path.join(settings.SCREENSHOTS_ROOT, str(game_id), str(image_id) + '.png')
        with open(image_path, 'rb') as f:
            image_data = f.read()
        return HttpResponse(image_data, content_type='image/png')

In your urls.py,

from django.urls import path
from .views import CustomImageView

urlpatterns = [
    # Other URL patterns
    path('screenshots/<uuid:game_id>/<uuid:image_id>.png', CustomImageView.as_view(), name='custom_image_view'),
]

And in your settings.py,

SCREENSHOTS_ROOT = '/path/to/screenshots/root/folder/'

With this setup, when a request is made to the URL /screenshots/<game_id>/<image_id>.png, Django will invoke the CustomImageView view, which will read the image file from the specified location and serve it as a response.

Jamil
  • 104
  • 2
0

You can use a FileField with a custom 'upload' function creating a dynamic upload path at save time.

Here is a sample:

class Image(models.Model):

    def user_directory_path(self, filename):
        # This will be called to obtain the upload path, including the filename(!!!)
        # file will be uploaded to MEDIA_ROOT/my_image_folder/uuid_filename/

        (name, extension)= os.path.splitext(filename)
        return 'my_image_folder/' + str(uuid.uuid4())[:8] + '_' + name + '/' + filename

   title = models.CharField(max_length=100)
   file = models.FileField(upload_to=user_directory_path, blank=True, null=True)
   post_date = models.DateField(blank=True, null=True)

If you dont want to store relative to MEDIA_ROOT you can set additionally "storage" in the similar logic ... see https://docs.djangoproject.com/en/4.2/topics/files/#file-storage

Razenstein
  • 3,532
  • 2
  • 5
  • 17
  • Saving the images is not a problem, but since I'm saving them outside of the media and static folders I was wondering if I could create a custom handler for them. – Daviid Jul 12 '23 at 11:46
  • see the added comment at the end ... FileSystemStorage etc. should do what you need – Razenstein Jul 12 '23 at 11:53