Set new `path` value for ImageField - python

I have the following situation. Project files was stored in ~/django-apps/app-old/app. For some reasons I move files to ~/django-apps/app . Application have some images, stored with use of ImageField. In database images have paths like so:
~/django-apps/app-old/app/media/images/blabla.jpeg
So, I need to fix this paths in database to look like this:
~django-apps/app/media/images/blabla.jpeg
I try to write management command for to do this:
from django.core.management.base import BaseCommand, CommandError
from books.models import Book
import string
class Command(BaseCommand):
help = ''
def handle(self, *args, **options):
books = Book.objects.all()
total = len(books)
curr = 1
for book in books:
print "%d/%d" % (curr, total)
if book.cover_url != "":
book.cover_url.path = string.replace(book.cover_url.path, "app-old/", "")
book.save()
curr+=1
By using this command I get following error:
Traceback (most recent call last):
File "manage.py", line 11, in <module>
execute_manager(settings)
File "/usr/local/lib/python2.6/dist-packages/django/core/management/__init__.py", line 438, in execute_manager
utility.execute()
File "/usr/local/lib/python2.6/dist-packages/django/core/management/__init__.py", line 379, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/usr/local/lib/python2.6/dist-packages/django/core/management/base.py", line 191, in run_from_argv
self.execute(*args, **options.__dict__)
File "/usr/local/lib/python2.6/dist-packages/django/core/management/base.py", line 220, in execute
output = self.handle(*args, **options)
File "/var/www/dizpers/data/django-apps/app/books/management/commands/fix-covers-path.py", line 23, in handle
book.cover_url.path = string.replace(book.cover_url.path, "bparser-old/", "")
File "/usr/local/lib/python2.6/dist-packages/django/db/models/fields/files.py", line 65, in _get_path
return self.storage.path(self.name)
File "/usr/local/lib/python2.6/dist-packages/django/core/files/storage.py", line 234, in path
raise SuspiciousOperation("Attempted access to '%s' denied." % name)
django.core.exceptions.SuspiciousOperation: Attempted access to '/var/www/dizpers/data/django-apps/app-old/app/media/covers/a3d9545d3a17bb68a91749019c95357d.jpeg' denied.
Why I get this error message? How I can fix image's path?
UPD1
My model contain ImageField like this:
cover_url = models.ImageField(upload_to=os.path.join(MEDIA_ROOT, "covers"), null=True, default=None)
UPD2
Path property is readonly

This should work
for book in books:
print "%d/%d" % (curr, total)
if book.cover_url != "":
new_path = string.replace(book.cover_url.path, "app-old/", "")
book.cover_url = new_path
book.save()
curr+=1

You get this message because the default file system storage prevents usage of absolute path for security reasons.
If you really want to use an absolute path
django-documents forces absolute paths for security reasons, this is how:
from django.core.files.storage import FileSystemStorage
fs = FileSystemStorage(location=UPLOAD_TO)
class Document(models.Model):
file = models.FileField(storage=fs, upload_to=UPLOAD_TO)
Where UPLOAD_TO can be an absolute path.
-- UPDATE IN REPLY TO QUESTION UPDATE --
If you don't need such security
Then you should read the documentation on FileField:
FileField.upload_to
A local filesystem path that will be appended to your MEDIA_ROOT setting to determine the value of the url attribute.
In your case, upload_to='covers' is sufficient.
Note that relative paths should be stored in the database.

Related

IOError : [Error no: 21] is a directory : './w2v-model/wordmodel3'

