I’ve been thinking about a potentially better way for handling media in my project. I have three models, Audio, Video and Image which reside in one app but are used extensively by all other apps. The reason for having media have their own model is because there are many models which have either a one-to-many or many-to-many relationship to the media.
In order to simplify things a bit and try to make each app a little less dependant on other apps (nobody likes circular imports) I have entertained a couple of ideas.
For each app, create its own Audio, Video and Image models.
Create one app, called Media, and define Audio, Video and Image there.
Option 1 seems more flexible, but a lot less DRY and perhaps more work than necessary. It does however make each app much less reliant on the current app with the media definitions.
Option 2 seems DRYer, separates out concerns quite well and is easily extensible, but I just have this nagging feeling like I’m walking into a trap.
So I guess my question is what do you think? Do you have any experience with such ideas or perhaps you have a complete different way of solving the design issue?
I guess the most significant questions would revolve around the relationships of the data and functionality among the apps. If the Audio, Video and Image models are really identical between the apps and you want to keep the data for those models segregated among the apps, you could create a base Audio, Video and Image model as an abstract parent class, creating app-specific instances in each app.
I’m currently working on a project. It’s for a band website. I want users to be able to upload media content (audio, video, images). The uploaded media content can then be used in collections, for blog posts and the archive. In the archive you can display different collections of media files, for instance a music album would have cover art (images) and tracks (audio). I am still at a point where I feel quite insecure about design decisions I make. But maybe my thoughts can be helpful to you?
My current design plan is to have a model which is a shell for files. It will have a file field, where the actual file is stored or alternatively there is a URL field for media files, that are not stored locally. It will have a field “type” and a boolean field “internal” to differentiate on the different types.
The File model will then be associated with with different Data Container Models. For instance the model Gallery would be a list of Files which are images. The model MusicAlbum would be a collection with front_artwork (Image File), back_artwork (Image File) and tracks (a list of Files that are audio).
So coming back to your initial questions: I have decided for option 2 in my case. As I said I’m far from being a good and experienced designer. My goal is to have all code concerning the handling of the file in one place. And I want all the code concerning displaying media in one place wich is the data container. I want the blog post to be oblivious of the data other then knowing that it has a container.
Thanks for the info. I like your thinking about all the code for the File being in one place. That’s very much what I’m trying to do if I can, and I think Ken’s suggestion about an abstract base class is the way to go.
Regarding your design, from what I can understand is that you’ll have a model which looks something like this
file = models.FileField()
type = (Are you thinking a string like "jpeg" or something similar)
internal = models.BooleanField()
And then your Gallery model would relate to the MyFile model?
file = models.ForeignKey(MyFile)
So effectively you’re implementing a base class which is flexible media model and your other media models inherit from it? If that is the case, I think it will work just fine and like your thinking about defining a model which defines what a file is in your system. The reason I have done what I have done (and by no way am I saying that this is a good design or the right way to do it) is by creating separate models for Image, Video and Audio, I avoid having to implement logic such as if this media type, do that etc. I have found however that I have had to write methods, whether it is for create instances of these media models or class methods which are quite similar, and hence could perhaps be refactored into something DRYer.
Can I ask if you have come across any particular pain points in your design? The biggest pain point for me at the moment is the lack of flexibility by having just one Image model which spans all my apps, and that sometimes that can cause circular imports. Hence why I’m looking at doing something along the lines of what you have done and Ken has suggested.
the models would look a bit differently. The foreign key field always goes to the child model. A data container, in this case a gallery, contains files. Also, I don’t want to define a foreign key relationship for every type fo data container (gallery, album, etc…), but rather I want a relationship to all data container, so it would look something like this:
file = m.FileField()
type = m.CharField(choices=...)
internal = m.BooleanField()
container = m.ForeignKey(DataContainer)
The gallery then would look like this:
common_attributes = ...
name = m.CharField()
name = m.CharField()
In this case, DataContainer must be a concrete class. If it were abstract, we couldn’t have a ForeingKey-Field relating to it. A pain point for this design is definetly the Django Admin as it becomes quite tricky with more complex inter model relationships.
if this media type, do that etc . I have found however that I have had to write methods, whether it is for create instances of these media models or class methods which are quite similar, and hence could perhaps be refactored into something DRYer.
I had experimented with creating a content management system in Django before and I tried an approach where I had different models for audio, video and image. I eventually ran into cases, where I had to figure out, which one a model was. However, that might have been just my fault.