Django (Models): how to get instance from foreign key - python

i'm new to django and sqlite. Is that possible i can get the instance.name value from its foreign key that is related to modeldb? I need to save my pdf file under the same directory as the modeldb class. From the above experiment, im got nothing with modelDB.instance / modelDB.instance.name.

move that upload function outside the class.
instance refer as the your class instance. So you can do like this
instance.modelDB.name
citatiions = models.FileField(...., upload_to=upload) #pass your function name here
check this answerlink

You could do,
def upload(instance, file_name):
return "documents/" + instance.ModelDB.name + "/pdf/" + filename

Related

Django Models Filefiled save according to query ID/pk

I am new to django and sqlite. From the code below i will upload my file to 'documents', since there is an overwrite storage function, if i upload the same file name with another query i will overwrite the old one which i dont wan it to be happend. So what I am thinking is to get the query id or pk as the directory.Its there anyway to store my upload file via their pk or id?
eg. document/name/test.zip
eg. document/name/test.zip
First define a function
def upload(instance, filename):
return "document/" + instance.user.name +"/" + filename
And in the filefield of model
upload_to=upload

Use model attribute as field parameter

I'm trying to create a folder and upload an image to in it. My model is similar to this:
class XYZ(models.Model):
def code(self):
syms = ['#','#','$','%','&','*','+','-']
return ''.join(x+random.choice(syms) for x in [self.name[-2:],self.name[2:]])
def make_folder(self):
os.mkdir(os.getcwd()+'/XYZ/'+folder)
def save(self):
self.make_folder()
super(XYZ,self).save(*args,**kwargs)
name = models.CharField(max_length=20)
folder = property(code)
image = models.ImageField(upload_to='HELP_HERE')
I've tried using folder, self.folder, property(code) but it says it isn't defined, how do I access this attribute? Is this the correct approach?
I've also set in the configs.py my MEDIA_URL and MEDIA_ROOT
I think a more simple and understandable way to do this would be to avoid using the inner class function and doing something like this:
# Reference this function outside of your model class.
def xyz_directory_path(instance, filename):
# file will be uploaded to MEDIA_ROOT/xyz_<id>/<filename>
return 'xyz_{0}/{1}'.format(instance.id, filename)
Then, on your models, reference the function in your upload_to field like so:
class XYZ(models.Model):
image = models.ImageField(upload_to=xyz_directory_path)
With your media config set up, this should work. There's a really nice and simple explanation about file handling here.

Python 2.7 unbound method with Django 1.7 migrations

I am upgrading to Django 1.7.4 and use the new built-in migrations, but I get the following error when attempting to run makemigrations:
ValueError: Could not find function upload_callback in app_utils.
Please note that due to Python 2 limitations, you cannot serialize unbound
method functions (e.g. a method declared and used in the same class body).
Please move the function into the main module body to use migrations.For more information,
see https://docs.djangoproject.com/en/1.7/topics/migrations/#serializing-values
My model definition:
class Discount(models.Model):
banner = models.ImageField(
help_text=_("Banner image for this discount"),
upload_to=upload_to('discounts/', 'title'),
blank=True,
null=True
)
And my upload callback in app_utils.py:
def upload_to(path, attribute=None):
def upload_callback(instance, filename):
compact = filename[:50]
try:
attr= unicode( slugify( getattr(instance, attribute) ) )
mypath = '%s/%s/%s' % (path, attr, compact)
except:
mypath = '%s%s' % (path, compact)
return mypath
return upload_callback
Based on the error message, it indicates upload_callback is unbound. So
I tried pulling upload_callback outside of the the wrapper function, but cannot find a way to pass in the extra path and attribute parameters passed into upload_to. Django's documentation is unclear how to do this, and it only specifies that instance and filename are required.
Ideally, what I would like is:
def upload_to(instance, filename, path, attribute=None):
...
Any ideas how I can go about achieving this?
After some serious deep digging on the web, I came across this Django bug report. The solution seems to create a callable factory class:
https://code.djangoproject.com/ticket/22999
More discussion here: Django - Cannot create migrations for ImageField with dynamic upload_to value

Generating URL using Autofield before model is saved

I'd like for my image urls to be /img/1 and /img/2, and I thought using the auto incremented id assigned to every model would be perfect for this, so that every url would be different. The problem is that an instance of a model does not have an id before it is saved. This is an issue in the code below from models.py:
def update_filename(instance, filename):
a = type(instance.id)
if a is not int:
a = 1
else:
a = instance.id
path = "img" + "/" + str(a) + ".jpg"
return path
class User_Image(models.Model):
image = models.ImageField(upload_to=update_filename)
Any suggestions on how to fix this? The id of every instance when django saves the pic is None, so every image saves into my img directory as "None" or "None_1" and so on.
You can't. From the documentation:
In most cases, this object will not have been saved to the database
yet, so if it uses the default AutoField, it might not yet have a
value for its primary key field.
I use function like this:
import uuid
def update_filename(instance, filename):
""" Rename picture """
extension = os.path.splitext(filename)[1]
return 'img/%s%s' % (uuid.uuid4(), extension)

Django, Python, trying to change field values / attributes in object retrieved from DB objects.all call, not working

I'm trying to change a specific field from a field in an object that I retrieved from a django db call.
class Dbobject ()
def __init__(self):
dbobject = Modelname.objects.all()
def test (self):
self.dbobject[0].fieldname = 'some new value'
then I am able to access a specific attribute like so:
objclass = Dbobject()
fieldvalue = dbobject.dbobject[0].fieldname
but I want to be able to use the "test" method of the Dbobject class to try to change the specific value on an object's attribute value, but it isn't changing it. I am stumped by this as this is how I thought I am supposed to change an object's attribute value.
I'm not sure if this is the problem or not, but I think you might be missing a save() method.
from models import Person
p = Person.objects.get(pk=100)
p.name = 'Rico'
p.save() # <== This writes it to the db. Is this what you're missing?
Above is the simple case. Adapted for what you wrote above, it'd be like:
dbobject.dbobject[0].fieldname = 'some new value'
dbobject.dbobject[0].save()
or, I'd write it more like:
rec = dbobject.dbobject[0]
rec.fieldname = 'some new value'
rec.save()
Also note that depending on whether and how you are using transactions, you may or may not see a change to the database until you commit.
I am not totally sure what you are trying to achieve, but shouldn't it be something like:
class Dbobject ():
def __init__(self):
self.dbobject = Modelname.objects.all()
def test (self):
self.dbobject[0].fieldname = 'some new value'

Categories