django multi file upload fields - django

List item
registration start date
Year
Vin#
Make
Title Owner (Upload field) ==== (can be several files)
HUT # (Upload field) ==== (can be several files)
Ifta # (Upload field) ==== (can be several files)
I need that model
If file upload fields had to be for a single file, then it would be okay, but how Can I handle that model?
(Should I create ForeignKey models for every file_upload field in order to handle multi file uploads??)

I would write something like this:
files_titleowner = models.ManyToManyField(FileTitleOwner, related_name="mymodel_filetitleowner", blank=True)
...
and so on. I usually specify the related_name attribute for each many to many field.
FileTitleOwner could be like this:
class FileTitleOwner(models.Model):
file = models.FileField(upload_to=user_directory_path,
null=True, blank=True,
verbose_name="...")
...
Also, user_directory_path is a function which returns the pathname for the file to be stored on file system:
def user_directory_path(instance, filename):
...
return f"{<construct opportunely a directory name>}/{filename}"

Related

Is there a way to avoid django to upload same name file again by altering its name

I'm trying to develop a simple model form by Django to upload pdf files. The form is based on a model. Every time, user upload a file a database table entry would be created with the file path (including filename), uploaded user name and time Etc.
when I upload the same file again, Django is uploading the same file by altering its name (poster-proposal.pdf ->poster-proposal_IomFZQM.pdf). It is also creating another entry in the database table.
I want Django to give the user a warning when he is trying to upload an already existing file saying (a file with the same name is already existing) or something like that and not to upload the duplicate file.
I followed this post,post 1 but it says it does not prevent Django from uploading the file.
I followed this method post 2, but I'm new to Django and it seems complicated. I believe for newer Django versions there should be an easier way to address this issue.
I added unique = True to FileField.It did not work
models.py
class files(models.Model):
repo_id = models.ForeignKey(Repository, on_delete = models.CASCADE)
username = models.CharField(db_column='username',max_length = 45)
date = models.DateTimeField(auto_now_add=True, db_column = 'date')
file = models.FileField(upload_to='documents/', db_column = 'file', unique = True)
indicator_name =models.CharField(db_column = 'indicator_name',max_length = 100)
username = models.CharField(db_column='username',max_length = 45)
Any idea would be highly appreciated. Thanks
The simplest way is to search for the name and then upload the file:
# Note that file name depends on your upload_to path.
# Either you should include it in the search or you have to use something like:
# filter(file_contains="filename") which might return results that you don't want
filename = "documents/" + filename_you_want_to_upload
files = files.objects.filter(file=filename)
if files.count() > 0:
# A file with that name exists.
# Return some error or ...
else:
# There is no file with that name.
# Upload the file and save it to database.

Django forms - is there a way to dynamically edit a FilePathField?

I have a django form which I am using to access a directory. However I would like to access two different directories based on a given input, but have one FilePathField.
As an example - I have two panels - 'panel1' and 'panel2'. The directory I would like to access is the analysis directory of each of these panels as such:
/path/destination/panel1/analysis/
/path/destination/panel2/analysis/
In each of these analysis directories are directories starting with "Experiment" which I would like a user to be able to choose to obtain some results.
I have my form:
class RunUploadForm(forms.Form):
directory_path = forms.FilePathField(
path='/path/destination/panel1/analysis',
required=True,
allow_folders=True,
allow_files=False,
recursive=True,
match="Experiment*",
label="Pick folder for results:"
)
class Meta:
fields = ('directory_path',)
This only allows the user to access panel1 directory as it is hardcoded into the path arg. Is there a way to dynamically change this path argument, maybe with a choicefield?
One way of doing so would be to pass the path as an argument to the __init__ method of the form, for example:
class RunUploadForm(forms.Form):
directory_path = forms.FilePathField(
path='/path/destination/panel1/analysis',
required=True,
allow_folders=True,
allow_files=False,
recursive=True,
match="Experiment*",
label="Pick folder for results:"
)
class Meta:
fields = ('directory_path',)
def __init__(self, *args, **kwargs):
path = kwargs.pop('path', 'somedefaultvalue')
super().__init__(*args, **kwargs)
self.fields['directory_path'] = forms.FilePathField(
path=path,
required=True,
allow_folders=True,
allow_files=False,
recursive=True,
match="Experiment*",
label="Pick folder for results:"
)
You need to crate a new instance of FilePathField because choices for this kind of field are generated on __init__

Error Importing .csv file into pgsql

