JsonResponse
need to set parameter safe=True in case of returning non object data
def get_users(request):
users = User.objects.all().values('first_name', 'last_name') # or simply .values() to get all fields
users_list = list(users) # important: convert the QuerySet to a list object
return JsonResponse(users_list, safe=False)
Call Celery task
important: call celery task need to use delay() function
views.py
from myapp.tasks import prepare_and_submit_data
def register(request):
form = SignupForm(request.POST or None)
if form.is_valid():
# Async function.
prepare_and_submit_data.delay(form.cleaned_data)
return render(request, 'success.html', {})
return render(request, 'signup.html', {'form': form})
tasks.py
from celery.decorators import task
@task
def prepare_and_submit_data(data):
# do some external API requests and modify data
data = requests.post(BASE_URL, data=data).json()
# ...
Picture manipulation
Use Pillow
from PIL import Image
im = Image.open("sweet_pic.ppm")
im.save("sweet_pic.jpg")
Use os to handle files
Extracting extension from filename from Python
os.path.splittext() # return a 2-tuple
os.path.exists() # File/Folder exists
os.path.dirname() # Folder name
os.path.basename() # filename without Folder
os.path.join() # join folder
os.listdir() # iterate over the folder
files = [i for i in os.listdir("Path/to/directory/storing/emails") if i.endswith("txt")]
delete folder with files
import shutil
shutil.rmtree('/folder_name')
import os
filename, file_extension = os.path.splitext('/path/to/somefile.ext')
#filename
'/path/to/somefile'
#file_extension
'.ext'
several Exceptions together
except (IDontLikeYouException, YouAreBeingMeanException) as e:
print(e)
Iterate number in for loop of a template
Django provides it. You can use either:
{{ forloop.counter }} index starts at 1.
{{ forloop.counter0 }} index starts at 0.
In template, you can do:
{% for item in item_list %}
{{ forloop.counter }} # starting index 1
{{ forloop.counter0 }} # starting index 0
# do your stuff
{% endfor %}
extract a page from a pdf as a jpeg
The pdf2image library can be used.
You can install it simply using,
pip install pdf2image
Once installed you can use following code to get images.
from pdf2image import convert_from_path
pages = convert_from_path('pdf_file', 500)
Saving pages in jpeg format
for page in pages:
page.save('out.jpg', 'JPEG')
Need to poppler to be installed beforehand. Path to poppler bin folder can be specified in convert_from_path function
Pass variable from save to post_save signal
use getattr()
You can:
Define and send your own signals.
Store additional info in model instance. Like this
def save(self, commit=True):
user = super(CustomFormThing, self).save(commit=False)
#set some other attrs on user here ...
user._some = 'some'
user._other = 'other'
if commit:
user.save()
return user
@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
some_id = getattr(instance, '_some', None)
other_id = getattr(instance, '_other', None)
if created:
#do something with the kwargs above...
Or to check if something is changed in object
def init(self, args, **kwargs):
super(YOURMODEL, self)._init(args, **kwargs)
# SAVE THE INITIAL VALUE
self.__original_value = self.value_you_want_to_track
def save(self, *args, **kwargs):
# Compare the initial value with the current value
if self.__original_value != self.value_you_want_to_track:
# DO SOMETHING, MAYBE TRIGGER SIGNAL
super(YOUR_MODEL, self).save(*args, **kwargs)
# Finally update the initial value after the save complete
self.__original_value = self.value_you_want_to_track
Validate file type
You can create a custom validator
def validate_file_extension(value):
import os
from django.core.exceptions import ValidationError
ext = os.path.splitext(value.name)[1]
valid_extensions = ['.xml']
if not ext.lower() in valid_extensions:
raise ValidationError(u'Unsupported file extension.')
Then in your form field
coupling_file = forms.FileField(label=’XML File Upload:’,required=True, validators=[validate_file_extension])
Use MD5 to discard uploaded duplicates
import hashlib
import os
from django.core.files.storage import FileSystemStorage
from django.db import models
class MediaFileSystemStorage(FileSystemStorage):
def get_available_name(self, name, max_length=None):
if max_length and len(name) > max_length:
raise(Exception("name's length is greater than max_length"))
return name
def _save(self, name, content):
if self.exists(name):
# if the file exists, do not call the superclasses _save method
return name
# if the file is new, DO call it
return super(MediaFileSystemStorage, self)._save(name, content)
def media_file_name(instance, filename):
h = instance.md5sum
basename, ext = os.path.splitext(filename)
return os.path.join('mediafiles', h[0:1], h[1:2], h + ext.lower())
class Media(models.Model):
# use the custom storage class fo the FileField
orig_file = models.FileField(
upload_to=media_file_name, storage=MediaFileSystemStorage())
md5sum = models.CharField(max_length=36)
# ...
def save(self, *args, **kwargs):
if not self.pk: # file is new
md5 = hashlib.md5()
for chunk in self.orig_file.chunks():
md5.update(chunk)
self.md5sum = md5.hexdigest()
super(Media, self).save(*args, **kwargs)
Use annotate in queryset to add new aggregate/summary field
Add two field in queryset
User.objects.filter(
username_startswith=”ab”).annotate(
posts=Count(‘post’, distinct=True)).annotate(
topics=Count(‘topic’, distinct=True)).values_list(
“username”,”posts”, “topics”)
Add new field in admin The following code worked perfectly. The overridden init and clean methods on the ModelForm adds the dynamic fields and defines how the values should be saved. The overridden get_form and get_fieldsets together with the fieldsets attribute on the AdminModel make sure the dynamic form fields get displayed in the admin.
def queryset(self):
qs = super(MandantAdmin, self).queryset()
qs = qs.annotate(students=Count(‘usermandantrelation’, distinct=True)).annotate(courses=Count(‘mandantcourse’, distinct=True))
return qs
def coursesnumber(self, instance):
counts = MandantCourse.objects.filter(mandant=instance).all().count()
url = reverse(‘xadmin:operation_mandantcourse_changelist’)
return_url = ‘{3}‘.format(url, str(instance.id), str(instance.id), str(counts)) # return link in list field
return return_url
courses_number.short_description = (‘Anzahl der Schulungen’)
courses_number.allow_tags = True
courses_number.admin_order_field = ‘courses’
How to create and save dynamic fields in Django Admin
class PersonAdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(PersonAdminForm, self).__init__(*args, **kwargs)
new_fields = {}
initial = self.instance.groups.all()
for group_type in GroupType.objects.all():
field_name = '{0}_groups'.format(group_type.name.lower())
qs = Group.objects.filter(group_type=group_type)
field = forms.ModelMultipleChoiceField(
queryset=qs,
required=False,
initial=initial,
)
new_fields[field_name] = field
self.fields.update(new_fields)
def clean(self):
cleaned_data = super(PersonAdminForm, self).clean()
groups = []
for group_type in GroupType.objects.all():
gt_name = '{0}_groups'.format(group_type.name.lower())
groups.extend(cleaned_data.get(gt_name))
self.instance.groups.clear()
self.instance.groups.add(*groups)
return cleaned_data
class Meta:
model = Person
fields = '__all__'
@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
form = PersonAdminForm
# using the fieldsets attribute instead of fields in order to dynamically
# add group type fields later.
fieldsets = (
(None, {
'fields': (
'name',
),
}),
)
def get_form(self, request, obj=None, **kwargs):
kwargs['fields'] = flatten_fieldsets(self.declared_fieldsets)
return super(PersonAdmin, self).get_form(request, obj, **kwargs)
def get_fieldsets(self, request, obj=None):
fieldsets = super(PersonAdmin, self).get_fieldsets(request, obj)
newfieldsets = list(fieldsets)
fields = []
for group_type in GroupType.objects.all():
fields.append('{0}_groups'.format(group_type.name.lower()))
newfieldsets.append(['Groups', {'fields': fields}])
return newfieldsets