how to use curent date in image path django - python

I'm writing my news web-site and I already have translit widget imported into my django models.py
and it's looks like
class Article(models.Model):
class Meta():
db_table = "article"
verbose_name = "Новость"
verbose_name_plural = "Новости"
def get_image_path(self, filename):
path = ''.join(["static/article/", translit.slugify(filename)])
return path
article_image1 = models.ImageField(upload_to= get_image_path, null=True, blank=True, verbose_name = "Фотография 1")
In that case all uploaded images are stored in path_to_app/static/article/some_image_name.jpg
But we have a lot of images and storing them in one folder is very problematicaly.
the problem is:
How can I save image to
path_to_app/static/article/todays_year/todays_month/todays_date/some_image_name.jpg
Thank you

Use the datetime.date.strftime() function.
from datetime import date
def get_image_path(self, filename):
path = ''.join([date.today().strftime('static/article/%Y/%m/%d/'),
translit.slugify(filename)])
return path

You can return a string from your upload_to function - in this case get_image_path, with the date-formatters in it, and Django will pass the date information to the string. (https://docs.djangoproject.com/en/1.7/ref/models/fields/#django.db.models.FileField.upload_to)

Related

Why is VSCode intellisense type hints different for these 2 Django model objects?

In the views.py after importing the Video model I am testing how intellisense works in VScode.
This is the views.py
from django.shortcuts import render
from .models import Video
# Create your views here.
video1: Video = Video.objects.get(id=1)
video2: Video = Video.objects.filter(id=1).first()
this is the models.py:
class Video(models.Model):
'''
info about videos
'''
video_id = models.TextField(blank=True, null=True)
title = models.TextField()
description = models.TextField()
tags = models.TextField()
is_uploaded = models.BooleanField()
date_uploaded = models.DateField(null=True)
filename = models.TextField()
thumbnail_filename = models.TextField()
When I start typing I get this for video1 which is from video1: Video = Video.objects.get(id=1):
As you can see it offers model fields
but for video2 which is from video2: Video = Video.objects.filter(id=1).first():
it doesn't offer model fields.
Why is that and how can we fix it?
The first one knows that it is getting a single model instance as it is guaranteed by the QuerySet. I think the second one is not guaranteed to return a model instance.
In the django source code for this:
def first(self):
"""Return the first object of a query or None if no match is found."""
for obj in (self if self.ordered else self.order_by('pk'))[:1]:
return obj
so it is returning Optional[<instance>] whereas get() returns an instance.
Interestingly, earliest may work for your usecase, and it is guaranteed to return a model instance as it subcalls get.

How to create folders in django admin?

Currently, I want to create a folder whenever I try to add a new tag in Django admin. But I don't know how to realize this function. my model.py code is as below:
class Tags(models.Model):
Tag_name = models.CharField('Tag Name', max_length=10, default='NA')
Description = models.TextField('Tag Description', max_length=100, blank=True)
class Meta:
verbose_name = 'Tags'
verbose_name_plural = verbose_name
def __str__(self):
return self.Tag_name
The function I want is, for example, if I create a tag named "test", the system will automatically create a folder named "test" in a specific place.
You can use signals, in your model.py
from django.db.models.signals import post_save
def callback(*args, **kwargs):
instance = kwargs.get('instance')
# Do after save
post_save.connect(callback, sender=Tags)

Django admin: How to get path of uploaded file

I have created model field for User Pic and User_pic_url, what i'm trying to do is when i upload image it's path should get populated in user_pic_url.
Note that i'm uploading image from django admin itself. any idea.
snapshot for ref:
Snapshot
Model.py:
class Main(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=100)
about = models.TextField()
contact = models.CharField(default='0', max_length=12)
email = models.CharField(default='-', max_length=50)
linkedin = models.CharField(default='-', max_length=50)
github = models.CharField(default='-', max_length=50)
site_name = models.CharField(default='-', max_length=50)
resume = models.FileField()
cover_letter = models.FileField()
user_pic = models.ImageField()
user_pic_url = models.TextField(default="-")
From Django documentation regarding managing files
Consider the following model, using an ImageField to store a photo:
class Car(models.Model):
name = models.CharField(max_length=255)
price = models.DecimalField(max_digits=5, decimal_places=2)
photo = models.ImageField(upload_to='cars')
Any Car instance will have a photo attribute that you can use to get
at the details of the attached photo:
car = Car.objects.get(name="57 Chevy")
car.photo
<ImageFieldFile: cars/chevy.jpg>
car.photo.name
'cars/chevy.jpg'
car.photo.path
'/media/cars/chevy.jpg'
car.photo.url
'http://media.example.com/cars/chevy.jpg'
if you want to get the uploaded path first make sure you have configure you MEDIA_URL MEDIA_ROOT in settings.py and also you have to put your put url patterns for media url given in the documentation
if you have already done that you have to simply put the query set
obj = Main.objects.all().first()
like this when you get any object you have to go to the imagefield and add url after that like this
you have to only put url after all the configuration in the imagefield
print(obj.user_pic.url) <---------you can get your url like this
You don't need a user_pic_url field. You can fetch the data from the user_pic field itself
class Main(models.Model):
# rest of your fields
user_pic = models.ImageField()
#property
def user_pic_url(self):
return self.user_pic.url
Now, you can access the URL directly as,
model_instance = Main.objects.first()
print(model_instance.user_pic_url)

upload_to dynamically generated url to callable

I've seen a lot of post about this problem without really understanding how to solve it.
I have this model:
class Project(TimeStampedModel):
name = models.TextField(max_length=100, default='no name')
logo = models.ImageField()
I'd like to have my image saved to media root following this template:
<name>/logo/<filename>
At first glance, I would like to do:
logo = models.ImageField(upload_to="{}/logo/".format(name))
But it raises this error: AttributeError: 'TextField' object has no attribute 'model'
Using a callable would be fine, partially though:
def upload_to_project(self, filename):
url = ("%s/%s") % (self.name, filename)
return url
and using:
logo = models.ImageField(upload_to=upload_to_project)
at least I have: <name>/<filename>
But how to pass the argument in this case? I'd like to reuse my function to upload in other subfolders, not only logo as:
<name>/logo/<filename>
<name>/history/<filename>
<name>/whatever/<filename>
Any idea on what I could do?
It looks like (re-reading your post it's not 100% clear) what you want is a partial application. Good news, it's part of Python's stdlib:
import os
from functools import partial
def generic_upload_to(instance, filename, folder):
return os.path.join(instance.name, folder, filename)
class Project(TimeStampedModel):
name = models.TextField(max_length=100, default='no name')
logo = models.ImageField(
upload_to=partial(generic_upload_to, folder="logo")
)
Note that this implementation assumes instance has a name attribute... if the instance attribute you want to use as first part has to be configurable too you can rewrite your upload_to as:
def generic_upload_to(instance, filename, folder, attrname):
return os.path.join(getattr(instance, attrname), folder, filename)
then use it as
class Project(TimeStampedModel):
name = models.TextField(max_length=100, default='no name')
logo = models.ImageField(
upload_to=partial(generic_upload_to, attrname="name", folder="logo")
)
And if you have more than one FileField or ImageField in your model and don't want to repeat the attrname part:
class Something(TimeStampedModel):
my_upload_to = partial(generic_upload_to, attrname="label")
label = models.CharField(max_length=100, default='no label')
logo = models.ImageField(
upload_to=partial(my_upload_to, folder="logo")
)
attachment = models.FileField(
upload_to=partial(my_upload_to, folder="attachment")
)

Is there an order in which models are generated into database?

In my project I need to change the location where files are being uploaded. This is done using a FileSystemStorage. The path were the files are uploaded should be easy to configure, for example using the Django Admin.
from django.core.files.storage import FileSystemStorage
from django.db import models
class Setting(models.Model):
entry = models.CharField(primary_key=True, db_column="entry", max_length=50)
value = models.CharField(db_column="value", max_length=250, blank=True, null=True)
def __unicode__(self):
return "%s" %(self.entry)
class Meta:
db_table = 'settings'
verbose_name = 'Setting'
verbose_name_plural = 'Settings'
fs = FileSystemStorage(location=Setting.objects.get(entry__exact='upload_path').value)
def generate_filename(instance, filename):
...
class FileImport(models.Model):
data_file = models.FileField(_('Data file'), upload_to=generate_filename, storage=fs)
I receive this error:
django.db.utils.DatabaseError:
relation "settings" does not exist
LINE 1: ...ELECT "settings"."entry", "settings"."value" FROM "settings"...
for the line where FileSystemStorage is being created. Is there a way of telling Django to create table settings(for Setting objects) first and then fill this table with some fixtures?
That won't solve your problem, since the Settings table still won't be populated. Move it into a class attribute that gets initialized the first time it's instantiated.

Categories