I am attempting to upload data into my postgres database using an excel file that I have converted into a .csv file. My .csv file is a simple test file, it contains only one row of data, all of which have cells that are formatted to be text and the titles of which match the columns in my data model.
The data model I am attempting to upload data to looks like:
class Publication(models.Model):
title = models.CharField(max_length=200)
journalists = models.ManyToManyField(Journalist, blank=True)
email = models.EmailField(blank=True)
tags = models.ManyToManyField(Tag, blank=True, related_name="publications")
url = models.URLField(blank=True)
notes = models.CharField(max_length=500, blank=True)
image_url = models.URLField(blank=True)
media_kit_url = models.URLField(blank=True)
When I go into psql and enter the command:
\copy apricot_app_publication from '~/Desktop/sampleDBPubs.csv';
I get back the following error:
ERROR: invalid input syntax for integer: "title,url,email,media_kit_url,notes,tags,image_url,journalists"
CONTEXT: COPY apricot_app_publication, line 1, column id: "title,url,email,media_kit_url,notes,tags,image_url,journalists"
I looked at this question Importing csv file into pgsql which addresses the same issue, but the answer given was that the error means that "you're trying to input something into an integer field which is not an integer...", but my data model does not have any integer fields, so I do not know how to solve the issue.
Can anyone suggest what might be causing the issue?
I just answered my own question. There is an automatically generated id column that is created behind the scenes on anything that has a many to many relationship in my Django app. Thus, the database is expecting an integer to be added from the .csv file, which is the id, but my .csv file does not have an id column and I do not want to add one as want the id's to continue to be auto-generated.
To get around this, I just have to specify which columns my file is going to provide data for in parenthesis after the table name:
EX:
\copy apricot_app_tag(title) FROM '~/Desktop/Sample_Database_Files/tags.csv' with csv header
Where 'title' is the only column in the tag table I want to update.

Dynamic File Path for image in Django

I'm trying to generate dynamic file paths in django. I want to make a file system like this
hierarchy:
--user_12
--channel_14
--program 2
--image1.jpg
--image2.jpg
--program 1
--image1.jpg
--image2.jpg
--user_14
--channel_13
--program 1
--image1.jpg
--image2.jpg
When a user want to upload image it will upload the image to the corresponding program folder.if program folder does not create it will automatically create a folder and store image..
my image path will look like this: media/images/john/johnchannel/birthday/img1.jpg ( where john=user,johnchannel=channel,birthday=program,images is the pre created folder where all image file should be stored)
I am very new in django. urgent help needed.
Are you looking for something like this?
misc.py
def get_upload_path(instance, filename):
""" creates unique-Path & filename for upload """
ext = filename.split('.')[-1]
filename = "%s%s.%s" % ('img', instance.pk, ext)
return os.path.join(
'images', instance.user.username, instance.channel, instance.something, filename
#images/ john/ johnchannel/ birthday/ img1.jpg
)
models.py
from misc import get_upload_path
class MyThing(models.Model):
user = models.ForeignKey(User)
channel = models.CharField(max_length=100) # johnchannel
something = models.CharField(max_length=100) # birthday
img = models.ImageField(upload_to=get_upload_path)
When using an ImageField in a Django model, you can specify a callable in the upload_to keyword argument: See the FileField docs here
So create a function that you'll point upload_to at, which can generate all your subdirectories as needed.

How do I reference the other object in django models

first post here.In Django, I want to have many files be associated with a particular model, so I'm doing a seperate model called files and have model 'A' 'have many' files. But I want my files to be saved in director named by model 'A'. So For example I want something like this:
class Show(models.Model):
name = models.CharField()
showfolder = models.FilePathField()
class Episode(models.Model):
show = models.ForeignKey(Show)
name = models.CharField()
files = models.ManyToManyField(mp3)
class Mp3(models.Model):
file = FileField(upload_to=Episode.show.showfolder)
So hopefully that last line expresses what I WANT it to do(get the folder name from Show object associated with the episode). The question is how would I really write that?(besides jumping through hoops in the controller.)
Thanks.
In your current model because of Episode ManyToMany relation to Mp3 it is possible for one file to be associated with one or more episodes. That would mean that your file will have to simultaneously exist in several locations.
To have a hierarchical structure you need ForeignKey to Episode in Mp3 model:
class Mp3(Model):
episode = ForeignKey(Episode)
Now about your file name. According to django documentation, upload_to attribute can accept callable and will pass two arguments to it: instance and filename.
def get_file_name(instance, original_filename):
return os.path.join(MEDIA_ROOT, 'mp3', instance.episode.show.showfolder,
original_filename)
class Mp3(Model):
file = FileField(upload_to=get_file_name)