def generate_w2vModel(decTokenFlawPath, w2vModelPath):
print("training...")
model = Word2Vec(sentences= DirofCorpus(decTokenFlawPath), size=30, alpha=0.01, window=5, min_count=0, max_vocab_size=None, sample=0.001, seed=1, workers=1, min_alpha=0.0001, sg=1, hs=0, negative=10, iter=5)
model.save(w2vModelPath)
def evaluate_w2vModel(w2vModelPath):
print("\nevaluating...")
model = Word2Vec.load(w2vModelPath)
for sign in ['(', '+', '-', '*', 'main']:
print(sign, ":")
print(model.most_similar_cosmul(positive=[sign], topn=10))
def main():
dec_tokenFlaw_path = ['./data/cdg_ddg/corpus/']
w2v_model_path = "./w2v_model/wordmodel3"
generate_w2vModel(dec_tokenFlaw_path, w2v_model_path)
evaluate_w2vModel(w2v_model_path)
print("success!")
this the python that i was running. This file is used to train word2vec model. The inputs are corpus files, and the output is the word2vec model. i got the following error :
Traceback (most recent call last):
File "create_w2vmodel.py", line 67, in <module>
main()
File "create_w2vmodel.py", line 62, in main
generate_w2vModel(dec_tokenFlaw_path, w2v_model_path)
File "create_w2vmodel.py", line 50, in generate_w2vModel
model.save(w2vModelPath)
File "/usr/local/lib/python2.7/dist-packages/gensim-3.4.0-py2.7-linux-x86_64.egg/gensim/models/word2vec.py", line 930, in save
super(Word2Vec, self).save(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/gensim-3.4.0-py2.7-linux-x86_64.egg/gensim/models/base_any2vec.py", line 281, in save
super(BaseAny2VecModel, self).save(fname_or_handle, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/gensim-3.4.0-py2.7-linux-x86_64.egg/gensim/utils.py", line 691, in save
self._smart_save(fname_or_handle, separately, sep_limit, ignore, pickle_protocol=pickle_protocol)
File "/usr/local/lib/python2.7/dist-packages/gensim-3.4.0-py2.7-linux-x86_64.egg/gensim/utils.py", line 550, in _smart_save
pickle(self, fname, protocol=pickle_protocol)
File "/usr/local/lib/python2.7/dist-packages/gensim-3.4.0-py2.7-linux-x86_64.egg/gensim/utils.py", line 1311, in pickle
with smart_open(fname, 'wb') as fout: # 'b' for binary, needed on Windows
File "build/bdist.linux-x86_64/egg/smart_open/smart_open_lib.py", line 89, in smart_open
File "build/bdist.linux-x86_64/egg/smart_open/smart_open_lib.py", line 301, in file_smart_open
IOError: [Errno 21] Is a directory: './w2v_model/wordmodel3'
please help me to change this particular error. i think there is no folder like this, but i had already created the w2v_model/wordmodel3 in my folder. I had tried it in many ways. I will provide smart_open_lib.py program file below :
def file_smart_open(fname, mode='rb'):
"""
Stream from/to local filesystem, transparently (de)compressing gzip and bz2
files if necessary.
"""
_, ext = os.path.splitext(fname)
if ext == '.bz2':
PY2 = sys.version_info[0] == 2
if PY2:
from bz2file import BZ2File
else:
from bz2 import BZ2File
return make_closing(BZ2File)(fname, mode)
if ext == '.gz':
from gzip import GzipFile
return make_closing(GzipFile)(fname, mode)
return open(fname, mode)
this is the trace back code which they tell. kindly request to help me fr change this error!!!
The Word2Vec .save() method needs a new path, to the filename (not directory!) to which you want to save the model's main file. (For most models of significant size, there will be extra files alongside that main file, with other extensions, that are also part of the model-save.)
If you're providing a path to an existing directory, you'll get an error like this.
Change your w2v_model_path to be a path to a desired file name, not an already-existing directory. (Perhaps that path will be inside that directory. But it shouldn't be the directory itself!)

Atom `script` add-on doesn't recognize Django Model/settings when running a script

It seems I run into some dependencies issues when trying to run a python script within my Django based web application using the atom add-on script.
I would like to run the following script using the Atom script add-on:
feeder.py:
import zmq
import time
from time import sleep
import uuid
from models import AccountInformation
context = zmq.Context()
zmq_socket = context.socket(zmq.PULL)
zmq_socket.bind("tcp://*:32225")
time.sleep(1)
while True:
try:
msg = zmq_socket.recv_string()
data = msg.split("|")
print(data)
if (data[0] == "account_info"):
version = data[1]
DID = uuid.UUID(data[2])
accountNumber = int(data[3])
broker = data[4]
leverage = data[5]
account_balance = float(data[6])
account_profit = float(data[7])
account_equity = float(data[8])
account_margin = float(data[9])
account_margin_free = float(data[10])
account_margin_level = float(data[11])
account_currency = data[12]
feed = AccountInformation(
version=version,
DID=DID,
accountNumber=accountNumber,
broker=broker,
leverage=leverage,
account_balance=account_balance,
account_pofit=account_profit,
account_equity=account_equity,
account_margin=account_margin,
account_margin_free=account_margin_free,
account_margin_level=account_margin_level,
account_currency=account_currency
)
feed.save()
# Push data to account information table
else:
print("no data")
except zmq.error.Again:
print("\nResource timeout.. please try again.")
sleep(0.000001)
Unfortunately it raises the following error:
Traceback (most recent call last):
File "C:\Users\Jonas Blickle\Desktop\dashex\Dashboard_app\feeder.py", line 5, in <module>
from models import AccountInformation
File "C:\Users\Jonas Blickle\Desktop\dashex\Dashboard_app\models.py", line 7, in <module>
class AccountInformation(models.Model):
File "C:\Program Files\lib\site-packages\django\db\models\base.py", line 103, in __new__
app_config = apps.get_containing_app_config(module)
File "C:\Program Files\lib\site-packages\django\apps\registry.py", line 252, in get_containing_app_config
self.check_apps_ready()
File "C:\Program Files\lib\site-packages\django\apps\registry.py", line 134, in check_apps_ready
settings.INSTALLED_APPS
File "C:\Program Files\lib\site-packages\django\conf\__init__.py", line 79, in __getattr__
self._setup(name)
File "C:\Program Files\lib\site-packages\django\conf\__init__.py", line 60, in _setup
raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: Requested setting INSTALLED_APPS, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
[Finished in 0.302s]
When I remove the model import everything just runs fine, it just won't populate my DB then since I need the imported model...
How to possibly solve this?
Your models are inside your apps, and your apps are inside your settings (INSTALLED_APPS), so you should configure the django's settings before you can access them.
Just add these before importing your models:
import django
django.setup()
You should also set DJANGO_SETTINGS_MODULE environment varialbe to specify your settings file; or use django.configure if you prefer (docs).

Django 1.10 path is on mount 'C:', start on mount 'D:'

I wanted to add additional fields to a many-to-many relationship and I created a intermediate model called Contact ( the goal is to implement a system that allows the user to follow other users and be followed too).
class Contact(models.Model):
user_from = models.ForeignKey(User,
related_name='rel_from_set')
user_to = models.ForeignKey(User,
related_name='rel_to_set')
created = models.DateTimeField(auto_now_add=True,
db_index=True)
class Meta:
ordering = ('-created',)
def __str__(self):
return '{} follows {}'.format(self.user_from, self.user_to)
I am using the User model provided by Django (from django.contrib.auth.models) . As this model is not one I created if I want to add fields to it, I should (or at least, I think I should ) add them dinamically (with monkey-patch) . So at the end of the models.py file I added the following code:
User.add_to_class('following', models.ManyToManyField('self', through=Contact , related_name='followers', symmetrical=False))
But I runned the python manage.py makemigrations I got the following error :
Migrations for 'auth':
Traceback (most recent call last):
File "manage.py", line 22, in <module>
execute_from_command_line(sys.argv)
File "C:\Program Files (x86)\Python35-32\lib\site-packages\django\core\managem
ent\__init__.py", line 367, in execute_from_command_line
utility.execute()
File "C:\Program Files (x86)\Python35-32\lib\site-packages\django\core\managem
ent\__init__.py", line 359, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "C:\Program Files (x86)\Python35-32\lib\site-packages\django\core\managem
ent\base.py", line 294, in run_from_argv
self.execute(*args, **cmd_options)
File "C:\Program Files (x86)\Python35-32\lib\site-packages\django\core\managem
ent\base.py", line 345, in execute
output = self.handle(*args, **options)
File "C:\Program Files (x86)\Python35-32\lib\site-packages\django\core\managem
ent\commands\makemigrations.py", line 192, in handle
self.write_migration_files(changes)
File "C:\Program Files (x86)\Python35-32\lib\site-packages\django\core\managem
ent\commands\makemigrations.py", line 210, in write_migration_files
migration_string = os.path.relpath(writer.path)
File "C:\Program Files (x86)\Python35-32\lib\ntpath.py", line 574, in relpath
path_drive, start_drive))
ValueError: path is on mount 'C:', start on mount 'D:'
After a quick google search :
"os.relpath does give you a relative path between two directories.
The problem you are encountering is that, on Windows, a relative path doesn't even exist if the two directories are on different drives (which is exactly what the error message says). "
But what is the solution ?
I am using Windows 8 and Django 1.10.
You are running makemigrations from another drive (not from C: where django is installed).
There was a bug with makemigrations on Windows:
see this Django ticket,
and the commit that fixed the bug:
makemigrations crash when creating migrations on a separate drive than where Django is installed
So to fix this error you should:
move your Django project (your Python code) on C: drive
or update your Django version (to Django 1.11)

django :UnicodeDecodeError: '

I want build a blog with Python 2.7 and Django 1.7.8.
When I use Django,I keep getting an error: UnicodeDecodeError.
The relevant code is:
#coding: utf-8
from django.db import models
class Entry(models.Model):
title = models.CharField(max_length=200)
body = models.TextField()
publish = models.BooleanField(default=False)
And ./manage.py makemigrations get an error:
Migrations for 'blog':
0001_initial.py:
- Create model Entry
Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.8-py2.7.egg/django/core/management/__init__.py", line 385, in execute_from_command_line
utility.execute()
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.8-py2.7.egg/django/core/management/__init__.py", line 377, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.8-py2.7.egg/django/core/management/base.py", line 288, in run_from_argv
self.execute(*args, **options.__dict__)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.8-py2.7.egg/django/core/management/base.py", line 338, in execute
output = self.handle(*args, **options)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.8-py2.7.egg/django/core/management/commands/makemigrations.py", line 124, in handle
self.write_migration_files(changes)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.8-py2.7.egg/django/core/management/commands/makemigrations.py", line 143, in write_migration_files
migrations_directory = os.path.dirname(writer.path)
File "/usr/local/lib/python2.7/dist-packages/Django-1.7.8-py2.7.egg/django/db/migrations/writer.py", line 222, in path
return os.path.join(basedir, self.filename)
File "/usr/lib/python2.7/posixpath.py", line 80, in join
path += '/' + b
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6 in position 10: ordinal not in range(128)
I don't see what's going wrong, any idea? I already add coding:utf-8 in top of code
do you have data in the models already?
if so, i am guessing you have some bad characters in there.
do you have a unicode or str method defined on the models?
if so, i suggest using them in a try statement of sorts like this:
def __str__():
try:
return "%s" % self.title
except:
return "%s" % self.pk
when you see only the PK, you will know that your 'title' field has bad data.
extend this to include whichever fields you want to display, not just title.
it looks like it fails when joining the path?
maybe you have folder names that can't be converted to ascii?
also , consider editing the file that is having the error? maybe add a print statement just before the line that fails that shows what is trying to be joined?
edit the file mentioned below, add the print statement to see what is trying to be joined?
File "/usr/lib/python2.7/posixpath.py", line 80, in join
path += '/' + b

Django: How to allow a Suspicious File Operation / copy a file

I want to do a SuspiciousFileOperation which django disallows by default.
I am writing a command (to run via manage.py importfiles) to import a given directory structure on the real file system in my self written filestorage in Django.
I think, this is my relevant code:
def _handle_directory(self, directory_path, directory):
for root, subFolders, files in os.walk(directory_path):
for filename in files:
self.cnt_files += 1
new_file = File(directory=directory, filename=filename, file=os.path.join(root, filename),
uploader=self.uploader)
new_file.save()
The backtrace is:
Traceback (most recent call last):
File ".\manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "C:\Python27\lib\site-packages\django\core\management\__init__.py", line 399, in execute_from_command_line
utility.execute()
File "C:\Python27\lib\site-packages\django\core\management\__init__.py", line 392, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "C:\Python27\lib\site-packages\django\core\management\base.py", line 242, in run_from_argv
self.execute(*args, **options.__dict__)
File "C:\Python27\lib\site-packages\django\core\management\base.py", line 285, in execute
output = self.handle(*args, **options)
File "D:\Development\github\Palco\engine\filestorage\management\commands\importfiles.py", line 53, in handle
self._handle_directory(args[0], root)
File "D:\Development\github\Palco\engine\filestorage\management\commands\importfiles.py", line 63, in _handle_directory
new_file.save()
File "D:\Development\github\Palco\engine\filestorage\models.py", line 157, in save
self.sha512 = hashlib.sha512(self.file.read()).hexdigest()
File "C:\Python27\lib\site-packages\django\core\files\utils.py", line 16, in <lambda>
read = property(lambda self: self.file.read)
File "C:\Python27\lib\site-packages\django\db\models\fields\files.py", line 46, in _get_file
self._file = self.storage.open(self.name, 'rb')
File "C:\Python27\lib\site-packages\django\core\files\storage.py", line 33, in open
return self._open(name, mode)
File "C:\Python27\lib\site-packages\django\core\files\storage.py", line 160, in _open
return File(open(self.path(name), mode))
File "C:\Python27\lib\site-packages\django\core\files\storage.py", line 261, in path
raise SuspiciousFileOperation("Attempted access to '%s' denied." % name)
django.core.exceptions.SuspiciousFileOperation: Attempted access to 'D:\Temp\importme\readme.html' denied.
The full model can be found at GitHub. The full command is currently on gist.github.com available.
If you do not want to check the model: the attribute file of my File class is a FileField.
I assume, this problem happens, because I am just "linking" to the file found. But I need to copy it, huh? How can I copy the file into the file?
In Django, SuspiciousFileOperation can be avoid by read the file from external dir and make a tmp file within the project media then save in the appropriate file filed as below
import tempfile
file_name="file_name.pdf"
EXT_FILE_PATH = "/home/somepath/"
file_path = EXT_FILE_PATH + file_name
if exists(file_path):
#create a named temporary file within the project base , here in media
lf = tempfile.NamedTemporaryFile(dir='media')
f = open(file_path, 'rb')
lf.write(f.read())
#doc object with file FileField.
doc.file.save(file_name, File(lf), save=True)
lf.close()
I haven't faced similar problem but related issue. I have recently upgraded Django 1.8 to 1.11.
Now I am getting the following error if try to save a file in a model having FileField field:
SuspiciousFileOperation at /api/send_report/
The joined path (/vagrant/tmp/test_file.pdf) is located outside of the base path component (/vagrant/media)
My model where I want to save the file:
class Report(BaseModel):
file = models.FileField(max_length=200, upload_to=os.path.join(settings.REPORTS_URL, '%Y/week_%W/'))
type = models.CharField(max_length=20, verbose_name='Type', blank=False, default='', db_index=True)
I am trying following codes to save the file from tmp folder which is not located in MEDIA_ROOT:
from django.core.files import File
filepath = "/vagrant/tmp/test_file.pdf"
file = File(open(filepath, "rb"))
report_type = "My_report_type"
report = Report.objects.create(
file=file,
type=report_type,
)
What I have done to solve the issue:
import os
from django.core.files import File
filepath = "/vagrant/tmp/test_file.pdf"
file = File(open(filepath, "rb"))
file_name = os.path.basename(file.name)
report_type = "My_report_type"
report = Report.objects.create(
type=report_type,
)
report.file.save(file_name, file, save=True)
Hope it will help someone.
Analyzing this part of stacktrace:
File "C:\Python27\lib\site-packages\django\core\files\storage.py", line 261, in path
raise SuspiciousFileOperation("Attempted access to '%s' denied." % name)
leads to the standard Django FileSystemStorage. It expects files to be within your MEDIA_ROOT. Your files can be anywhere in the file system, therefore this problem occurs.
You should pass file-like object instead of a path to your File model. The easiest way to achieve that would be to use Django File class, which is a wrapper around python file-like objects. See File object documentation for more details.
Update:
Ok, I am suggesting here a route taken from the docs:
from django.core.files import File as FileWrapper
def _handle_directory(self, directory_path, directory):
for root, subFolders, files in os.walk(directory_path):
for filename in files:
self.cnt_files += 1
new_file = File(
directory=directory, filename=filename,
file=os.path.join(root, filename),
uploader=self.uploader)
with open(os.path.join(root, filename), 'r') as f:
file_wrapper = FileWrapper(f)
new_file = File(
directory=directory, filename=filename,
file=file_wrapper,
uploader=self.uploader)
new_file.save()
If it works it should copy the file to the location provided by your secure_storage callable.
Check if there is slash before your filepath
file_item = models.FileField(upload_to=content_file_name)
def content_file_name(username, filename):
return '/'.join(['content', username, filename])
Note here "content" not "/content". That was the problem for me.

Categories

Resources