-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Mvp for image upload saving (#7)
* feat: Mvp for image upload saving Save extracted images, and make models for map previews * feat: Map previews Make development server serve files * feat: Map details - Implement map detail view - Better docs for permissions regarding editing - Check for object ban status in `CanEdit` permissions so that banned objects can't be edited by the offender - Fix pytest debugging by adding `setuptools` as a req. - Test that an uploaded map can be retrieved via the API
- Loading branch information
1 parent
3c418ff
commit 2ce9b6f
Showing
20 changed files
with
453 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# File uploads | ||
|
||
All file uploads should go into the `kirovy.models.file_base.CncNetFileBaseModel` class. | ||
|
||
This class uses Django's [upload_to](https://docs.djangoproject.com/en/5.0/ref/models/fields/#django.db.models.FileField.upload_to) | ||
logic to automatically place the files. By default, files will go to: | ||
|
||
- `{seetings.MEDIA_ROOT}/{game_slug}/{object.UPLOAD_TYPE}/{object.id}/filename.ext` | ||
|
||
An example of a default upload path would be: | ||
|
||
- `/uploaded_media/yr/uncategorized_uploads/1234/conscript_sprites.shf` | ||
|
||
## Customizing the upload path for a subclass | ||
|
||
Controlling where a file is saved can be easily done by changing `UPLOAD_TYPE: str` for the subclass. | ||
The default value is `uncategorized_uploads`. | ||
|
||
If you need even more control, then override `kirovy.models.file_base.CncNetFileBaseModel.generate_upload_to` with your | ||
own function. Files will still always be placed in `settings.MEDIA_ROOT`, but `generate_upload_to` can control | ||
everything about the upload path after that application-wide root path. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# Generated by Django 4.2.11 on 2024-08-15 03:35 | ||
|
||
from django.db import migrations | ||
from django.db.backends.postgresql.schema import DatabaseSchemaEditor | ||
from django.db.migrations.state import StateApps | ||
|
||
from kirovy import typing | ||
from kirovy.models import CncFileExtension as _Ext, CncUser as _User | ||
|
||
|
||
def _forward(apps: StateApps, schema_editor: DatabaseSchemaEditor): | ||
|
||
# This is necessary in case later migrations make schema changes to these models. | ||
# Importing them normally will use the latest schema state and will crash if those | ||
# migrations are after this one. | ||
CncFileExtension: typing.Type[_Ext] = apps.get_model("kirovy", "CncFileExtension") | ||
CncUser: typing.Type[_User] = apps.get_model("kirovy", "CncUser") | ||
|
||
migration_user = CncUser.objects.get_or_create_migration_user() | ||
|
||
jpg = CncFileExtension( | ||
extension="jpg", | ||
extension_type=_Ext.ExtensionTypes.IMAGE.value, | ||
about="Jpg files are used for previews on the website and in the client.", | ||
last_modified_by_id=migration_user.id, | ||
) | ||
jpg.save() | ||
|
||
jpeg = CncFileExtension( | ||
extension="jpeg", | ||
extension_type=_Ext.ExtensionTypes.IMAGE.value, | ||
about="Jpeg files are used for previews on the website and in the client.", | ||
last_modified_by_id=migration_user.id, | ||
) | ||
jpeg.save() | ||
|
||
png = CncFileExtension( | ||
extension="png", | ||
extension_type=_Ext.ExtensionTypes.IMAGE.value, | ||
about="PNG files are used for previews on the website and in the client.", | ||
last_modified_by_id=migration_user.id, | ||
) | ||
png.save() | ||
|
||
|
||
def _backward(apps: StateApps, schema_editor: DatabaseSchemaEditor): | ||
"""Deleting the games on accident could be devastating to the db so no.""" | ||
pass | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
("kirovy", "0006_cncmap_parent"), | ||
] | ||
|
||
operations = [ | ||
migrations.RunPython(_forward, reverse_code=_backward, elidable=False), | ||
] |
21 changes: 21 additions & 0 deletions
21
kirovy/migrations/0008_alter_cncfileextension_extension_type.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Generated by Django 4.2.11 on 2024-08-15 03:54 | ||
|
||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
("kirovy", "0007_jpg_png"), | ||
] | ||
|
||
operations = [ | ||
migrations.AlterField( | ||
model_name="cncfileextension", | ||
name="extension_type", | ||
field=models.CharField( | ||
choices=[("map", "map"), ("assets", "assets"), ("image", "image")], | ||
max_length=32, | ||
), | ||
), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# Generated by Django 4.2.11 on 2024-08-15 04:00 | ||
|
||
from django.conf import settings | ||
from django.db import migrations, models | ||
import django.db.models.deletion | ||
import kirovy.models.file_base | ||
import uuid | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
("kirovy", "0008_alter_cncfileextension_extension_type"), | ||
] | ||
|
||
operations = [ | ||
migrations.CreateModel( | ||
name="MapPreview", | ||
fields=[ | ||
( | ||
"id", | ||
models.UUIDField( | ||
default=uuid.uuid4, | ||
editable=False, | ||
primary_key=True, | ||
serialize=False, | ||
), | ||
), | ||
("created", models.DateTimeField(auto_now_add=True, null=True)), | ||
("modified", models.DateTimeField(auto_now=True, null=True)), | ||
("name", models.CharField(max_length=255)), | ||
( | ||
"file", | ||
models.FileField( | ||
upload_to=kirovy.models.file_base._generate_upload_to | ||
), | ||
), | ||
("hash_md5", models.CharField(max_length=32)), | ||
("hash_sha512", models.CharField(max_length=512)), | ||
("is_extracted", models.BooleanField()), | ||
( | ||
"cnc_game", | ||
models.ForeignKey( | ||
on_delete=django.db.models.deletion.PROTECT, to="kirovy.cncgame" | ||
), | ||
), | ||
( | ||
"cnc_map_file", | ||
models.ForeignKey( | ||
on_delete=django.db.models.deletion.CASCADE, | ||
to="kirovy.cncmapfile", | ||
), | ||
), | ||
( | ||
"file_extension", | ||
models.ForeignKey( | ||
on_delete=django.db.models.deletion.PROTECT, | ||
to="kirovy.cncfileextension", | ||
), | ||
), | ||
( | ||
"last_modified_by", | ||
models.ForeignKey( | ||
null=True, | ||
on_delete=django.db.models.deletion.SET_NULL, | ||
related_name="modified_%(class)s_set", | ||
to=settings.AUTH_USER_MODEL, | ||
), | ||
), | ||
], | ||
options={ | ||
"abstract": False, | ||
}, | ||
), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import pathlib | ||
import uuid | ||
|
||
from django.db import models | ||
|
||
from kirovy import typing as t | ||
from kirovy.models import cnc_map, file_base, cnc_user, cnc_game | ||
|
||
|
||
class MapPreview(file_base.CncNetFileBaseModel): | ||
"""An image preview for a C&C Map upload. | ||
.. note:: | ||
This class has no user link. The link to the user is via | ||
:attr:`kirovy.models.map_preview.CncMapPreview.cnc_map`. | ||
.. note:: | ||
Map previews are uploaded to the same directory as map files using | ||
:func:`kirovy.models.cnc_map.CncMap.get_map_directory_path` through this class's | ||
:attr:`kirovy.models.map_preview.CncMapPreview.cnc_map`. | ||
""" | ||
|
||
cnc_map_file = models.ForeignKey(cnc_map.CncMapFile, on_delete=models.CASCADE) | ||
"""The map file that this preview belongs to. We link to the file so that we can have version-specific previews.""" | ||
|
||
ALLOWED_EXTENSION_TYPES = { | ||
cnc_game.CncFileExtension.ExtensionTypes.IMAGE.value, | ||
} | ||
|
||
is_extracted = models.BooleanField(null=False, blank=False) | ||
"""If true, then this image was extracted from the uploaded map file, usually generated by FinalAlert. | ||
This will always be false for games released after Yuri's Revenge because Generals and beyond do not pack the | ||
preview image into the map files. | ||
""" | ||
|
||
def save(self, *args, **kwargs): | ||
self.name = self.cnc_map_file.name | ||
self.cnc_game = self.cnc_map_file.cnc_game | ||
return super().save(*args, **kwargs) | ||
|
||
@staticmethod | ||
def generate_upload_to(instance: "MapPreview", filename: str) -> pathlib.Path: | ||
"""Generate the path to upload map previews to. | ||
Gets called by :func:`kirovy.models.file_base._generate_upload_to` when ``CncMapFile.save`` is called. | ||
See [the django docs for file fields](https://docs.djangoproject.com/en/5.0/ref/models/fields/#filefield). | ||
``upload_to`` is set in :attr:`kirovy.models.file_base.CncNetFileBaseModel.file`, which calls | ||
``_generate_upload_to``, which calls this function. | ||
:param instance: | ||
Acts as ``self``. The map preview object that we are creating an upload path for. | ||
:param filename: | ||
The filename of the uploaded file. | ||
:return: | ||
Path to upload map to relative to :attr:`~kirovy.settings.base.MEDIA_ROOT`. | ||
""" | ||
filename = pathlib.Path(filename) | ||
filename_uuid = str(uuid.uuid4()).replace("-", "") | ||
final_file_name = f"{instance.name}_{filename_uuid}{filename.suffix}" | ||
|
||
# e.g. "yr/maps/CNC_NET_MAP_ID_HEX/ra2_map_file_name_UUID.png | ||
return pathlib.Path( | ||
instance.cnc_map_file.cnc_map.get_map_directory_path(), final_file_name | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
from kirovy.settings.base import * | ||
from ._base import * |
Oops, something went wrong.