Django

155 Notes
+ ORM - Update a filed value (Dec. 4, 2023, 11:33 a.m.)

from django.db.models import F, Value from django.db.models.functions import Concat TemplateType.objects.filter(uuid=self.kwargs.get('uuid')).update( deleted=True, name=Concat(F('name'), Value('-DELETED-'), F('id')) )

+ Test ajax views (Sept. 19, 2023, 3:52 p.m.)

response = self.client.post( reverse('view_name', args=(obj.id,)), **{'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'} )

+ Save Image overwriting the previous name (May 14, 2023, 1:43 p.m.)

from django.core.files.storage import FileSystemStorage class OverwriteStorage(FileSystemStorage): def get_available_name(self, name, max_length=None): self.delete(name) return name def upload_to(instance, filename): return 'avatars/{filename}.jpg'.format(filename=instance.id) class Account(AbstractUser): avatar = models.ImageField( blank=True, null=True, upload_to=upload_to, storage=OverwriteStorage() )

+ Access migration model (March 9, 2023, 3:55 p.m.)

from django.db.migrations.recorder import MigrationRecorder MigrationRecorder.Migration.objects.values_list('id', 'app', 'name')

+ Find Postgres version from Django (Nov. 19, 2022, 11:47 p.m.)

from django.db import connection print(connection.cursor().connection.server_version)

+ Coding style - Imports (Nov. 3, 2022, 9:32 p.m.)

# future from __future__ import unicode_literals # standard library import json from itertools import chain # third-party import bcrypt # Django from django.http import Http404 from django.http.response import ( Http404, HttpResponse, HttpResponseNotAllowed, StreamingHttpResponse, cookie, ) # local Django from .models import LogEntry # try/except try: import yaml except ImportError: yaml = None CONSTANT = 'foo' class Example: # ...

+ Logging (Aug. 18, 2022, 3:19 p.m.)

from logging import getLogger LOG = getLogger(__name__) LOG.debug('message')

+ Current directory - dirname vs abspath (June 18, 2022, 12:57 a.m.)

This returns the current folder that the scripts exists in: os.path.abspath(os.path.dirname(os.path.abspath(__file__))) OR os.path.dirname(__file__) # /home/mohsen/my project ------------------------------------------------------------------------------------------------------ This returns the parent folder that the scripts exists in: os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # /home/mohsen ------------------------------------------------------------------------------------------------------

+ Transaction Atomic (June 4, 2022, 10:40 p.m.)

https://seddonym.me/2020/11/19/trouble-atomic/ By default, each Django ORM query is automatically committed to the database. Sometimes, however, we need to group multiple operations, so that they happen either altogether, or not at all. The property of queries grouped indivisibly like this is known as atomicity. from django.db import transaction def transfer(source: Account, destination: Account, amount: int) -> None: with transaction.atomic(): BalanceLine.objects.create( account=source, amount=-amount, ) BalanceLine.objects.create( account=destination, amount=amount, ) Because we’ve wrapped the queries in transaction.atomic, we know that whatever happens, the two balance lines will either both make it into the database together or not at all. This is a very good thing because if only the first balance line was written, the books wouldn’t balance. -------------------------------------------------------------------------------------------------------------- How does it work? Under the hood, Django begins a database transaction when transaction.atomic is entered and does not commit it until the context exits without an exception being raised. If for some reason, the second ORM operation does raise an exception, the database will roll back the transaction. Corrupt data is avoided. We call this operation ‘atomic’ because, like an atom, it’s indivisible. task_billing_checks_periodic -------------------------------------------------------------------------------------------------------------- Nested atomic blocks: transaction.atomic also supports nesting: with transaction.atomic(): ... ... with transaction.atomic(): ... with transaction.atomic(): ... ... with transaction.atomic(): ... ... The details of how these works are a little harder to wrap one’s head around. In many database engines, such as PostgreSQL, there’s no such thing as a nested transaction. So instead Django implements this using a single outer transaction, and then a series of database savepoints: with transaction.atomic(): # Begin transaction ... ... with transaction.atomic(): # Savepoint 1 ... with transaction.atomic(): # Savepoint 2 ... ... with transaction.atomic(): # Savepoint 3 ... ... ... # Transaction will now be committed. All the inner atomic blocks behave slightly differently from the outer ones: in the event of an exception, rather than rolling back the whole transaction, it rolls back to the savepoint set when it entered the context manager. The crucial thing to realize here is that the transaction is only committed when we exit the outer block. This means that any database operations executed in inner blocks are still subject to rollback. --------------------------------------------------------------------------------------------------------------

+ List SQL statements (June 1, 2022, 1:09 p.m.)

from django.db import connections connection.queries ----------------------------------------------------------------- from django.db import reset_queries reset_queries() -----------------------------------------------------------------

+ Get model field names (March 14, 2022, 12:16 p.m.)

Student._meta.get_all_field_names()

+ Dump Data (Feb. 6, 2022, 9:42 a.m.)

python manage.py dumpdata personnel.EducationDegree > personnel/fixtures/education_degrees.json --indent=2 python manage.py loaddata personnel/fixtures/education_degrees.json

+ PyCharm - Connect to PostgreSQL database without password (Jan. 11, 2022, 12:51 p.m.)

Set to "trust" in the file pg_hba.conf: host all all 127.0.0.1/32 trust or set it to trust for only a database user: host all mohsen 127.0.0.1/32 trust

+ PostgreSQL error: fe_sendauth: no password supplied (Dec. 20, 2021, 1:20 p.m.)

Add the following line in the file /etc/postgresql/11/main/pg_hba.conf: # TYPE DATABASE USER ADDRESS METHOD local all <the_username> trust <the_username> should be the database username for your project

+ Abstract Model (April 6, 2021, 11:53 p.m.)

Abstract models are models that have no reflection in the database and can’t be instantiated. You should use abstract models if you want to share logic between models.

+ File Size Format (Jan. 20, 2021, 12:59 p.m.)

from django.template.defaultfilters import filesizeformat filesizeformat(6347255300096)

+ Benefits of uWSGI (Sept. 18, 2020, 7:44 p.m.)

- It's almost entirely configurable through environment variables (which fits well with containers) -It includes native HTTP support, which can circumvent the need for a separate HTTP server like Apache or Nginx.

+ Generate Secret Key (Aug. 26, 2020, 9:20 a.m.)

from django.core.management.utils import get_random_secret_key print(get_random_secret_key())

+ Translation (Aug. 11, 2020, 9:02 a.m.)

Contextual markers: from django.utils.translation import pgettext month = pgettext("month name", "May") or: from django.db import models from django.utils.translation import pgettext_lazy class MyThing(models.Model): name = models.CharField(help_text=pgettext_lazy( 'help text for MyThing model', 'This is the help text')) ------------------------------------------------------------------------------------------ from django.utils.translation import gettext_lazy as _ from django.utils.text import format_lazy success_message = format_lazy( _('The {item} was updated successfully.'), item=_('bank') ) ------------------------------------------------------------------------------------------

+ The paths in settings.py (Aug. 10, 2020, 2:30 p.m.)

Django >= 3.1 import sys from pathlib import Path BASE_DIR = Path(__file__).resolve(strict=True).parent.parent sys.path.append(str(BASE_DIR / 'apps')) LOCALE_PATHS = list(Path.cwd().rglob('locale')) MEDIA_ROOT = BASE_DIR / 'tiptong' / 'media' MEDIA_URL = '/media/' STATIC_ROOT = BASE_DIR / 'tiptong' / 'static' STATIC_URL = '/static/' DATABASES = { "default": { "ENGINE": "django.db.backends.sqlite3", "NAME": str(BASE_DIR / "db.sqlite3"), } } Example usage in views.py: from django.conf import settings json_path = settings.STATIC_ROOT / 'my_app/json/data.json' ---------------------------------------------------------------------------- Django <= 3.0 import os import sys import glob BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, os.path.join(BASE_DIR, 'apps')) LOCALE_PATHS = [ *glob.glob(BASE_DIR + '/*/*/locale', recursive=False) ] MEDIA_ROOT = os.path.join(BASE_DIR, 'tiptong', 'media') MEDIA_URL = '/media/' STATIC_ROOT = os.path.join(BASE_DIR, 'tiptong', 'static') STATIC_URL = '/static/' DATABASES = { "default": { "ENGINE": "django.db.backends.sqlite3", "NAME": os.path.join(BASE_DIR, 'db.sqlite3'), } } ----------------------------------------------------------------------------

+ Distinct on old database backends (Aug. 7, 2020, 9:17 p.m.)

agent_numbers = polls.order_by('agent_number').values_list('agent_number', flat=True).distinct()

+ OPTIONS vs HEAD in API (July 28, 2020, 8:36 p.m.)

OPTIONS method returns info about API (methods/content type) HEAD method returns info about resource (version/length/type) Server response OPTIONS HTTP/1.1 200 OK Allow: GET,HEAD,POST,OPTIONS,TRACE Content-Type: text/html; charset=UTF-8 Date: Wed, 08 May 2013 10:24:43 GMT Content-Length: 0 HEAD HTTP/1.1 200 OK Accept-Ranges: bytes Content-Type: text/html; charset=UTF-8 Date: Wed, 08 May 2013 10:12:29 GMT ETag: "780602-4f6-4db31b2978ec0" Last-Modified: Thu, 25 Apr 2013 16:13:23 GMT Content-Length: 1270

+ iterator (July 26, 2020, 2:04 p.m.)

Returns an iterator over the query results. A QuerySet typically caches its results internally so that repeated evaluations do not result in additional queries. In contrast, iterator() will read results directly, without doing any caching at the QuerySet level (internally, the default iterator calls iterator() and caches the return value). For a QuerySet which returns a large number of objects that you only need to access once, this can result in better performance and a significant reduction in memory. Note that using iterator() on a QuerySet which has already been evaluated will force it to evaluate again, repeating the query. Also, use of iterator() causes previous prefetch_related() calls to be ignored since these two optimizations do not make sense together. Depending on the database backend, query results will either be loaded all at once or streamed from the database using server-side cursors.

+ Hash passwords (July 16, 2020, 11:24 a.m.)

For bulk create you might need to set passwords like this: from django.contrib.auth.hashers import make_password password=make_password('A Password!')

+ Running Tests (July 15, 2020, 9:21 p.m.)

python manage.py test api.v1.books.tests.books

+ Measuring elapsed time (June 10, 2020, 9:16 a.m.)

from datetime import datetime from django.utils.translation import gettext_lazy as _ from django.utils.timezone import make_aware, get_current_timezone def get_elapsed_time(from_date_time_obj, short_version: bool) -> str: now = make_aware(datetime.now(), get_current_timezone()) diff_time = now - from_date_time_obj elapsed_days, elapsed_seconds = diff_time.days, diff_time.seconds hours = int(elapsed_seconds / 3600) minutes = int(elapsed_seconds % 3600 / 60) seconds = int((elapsed_seconds % 3600) % 60) # Short version if short_version: if elapsed_days: return_value = '{:d} {}'.format(elapsed_days, _('days')) elif hours: return_value = '{:d} {}'.format(hours, _('hours')) elif minutes: return_value = '{:d} {}'.format(hours, _('minutes')) elif seconds: return_value = '{:d} {}'.format(hours, _('seconds')) else: return_value = '' return '{} {}'.format(return_value, _('earlier')) # Long version # Seconds (We always have some "seconds" to display to the user) duration_string = '{:02d} {} '.format(seconds, _('seconds')) # Minutes if minutes: duration_string = '{:02d} {} {} '.format( minutes, _('minutes'), _('and') ) + duration_string # Hours if hours: duration_string = '{:02d} {} {} '.format( hours, _('hours'), _('and') ) + duration_string # Days if elapsed_days: duration_string = '{:02d} {} {} '.format( elapsed_days, _('days'), _('and') ) + duration_string return '{} {}'.format(duration_string, _('earlier'))

+ Send Errors to Email (June 9, 2020, 8:37 a.m.)

1- settings.py: ERRORS_SUBJECT = 'TipTong API' ERRORS_FROM_EMAIL = 'devops@tiptong.ir' ERRORS_RECIPIENTS = ['mohsen@mohsenhassani.com'] 2- from django.core.mail import send_mail from django.conf import settings try: something_risky_code() except Exception as e: send_mail( settings.ERRORS_SUBJECT, str(e), settings.ERRORS_FROM_EMAIL, settings.ERRORS_RECIPIENTS )

+ Models - FileField upload_to (June 8, 2020, 10:07 p.m.)

import uuid def upload_to(instance, filename): return 'announcements/{}.wav'.format(uuid.uuid4()) class Announcement(models.Model): voice = models.FileField(_('voice'), upload_to=upload_to)

+ Queryset - Filter on ManyToMany count (May 17, 2020, 11:13 a.m.)

questions = Question.objects.annotate(num_answers=Count('answers')) \ .filter(num_answers__gt=4, deleted=False, image__gt='' ).order_by('translated_at')

+ CBV - CheckboxSelectMultiple (May 16, 2020, 1:01 p.m.)

from django.forms.models import modelform_factory class ModelFormWidgetMixin: def get_form_class(self): return modelform_factory( self.model, fields=self.fields, widgets=self.widgets ) ----------------------------------------------------------------------- class ProductCreate(ModelFormWidgetMixin, CreateView): model = Product fields = [ 'name', 'image', 'units', 'default_unit', 'extra_info', 'is_enabled' ] template_name = 'manager/occupations/products-create.html' widgets = { 'units': forms.CheckboxSelectMultiple, 'extra_info': forms.CheckboxSelectMultiple } -----------------------------------------------------------------------

+ Template - Get form field ID (May 16, 2020, 10:25 a.m.)

{{ field.auto_id }} {{ field.id_for_label }} {{ field.html_name }}

+ Signals (May 16, 2020, 8:41 a.m.)

from django.db.models.signals import post_save from django.dispatch import receiver class Occupation(models.Model): pass @receiver(post_save, sender=Occupation) def create_tag(sender, instance, created, **kwargs): """Create a tag for new occupation. Update the name if already created.""" if created: Tag.objects.create( name=instance.name, content_type=ContentType.objects.get_for_model(instance), object_id=instance.pk ) else: Tag.objects.filter( content_type=ContentType.objects.get_for_model(instance), object_id=instance.pk ).update( name=instance.name )

+ GenericForeignKey (May 13, 2020, 4:10 p.m.)

from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType class Tag(models.Model): content_type = models.ForeignKey( ContentType, on_delete=models.SET_NULL, blank=True, null=True ) object_id = models.CharField(max_length=50, blank=True, null=True) content_object = GenericForeignKey('content_type', 'object_id') ------------------------------------------------------------------------------ from django.contrib.contenttypes.models import ContentType Tag.objects.create( name=instance.name, content_type=ContentType.objects.get_for_model(instance), object_id=instance.pk ) ------------------------------------------------------------------------------ Tag.objects.get( content_type=ContentType.objects.get_for_model(instance), object_id=instance.pk ).delete() ------------------------------------------------------------------------------

+ Class-Based Views (CBV) (May 11, 2020, 10:54 a.m.)

https://ccbv.co.uk/projects/Django/3.0/django.views.generic.base/View/

+ CBV - SuccessMessageMixin (May 11, 2020, 10:40 a.m.)

from django.contrib.messages.views import SuccessMessageMixin from django.utils.text import format_lazy class CategoryCreateView(SuccessMessageMixin, CreateView): model = Category fields = ['name'] success_message = format_lazy( _('The {item} was created successfully.'), item=_('category') )

+ CBV - Set asterisk for required fields (May 11, 2020, 10:39 a.m.)

class CategoryCreateView(CreateView, ListView): def get_form(self, form_class=None): form = super().get_form(form_class) form.required_css_class = 'required' return form

+ CBV - Delete old image on form save (May 10, 2020, 4:03 p.m.)

def form_valid(self, form): data = form.cleaned_data config = Config.objects.get(pk=1) if config.occupations_default_image != data['occupations_default_image']: config.occupations_default_image.delete() if config.products_default_image != data['products_default_image']: config.products_default_image.delete() return super().form_valid(form)

+ DRF - Save a list of object PKs (May 9, 2020, 10:06 a.m.)

class TimetableWriteSerializer(serializers.ModelSerializer): timetables = serializers.PrimaryKeyRelatedField( many=True, queryset=Timetable.objects.filter(enable=True) ) class Meta: model = ExpertProfile fields = ['timetables']

+ Run django code in separate file (May 9, 2020, 8:09 a.m.)

Add these two lines at the top of the file: import os import django os.environ['DJANGO_SETTINGS_MODULE'] = 'ranking.settings' django.setup() -------------------------------------------------------------------------------------------- The top solution fixes the following exception: django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet. --------------------------------------------------------------------------------------------

+ Models - limit_choices_to (May 8, 2020, 6:23 p.m.)

report_permissions = models.ManyToManyField( Permission, verbose_name=_('report permissions'), limit_choices_to={'category': '1'} ) ------------------------------------------------------------------ taff_member = models.ForeignKey( User, on_delete=models.CASCADE, limit_choices_to={'is_staff': True}, ) ------------------------------------------------------------------ from django.db.models import Q limit_choices_to=Q(share_holder=True) | Q(distributor=True) ------------------------------------------------------------------ product = models.ForeignKey( Product, limit_choices_to={ id__in=BaseModel._product_list, }, ) ------------------------------------------------------------------

+ CBV - Simple View (May 4, 2020, 3:08 p.m.)

class RestoreQuestion(View): def get(self, request, *args, **kwargs): pk = self.kwargs.get('pk') if pk: Question.objects.filter(id=pk).update(deleted=False) return HttpResponseRedirect(reverse_lazy('deletions:home')) else: return HttpResponseRedirect(reverse_lazy('home'))

+ CBV - Pass Params to Form (May 4, 2020, 10:28 a.m.)

View: class QuestionEditView(SuccessMessageMixin, UpdateView): model = Question template_name = 'expert_verified/edit.html' success_message = format_lazy( _('The {item} was updated successfully.'), item=_('question') ) form_class = QuestionForm context_object_name = 'question' def get_form_kwargs(self): kwargs = super().get_form_kwargs() kwargs.update({'request': self.request}) return kwargs form: class QuestionForm(forms.ModelForm): def __init__(self, *args, **kwargs): self.request = kwargs.pop('request') super().__init__(*args, **kwargs) print(self.request.user)

+ Makemessages exclude (April 11, 2020, 3:31 p.m.)

django-admin makemessages -i apps/ -l fa

+ Thread in TemplateView (April 8, 2020, 9:29 a.m.)

class QuestionsImportView(TemplateView): template_name = 'questions/index.html' def get(self, request, *args, **kwargs): threading.Thread(target=import_questions).start() context = self.get_context_data(**kwargs) return self.render_to_response(context)

+ DRF - get_extra_kwargs method (March 3, 2020, 2:21 p.m.)

def get_extra_kwargs(self): # Set "document" to non-required for partial-update action. extra_kwargs = {'city': {'required': True}} action = self.context['view'].action if action == 'partial_update': extra_kwargs['document'] = {'required': False} return extra_kwargs

+ DRF - Viewsets (March 1, 2020, 1:53 p.m.)

The ViewSet class inherits from APIView. You can use any of the standard attributes such as permission_classes, authentication_classes in order to control the API policy on the viewset. A ViewSet class is simply a type of class-based View, that does not provide any method handlers such as .get() or .post(), and instead provides actions such as .list() and .create(). class UserViewSet(viewsets.ViewSet): """ A simple ViewSet for listing or retrieving users. """ def list(self, request): queryset = User.objects.all() serializer = UserSerializer(queryset, many=True) return Response(serializer.data) def retrieve(self, request, pk=None): queryset = User.objects.all() user = get_object_or_404(queryset, pk=pk) serializer = UserSerializer(user) return Response(serializer.data) ----------------------------------------------------------------------------------- ViewSet actions: def list(self, request): pass def create(self, request): pass def retrieve(self, request, pk=None): pass def update(self, request, pk=None): pass def partial_update(self, request, pk=None): pass def destroy(self, request, pk=None): pass ----------------------------------------------------------------------------------- The ViewSet class does not provide any implementations of actions. In order to use a ViewSet class you'll override the class and define the action implementations explicitly. ----------------------------------------------------------------------------------- GenericViewSet The GenericViewSet class inherits from GenericAPIView, and provides the default set of get_object, get_queryset methods and other generic view base behavior, but does not include any actions by default. In order to use a GenericViewSet class you'll override the class and either mixin the required mixin classes, or define the action implementations explicitly. ----------------------------------------------------------------------------------- ModelViewSet The ModelViewSet class inherits from GenericAPIView and includes implementations for various actions, by mixing in the behavior of the various mixin classes. The actions provided by the ModelViewSet class are .list(), .retrieve(), .create(), .update(), .partial_update(), and .destroy(). ----------------------------------------------------------------------------------- ReadOnlyModelViewSet The ReadOnlyModelViewSet class also inherits from GenericAPIView. As with ModelViewSet it also includes implementations for various actions, but unlike ModelViewSet only provides the 'read-only' actions, .list() and .retrieve(). -----------------------------------------------------------------------------------

+ Faker & Factoryboy (Feb. 24, 2020, 10:23 a.m.)

https://faker.readthedocs.io/en/latest/providers/faker.providers.lorem.html https://factoryboy.readthedocs.io/en/latest/introduction.html https://factoryboy.readthedocs.io/en/latest/recipes.html https://faker.readthedocs.io/en/latest/providers.html https://factoryboy.readthedocs.io/en/latest/reference.html#simple-parameters ---------------------------------------------------------------------- from accounts.factories import AccountFactory AccountFactory() AccountFactory.reset_sequence() AccountFactory.reset_sequence(10) ----------------------------------------------------------------------

+ Create Test Database Permission Denied (Jan. 22, 2020, 3:38 p.m.)

When running "python manage.py test" command, you might get the error: "Got an error creating the test database: permission denied to create database" For solving the problem, you need to give permission to your project database user: sudo su su postgres -l psql ALTER USER mohsen CREATEDB; Instead of "mohsen" write your project database username.

+ Test - RequestFactory vs Client (Jan. 22, 2020, 11:31 a.m.)

TestCase is used when you want to test an HTTP request and RequestFactory is used when you want to test the views by calling them inside Django. ----------------------------------------------------------------------- Typically just use the test client. That'll ensure that you're testing your project more completely, as the full request-response cycle is under test, including routing and middleware. ----------------------------------------------------------------------- Use RequestFactory if you want to write unit tests that require a request instance, or if you have some good reason to want to test just the view itself. ----------------------------------------------------------------------- RequestFactory will be much quicker, which is important when you have a lot of tests. It is also only testing the part you want to test, which is a better unit test - you will more quickly know where the error is. You should still have some tests with TestCase to test the full HTTP request. ----------------------------------------------------------------------- Testing a GET request Before now, you may well have used the Django test client to test views. That is fine for higher-level tests, but if you want to test a view in isolation, it’s no use because it emulates a real web server and all of the middleware and authentication, which we want to keep out of the way. Instead, we need to use RequestFactory: from django.test import RequestFactory RequestFactory actually implements a subset of the functionality of the Django test client, so while it will feel somewhat familiar, it won’t have all the same functionality. For instance, it doesn’t support middleware, so rather than logging in using the test client’s login() method, you instead attach a user directly to the request, as in this example: request = RequestFactory() request.user = user ----------------------------------------------------------------------- RequestFactory returns a request, while Client returns a response. The RequestFactory does what it says - it's a factory to create request objects. Nothing more, nothing less. The Client is used to fake a complete request-response cycle. It will create a request object, which it then passes through a WSGI handler. This handler resolves the URL, calls the appropriate middleware and runs the view. It then returns the response object. It has the added benefit that it gathers a lot of extra data on the response object that is extremely useful for testing. The RequestFactory doesn't actually touch any of your code, but the request object can be used to test parts of your code that require a valid request. The Client runs your views, so in order to test your views, you need to use the Client and inspect the response. -----------------------------------------------------------------------

+ Files and Directories (Jan. 3, 2020, 2:12 p.m.)

os.makedirs( settings.VOICEMAIL_ROOT + '/deleted/request/{}'.format(voicemail_record.voicemail_id), exist_ok=True) os.makedirs( settings.VOICEMAIL_ROOT + '/deleted/response/{}'.format(voicemail_record.voicemail_id), exist_ok=True) --------------------------------------------------------------- shutil.move(voicemail_record.recording_path.path, '{}/deleted/request/{}/'.format( settings.VOICEMAIL_ROOT, voicemail_record.voicemail_id) ) if voicemail_record.reply_recording_path: shutil.move(voicemail_record.reply_recording_path.path, '{}/deleted/response/{}/'.format( settings.VOICEMAIL_ROOT, voicemail_record.voicemail_id) ) ---------------------------------------------------------------

+ Excel Files (Dec. 24, 2019, 7:27 p.m.)

import xlrd if request.POST and request.FILES: excel_file = request.FILES['excel_file'].read() book = xlrd.open_workbook(file_contents=excel_file) sheet = book.sheet_by_index(0) for row_num in range(sheet.nrows): sheet.row_values(row_num)[1]

+ DRF - to_representation vs to_internal_value (Dec. 23, 2019, 11:53 a.m.)

The to_representation() method is called to convert the initial datatype into a primitive, serializable datatype. The to_internal_value() method is called to restore a primitive datatype into its internal python representation. This method should raise a "serializers.ValidationError" if the data is invalid. ------------------------------------------------------------------------------------------ def to_internal_value(self, data): data_ = data.copy() # Get registrar type if data.get('registrar_type'): if data['registrar_type'] == 'student': data_['registrar_type'] = '1' elif data['registrar_type'] == 'teacher': data_['registrar_type'] = '2' return super().to_internal_value(data_) ------------------------------------------------------------------------------------------

+ CBV - Raise form error in form_valid() (Dec. 18, 2019, 2:37 p.m.)

def form_valid(self, form): data = form.cleaned_data if data['default_unit'].pk not in data['units'].values_list('pk', flat=True): form.add_error('default_unit', _('The selected item does not exist in selected units.')) return self.form_invalid(form) return super().form_valid(form)

+ CBV - Change form widget in generic CreateView/UpdateView (Dec. 18, 2019, 10:26 a.m.)

from django.forms.models import modelform_factory class ModelFormWidgetMixin: def get_form_class(self): return modelform_factory(self.model, fields=self.fields, widgets=self.widgets) ---------------------------------------------------------------------- from django import forms class ProductCreate(ModelFormWidgetMixin, CreateView): widgets = { 'units': forms.CheckboxSelectMultiple } ----------------------------------------------------------------------

+ Queries - Use regex (Dec. 12, 2019, 10:56 p.m.)

The records whose caller_id field has only 3 diits: Calls.objects.filter(caller_id__regex=r'^[0-9]{3}$') -------------------------------------------------------------

+ URLs - include (Dec. 8, 2019, 9:24 a.m.)

include(module, namespace=None) include(pattern_list) include((pattern_list, app_namespace), namespace=None) application namespace: This describes the name of the application that is being deployed. Every instance of a single application will have the same application namespace. For example, Django’s admin application has a somewhat predictable application namespace of 'admin'. instance namespace: This identifies a specific instance of an application. Instance namespaces should be unique across your entire project. However, an instance namespace can be the same as the application namespace. This is used to specify a default instance of an application. For example, the default Django admin instance has an instance namespace of 'admin'.

+ Create uploadpath based on the current date (Nov. 30, 2019, 11 a.m.)

def get_upload_path(instance, filename): return os.path.join('account/avatars/', now().date().strftime("%Y/%m/%d"), filename) class User(AbstractUser): avatar = models.ImageField(blank=True, upload_to=get_upload_path)

+ Modeling Polymorphism (Nov. 13, 2019, 12:18 p.m.)

Polymorphism is the ability of an object to take on many forms. Common examples of polymorphic objects include event streams, different types of users, and products in an e-commerce website. A polymorphic model is used when a single entity requires different functionality or information. ------------------------------------------------------------------

+ ugettext_lazy, ugettext, ugettext_noop (Nov. 10, 2019, 11:57 a.m.)

ugettext_lazy holds a reference to the translation string instead of the actual translated text, so the translation occurs when the value is accessed rather than when they’re called. When to use ugettext() or ugettext_lazy(): ugettext_lazy(): - models.py (fields, verbose_name, help_text, methods short_description); - forms.py (labels, help_text, empty_label); - apps.py (verbose_name). ugettext(): - views.py - Other modules similar to view functions that are executed during the request process ------------------------------------------------------------------ ugettext: The function returns the translation for the currently selected language. ugettext_lazy: The function marks the string as translation string, but only fetches the translated string when it is used in a string context, such as when rendering a template. ugettext_noop: This function only marks a string as a translation string, it does not have any other effect; that is, it always returns the string itself. The string is later translated from a variable. Use this if you have constant strings that should be stored in the source language because they are exchanged over systems or users – such as strings in a database – but should be translated at the last possible point in time, such as when the string is presented to the user. ------------------------------------------------------------------ ugettext_noop example: import logging from django.http import HttpResponse from django.utils.translation import ugettext as _, ugettext_noop as _noop def view(request): msg = _noop("An error has occurred") logging.error(msg) return HttpResponse(_(msg)) ------------------------------------------------------------------

+ Managers (Aug. 15, 2019, 9:36 a.m.)

class MyManager(models.Manager): def get_queryset(self): return super().get_queryset().filter(last_data__startswith='SIP/Mohsen') class MyModel(models.Model): ... objects = models.Manager() my_objects = MyManager()

+ FloatField vs DecimalField (July 31, 2019, 1:28 a.m.)

Always use DecimalField for money. Even simple operations (addition, subtraction) are not immune to float rounding issues. ------------------------------------------------------------- DecimalField: - DecimalFields must define a 'decimal_places' and a 'max_digits' attribute. - You get two free form validations included here from the above required attributes, i.e. If you set max_digits to 4, and you type in a decimal that is 4.00000 (5 digits), you will get this error: Ensure that there are no more than 4 digits in total. - You also get a similar form validation done for decimal places (which in most browsers will also validate on the front end using the step attribute on the input field. If you set decimal_places = 1 and type in 0.001 as the value you will get an error that the minimum value has to be 0.1. - With a Decimal type, rounding is also handled for you due to the required attributes that need to be set. - In the database (postgresql), the DecimalField is saved as a numeric(max_digits,decimal_laces) Type, and Storage is set as "main" ------------------------------------------------------------- FloatField: - No smart rounding, and can actually result in rounding issues as described in Seths answer. - Does not have the extra form validation that you get from DecimalField - In the database (postgresql), the FloatField is saved as a "double precision" Type, and Storage is set as "plain" -------------------------------------------------------------

+ Aggregation vs Annotation (July 22, 2019, 10:48 a.m.)

Aggregate is used to the aggregate whole table. User.objects.aggregate(total_users=Count('id')) Most of the time we want to apply the aggregations to groups of rows, and for that, annotate can be used. User.objects.values("is_staff").annotate(user_count=Count('*') User.objects.values("is_staff", "is_active").annotate(user_count=Count("*")) User.objects.values("is_staff").annotate(user_count=Count("*")).filter(user_count__gt = 1) ----------------------------------------------------------------------------- Aggregate calculates values for the entire queryset. Aggregate generates result (summary) values over an entire QuerySet. It operates over the rowset to get a single value from the rowset. (For example sum of all prices in the rowset). It is applied on the entire QuerySet and generates result (summary) values over an entire QuerySet. Book.objects.aggregate(average_price=Avg('price')) Returns a dictionary containing the average price of all books in the queryset. ----------------------------------------------------------------------------- Annotate calculates summary values for each item in the queryset. Annotate generates an independent summary for each object in a QuerySet.(We can say it iterates each object in a QuerySet and applies operation) Annotation >>> q = Book.objects.annotate(num_authors=Count('authors')) >>> q[0].num_authors 2 >>> q[1].num_authors 1 q is the queryset of books, but each book has been annotated with the number of authors. Annotation videos = Video.objects.values('id', 'name','video').annotate(Count('user_likes',distinct=True) -----------------------------------------------------------------------------

+ m2m (July 11, 2019, 7:37 p.m.)

For ModelForm just do: form.sve() If you had to use commit=False in form.save(), then you have to save the m2m manually: if form.is_valid(): project = form.save(commit=False) # Do something extra with "project" .... project.save() form.save_m2m() --------------------------------------------------------- if form.fields.get('units'): new_category.units.set(data['units']) ---------------------------------------------------------

+ Style Admin Interface in admin.py (April 18, 2018, 6:09 a.m.)

class NoteAdmin(admin.ModelAdmin): search_fields = ('title', 'note') list_filter = ('category',) class Media: css = { 'all': ('admin/css/interface.css',) } ------------------------------------------------------------- The path to "interface.css" is: Projects/notes/notes/static/admin/css/interface.css ------------------------------------------------------------- And finally, I couldn't make "nginx" recognize this file. For solving the problem I had to comment the "location /static/admin/" block in nginx file, and do "collectstatic" in my project to just gather together all admin static files. -------------------------------------------------------------

+ Ajax (April 22, 2018, 5:38 p.m.)

$.ajax({ type: 'POST', url: $(this).attr('href'), data: { csrfmiddlewaretoken: '{{ csrf_token }}', }, dataType: 'json', success: function (data) { }, error: function () { } }); ---------------------------------------------------------------------------- Examples of serializing data in views and return a response: from django.core import serializers def get_cities(request): if request.is_ajax(): cities = City.objects.filter(province=request.POST['province_id']) return HttpResponse(serialize('json', cities, fields=('pk', 'name'))) ---------------------------------------------------------------------------- def delete_order(request, p_type, pid): if request.is_ajax(): return JsonResponse({'orders_length': len(request.session['orders']), 'total_price': request.session['orders_total_price'], 'status': 'deleted'}) ---------------------------------------------------------------------------- return HttpResponse('rejected', content_type='text/plain') ---------------------------------------------------------------------------- foos = Foo.objects.all() data = serializers.serialize('json', foos) return HttpResponse(data, mimetype='application/json') ---------------------------------------------------------------------------- import json def json_response(something): return HttpResponse(json.dumps(something), content_type='application/javascript; charset=UTF-8') ---------------------------------------------------------------------------- from django.core.serializers.json import DjangoJSONEncoder def categories_view(request): categories = Category.objects.annotate(notes_count=Count('notes__pk')).values('pk', 'name', 'notes_count') data = json.dumps(list(categories), cls=DjangoJSONEncoder) return HttpResponse(data, content_type='application/json') ---------------------------------------------------------------------------- For Django 1.7+ from django.http import JsonResponse return JsonResponse({'foo': 'bar'}) Serializing non-dictionary objects In order to serialize objects other than dict you must set the safe parameter to False: return JsonResponse([1, 2, 3], safe=False) Without passing safe=False, a TypeError will be raised. ---------------------------------------------------------------------------- If you need to serialize some fields of an object, you can not use this: return JsonResponse({'products': serialize('json', Coffee.objects.all().values('id', 'name'))}) The correct way is: return JsonResponse({'products': serialize('json', Coffee.objects.all(), fields=('id', 'name'))}) ---------------------------------------------------------------------------- success: function (cities) { $("#id_city").empty(); $('<option value="0"> ---------- </option>').appendTo('#id_city'); $.each(cities, function (idx, city) { console.log(idx, city); $('<option value="' + city['pk'] + '">' + city['fields']['name'] + '</option>').appendTo($('#id_city')); }); }, ----------------------------------------------------------------------------

+ Django-2 Sample settings.py (April 29, 2018, 1:14 p.m.)

import os import re def gettext_noop(s): return s BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) ROOT_URLCONF = 'mohsenhassani.urls' DEBUG = True ADMINS = [('Mohsen Hassani', 'Mohsen@MohsenHassani.com')] ALLOWED_HOSTS = [] if DEBUG: ALLOWED_HOSTS.extend(['localhost', '127.0.0.1']) TIME_ZONE = 'Asia/Tehran' USE_TZ = True LANGUAGE_CODE = 'en-us' LANGUAGES = [('en', gettext_noop('English')), ('fa', gettext_noop('Persian'))] USE_I18N = True LOCALE_PATHS = [ os.path.join(BASE_DIR, 'locale'), ] USE_L10N = True SERVER_EMAIL = 'report@mohsenhassani' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'mohsenhassanidb', 'USER': 'root', 'PASSWORD': '', } } INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.humanize', 'mohsenhassani', ] TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] PREPEND_WWW = False DISALLOWED_USER_AGENTS = [ re.compile(r'^NaverBot.*'), re.compile(r'^EmailSiphon.*'), re.compile(r'^SiteSucker.*'), re.compile(r'^sohu-search'), re.compile(r'^DotBot'), ] IGNORABLE_404_URLS = [ re.compile(r'^/favicon.ico$'), re.compile(r'^/robots.txt$'), ] SECRET_KEY = 'xqb&)90m*_!n3ovc$@%mo8!8!7j5d9o=8nm(iyw%#mzz&o1n6)' MEDIA_ROOT = os.path.join(BASE_DIR, 'mohsenhassani', 'media/') MEDIA_URL = '/media/' STATIC_ROOT = os.path.join(BASE_DIR, 'mohsenhassani', 'static/') STATIC_URL = '/static/' FILE_UPLOAD_MAX_MEMORY_SIZE = 52428800 # i.e. 50 MB WSGI_APPLICATION = 'mohsenhassani.wsgi.application' MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] SESSION_EXPIRE_AT_BROWSER_CLOSE = True AUTH_USER_MODEL = 'accounts.User' LOGIN_URL = '/accounts/login/' LOGIN_REDIRECT_URL = '/accounts/profile/' LOGOUT_REDIRECT_URL = None PASSWORD_RESET_TIMEOUT_DAYS = 3 AUTH_PASSWORD_VALIDATORS = [] NUMBER_GROUPING = 3

+ Send HTML Email with Attachment (April 30, 2018, 5:10 p.m.)

from django.core.mail import EmailMessage email = EmailMessage('subject', 'message', 'email_from', ['to_email'] ) email.content_subtype = "html" if data['attachment']: file_ = data['attachment'] email.attach(file_.name, file_.read(), file_.content_type) email.send() ----------------------------------------------------------------------------- for attachment in request.FILES: if data[attachment]: file_ = data[attachment] email.attach(file_.name, file_.read(), file_.content_type) -----------------------------------------------------------------------------

+ URL - Login Required & is_superuser (May 1, 2018, 10:26 a.m.)

from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import user_passes_test urlpatterns = [ path('reports/', user_passes_test(lambda u: u.is_superuser)( login_required(report.reports)), name='reports'), ] oops.... iIt seems "user_passes_test" already does check the "login_required" somehow... so remove that decorator: path('reports/', user_passes_test(lambda u: u.is_superuser)(report.reports), name='reports'),

+ Database Functions, Aggregation, Annotations (June 16, 2018, 10:25 a.m.)

from django.db.models import F OrgPayment.objects.update(shares=F('shares') / 70000) Property.objects.filter(id=pid).update(views=F('views') + 1) ------------------------------------------------------------ from django.db.models import Count Book.objects.annotate(num_authors=Count('authors')).order_by('num_authors') ------------------------------------------------------------ from django.db.models import Avg Author.objects.annotate(average_rating=Avg('book__rating')) ------------------------------------------------------------ from django.db.models import Avg, Count Book.objects.annotate(num_authors=Count('authors')).aggregate(Avg('num_authors')) ------------------------------------------------------------ Database Functions: Coalesce: from django.db.models import Sum, Value from django.db.models.functions import Coalesce certificates_total_hours = reward_request.chosen_certificates.aggregate(total_hours=Coalesce(Sum('course_hours'), Value(0))) ------------------------------------------------------------ Concat: # Get the display name as "name (goes_by)" from django.db.models import CharField, Value as V from django.db.models.functions import Concat Author.objects.create(name='Margaret Smith', goes_by='Maggie') author = Author.objects.annotate( screen_name=Concat('name', V(' ('), 'goes_by', V(')'), output_field=CharField())).get() print(author.screen_name) ------------------------------------------------------------ Length: Accepts a single text field or expression and returns the number of characters the value has. If the expression is null, then the length will also be null. from django.db.models.functions import Length Author.objects.create(name='Margaret Smith') author = Author.objects.annotate( name_length=Length('name'), goes_by_length=Length('goes_by')).get() print(author.name_length, author.goes_by_length) ------------------------------------------------------------ Lower: Accepts a single text field or expression and returns the lowercase representation. Usage example: >>> from django.db.models.functions import Lower >>> Author.objects.create(name='Margaret Smith') >>> author = Author.objects.annotate(name_lower=Lower('name')).get() >>> print(author.name_lower) margaret smith ------------------------------------------------------------ Substr: Returns a substring of length (length) from the field or expression starting at position pos. The position is 1-indexed, so the position must be greater than 0. If the length is None, then the rest of the string will be returned. Usage example: >>> # Set the alias to the first 5 characters of the name as lowercase >>> from django.db.models.functions import Substr, Lower >>> Author.objects.create(name='Margaret Smith') >>> Author.objects.update(alias=Lower(Substr('name', 1, 5))) 1 >>> print(Author.objects.get(name='Margaret Smith').alias) marga ------------------------------------------------------------ Upper: Accepts a single text field or expression and returns the uppercase representation. >>> from django.db.models.functions import Upper >>> Author.objects.create(name='Margaret Smith') >>> author = Author.objects.annotate(name_upper=Upper('name')).get() >>> print(author.name_upper) MARGARET SMITH ------------------------------------------------------------

+ Create directories if they don't exist (June 17, 2018, 4:39 p.m.)

import os from django.conf import settings avatar_path = '%s/images/avatars' % settings.MEDIA_ROOT if not os.path.exists(os.path.dirname(avatar_path)): os.makedirs(avatar_path)

+ Serve media files in debug mode (April 15, 2019, 10:41 a.m.)

urls.py: --------- from django.conf import settings from django.conf.urls.static import static if settings.DEBUG: urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

+ Save file path to Django ImageField (June 17, 2018, 5:40 p.m.)

models.py: ------------- avatar = models.ImageField(_('avatar'), upload_to='manager/images/avatars/', null=True, blank=True) views: -------- request.user.avatar.name = 'images/avatars/mohsen.png' request.user.save()

+ Forms - Validate Excel File (July 2, 2018, 9:23 a.m.)

from xlrd import open_workbook, XLRDError from django import forms from django.utils.translation import ugettext_lazy as _ class UploadExcelForm(forms.Form): file = forms.FileField(label=_('file')) def clean_excel_file(self): excel_file = self.cleaned_data['excel_file'] try: open_workbook(file_contents=excel_file.read()) excel_file.file.seek(0) except XLRDError: raise forms.ValidationError(_('Please upload a valid excel file.')) return excel_file

+ Messages (July 6, 2018, 7:27 p.m.)

View: ------------ from django.contrib import messages messages.success(request, _('The information was saved successfully.')) return HttpResponseRedirect(reverse('url', args=(code,))) ----------------------------------------------------------------- Template: ------------ {% if messages %} <ul class="messages"> {% for message in messages %} <li {% if message.tags %} class="alert alert-{{ message.tags }}" {% endif %}>{{ message }}</li> {% endfor %} </ul> {% endif %} ----------------------------------------------------------------- {% if message.tags == 'success' %} ----------------------------------------------------------------- https://getbootstrap.com/docs/4.0/components/alerts/ https://testdriven.io/tips/9329fe4a-605d-4c73-b254-d79542925b81/ https://docs.djangoproject.com/en/4.2/ref/contrib/messages/ -----------------------------------------------------------------

+ QuerySet - Filter based on Text Length (July 16, 2018, 1:34 p.m.)

from django.db.models.functions import Length invalid_username = Driver.objects.annotate( text_len=Length('username')).filter(text_len__lt=11)

+ QuerySet - Duplicate objects based on a specific field (July 16, 2018, 1:46 p.m.)

duplicate_plate_number_ids = Driver.objects.values( 'plate_number').annotate(Count('plate_number')).order_by().filter( plate_number__count__gt=1).values_list('plate_number', flat=True) --------------------------------------------------------------------------------------------------------- duplicate_invoices = Invoice.objects.values('number').annotate(number_count=Count('number')).filter(number_count__gt=1) ---------------------------------------------------------------------------------------------------------

+ Bulk Insert / Bulk Create (Oct. 7, 2018, 10:37 a.m.)

entry_records = [] for i in range(2000): entry_records.append(Entry(headline='This is a test')) Entry.objects.bulk_create(entry_records)

+ Force files to open in the browser instead of downloading (Oct. 9, 2018, 8:18 a.m.)

Force browser that the file should be viewed in the browser: Content-Type: application/pdf Content-Disposition: inline; filename="filename.pdf" To have the file downloaded rather than viewed: Content-Type: application/pdf Content-Disposition: attachment; filename="filename.pdf"

+ Find Model Relations (Oct. 17, 2018, 4:18 p.m.)

for field in [f for f in file._meta.get_fields() if not f.concrete] ---------------------------------------------------------------------- model = field.related_model model = type(instance) # For deferred instances model = instance._meta.proxy_for_model ---------------------------------------------------------------------- app_label = model._meta.app_label app_label = instance._meta.app_label ---------------------------------------------------------------------- model_name = model.__name__ ---------------------------------------------------------------------- if field.get_internal_type() == 'ForeignKey': ---------------------------------------------------------------------- field.remote_field.name ---------------------------------------------------------------------- field.through.objects.filter(file_id=file.id) ---------------------------------------------------------------------- ct = ContentType.objects.get_for_model(model) ---------------------------------------------------------------------- model._meta.local_fields ----------------------------------------------------------------------

+ Pass JSON object data from view to template (April 13, 2019, 10:02 a.m.)

View: import json data = json.dumps(the_dictionary) return render(request, 'abc.html', {'data': data}) ---------------------------------------------------- Template: <script type="text/javascript"> {{ data|safe }} </script>

+ Form - Access Field type in template (Dec. 8, 2018, 10:53 a.m.)

{{ field.field.widget.input_type }}

+ QuerySet - Group By (Dec. 14, 2018, 7:22 a.m.)

requests = Loan.objects.filter(loan__type='n', status__status__in=['1', '2', '3']) stats = requests.values('personnel__center__title').annotate(Count('id')).order_by() {% for stat in stats %} <tr> <td>{{ forloop.counter }}</td> <td>{{ stat.personnel__center__title }}</td> <td>{{ stat.id__count }}</td> </tr> {% endfor %} ----------------------------------------------------------------------- this_week_articles = Article.objects.filter( created_at__gte=seven_days_ago, deleted=False ).values('creating_user__first_name', 'creating_user__last_name' ).annotate(Count('pk')).order_by() # Result is: <QuerySet [{'creating_user__last_name': 'Hassani', 'creating_user__first_name': 'Mohsen', 'pk__count': 286}, {'creating_user__last_name': 'BiGheri', 'creating_user__first_name': 'Mehdi', 'pk__count': 31}]> ----------------------------------------------------------------------- from itertools import groupby def extract_call_id(call): return call.call_id grouped_call_ids = [list(g) for t, g in groupby(today_calls, key=extract_call_id)] For returning a dictionary instead of "list" in the above example, see the following example. grouped_call_ids = [{'title': t, 'calls': list(g)} for t, g in groupby(today_calls, key=extract_call_id)] -----------------------------------------------------------------------

+ Google reCAPTCHA API (Dec. 17, 2018, 11:25 a.m.)

1- Register your application in the reCAPTCHA admin: https://www.google.com/recaptcha/admin#list 2- After registering your website, you will be handed a Site key and a Secret key. The Site key will be used in the reCAPTCHA widget which is rendered within the page where you want to place it. The Secret key will be stored safely in the server, made available through the settings.py module. GOOGLE_RECAPTCHA_SECRET_KEY = '' 3- Add the following tag to the head: <script src='https://www.google.com/recaptcha/api.js'></script> 4- Add the following tag to the form: <div class="g-recaptcha" data-sitekey=""></div> 5- pip install requests 6- Views.py import requests from django.conf import settings if request.POST: recaptcha_response = request.POST.get('g-recaptcha-response') data = { 'secret': settings.GOOGLE_RECAPTCHA_SECRET_KEY, 'response': recaptcha_response } response = requests.post( 'https://www.google.com/recaptcha/api/siteverify', data=data) result = response.json() if result['success']: else:

+ Split QuerySets (Dec. 17, 2018, 8:56 p.m.)

def chunks(items, length): for chunk in range(0, len(items), length): yield items[chunk:chunk + length] ------------------------------------------------------------ Usage Example: excel_file = get_object_or_404(ExcelFile, id=eid) job_list = list(chunks(excel_file.tempdata_set.all(), 250)) ------------------------------------------------------------

+ Admin - Render checkboxes for m2m (Jan. 13, 2019, 8:36 a.m.)

admin.py: --------------------------------------------------------- from django.contrib.auth.admin import UserAdmin from django.db import models from django.forms import CheckboxSelectMultiple class PersonnelAdmin(UserAdmin): formfield_overrides = { models.ManyToManyField: {'widget': CheckboxSelectMultiple} }

+ Truncate a long string (Jan. 27, 2019, 12:17 a.m.)

data = data[:75] ---------------------------------------------------------------------- import textwrap textwrap.shorten("Hello world!", width=12) textwrap.shorten("Hello world", width=10, placeholder="...") ---------------------------------------------------------------------- from django.utils.text import Truncator value = Truncator(value).chars(75) ----------------------------------------------------------------------

+ Model Conventions (Feb. 8, 2019, 6:23 a.m.)

https://steelkiwi.com/blog/best-practices-working-django-models-python/

+ CSRF Token in an external javascript file (March 16, 2019, 12:41 p.m.)

function getCookie(name) { var cookieValue = null; if (document.cookie && document.cookie != '') { var cookies = document.cookie.split(';'); for (var i = 0; i < cookies.length; i++) { var cookie = cookies[i].trim(); // Does this cookie string begin with the name we want? if (cookie.substring(0, name.length + 1) == (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } // Then call it like the following: getCookie('csrftoken');

+ Forms - Validation (March 11, 2018, 2:59 p.m.)

class ReportForm1(forms.Form): src_server_ip = forms.CharField(required=False) dst_server_ip = forms.CharField(required=False) def clean(self): if self.cleaned_data['src_server_ip'] == '' and self.cleaned_data[ 'dst_server_ip'] == '': self.add_error('src_server_ip', 'At lease a source or destination is required.')

+ URL Regex that accepts all characters (Jan. 19, 2018, 11:44 p.m.)

(.*)

+ Forms - Custom ModelChoiceField (Nov. 15, 2017, 2:24 p.m.)

class AppointmentChoiceField(forms.ModelChoiceField): def label_from_instance(self, appointment): return "%s" % appointment.get_time() -------------------------------------------------------------------- class IntCommaChoiceField(forms.ModelChoiceField): def label_from_instance(self, base_amount): return "%s" % intcomma(base_amount) -------------------------------------------------------------------- class LoanAmountEditForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['base_amount'] = IntCommaChoiceField( queryset=LoanBaseAmount.objects.all(), label=_('base amount') ) class Meta: model = LoanAmount exclude = [] --------------------------------------------------------------------

+ JPG Validator (July 17, 2017, 8:53 a.m.)

from PIL import Image def jpg_validator(certificate): file_type = Image.open(certificate.file).format certificate.file.seek(0) if file_type == 'jpg' or file_type == 'JPEG': return True else: raise ValidationError(_('The extension of certificate file should be jpg.'))

+ Views - order_by sum of fields (June 10, 2017, 11:54 a.m.)

top_traffic_servers = Server.objects.extra( select={'sum': 'total_bytes_outgoing + total_bytes_incoming'}, order_by=('-sum',)) --------------------------------------------------- If you need to do some filtering, you can add filter() to the end: top_traffic_servers = Server.objects.extra( select={'sum': 'total_bytes_outgoing + total_bytes_incoming'}, order_by=('-sum',)).filter(status='1')

+ Use MySQL or MariaDB with Django (May 18, 2017, 8:41 p.m.)

1- Installation: MySQL: sudo apt-get install python-pip python-dev mysql-server libmysqlclient-dev MariaDB: sudo apt-get install python-pip python-dev mariadb-server libmariadbclient-dev libssl-dev 2- mysql -u root -p 3- CREATE DATABASE myproject CHARACTER SET UTF8; 4- CREATE USER myprojectuser@localhost IDENTIFIED BY 'password'; 5- GRANT ALL PRIVILEGES ON myproject.* TO myprojectuser@localhost; 6- FLUSH PRIVILEGES; 7- exit 8- In the project environment: pip install mysqlclient

+ X-Frame-Options (Sept. 26, 2016, 8:35 p.m.)

Error in remote calling: ..does not permit cross-origin framing Description: There is a special header to allow or disallow showing page inside i-frame - X-Frame-Options It's used to prevent an attack called clickjacking. You can check the Django's doc about it https://docs.djangoproject.com/en/dev/ref/clickjacking/ Sites that want their content to be shown in i-frame just don't set this header. In your installation of Django this protection is turned on by default. If you wan't to allow embedding your content inside i-frames you can either disable the clickjack protection in your settings for the whole site, or use per view control with: django.views.decorators.clickjacking decorators xframe_options_exempt xframe_options_deny xframe_options_sameorigin Per view control is a better option. -------------------------------------------------------------- Example: from django.views.decorators.clickjacking import xframe_options_exempt @xframe_options_exempt def home(request): #

+ Django Session Key (Sept. 20, 2016, 7:28 p.m.)

if not request.session.exists(request.session.session_key): request.session.create() session_key = request.session.session_key

+ Django REST Framework - Installation and Configuration (Sept. 19, 2016, 11:14 p.m.)

1-pip install djangorestframework django-filter markdown 2-Add 'rest_framework' to your INSTALLED_APPS setting. INSTALLED_APPS = ( ... 'rest_framework', ) 3-If you're intending to use the browsable API you'll probably also want to add REST framework's login and logout views. Add the following to your root urls.py file. urlpatterns = [ url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')) ]

+ User Timezone (Sept. 5, 2016, 12:42 a.m.)

There are several plugins you can use, but I guess there are reasons I need to avoid using them: - They mainly require big .dat files which contain the timezones allover the world - They use middlewares to check the user's timezone, which might be called on every request and finally cause speed problem when opening pages. - They only work with templates (using template tags and filters). -------------------------------------------------------- The simplest way I have achieved is using a snippet which uses an online web service: import requests import pytz user_time_zone = requests.get('http://freegeoip.net/json/').json()['time_zone'] timezone.activate(pytz.timezone(user_time_zone)) This snippet can be used in only the views which need to detect user's timezone; no need of middleware. -------------------------------------------------------- If you ever needed to use it in every request, you can use it in a middleware. Create a file named `middleware.py` and add this middleware to it: import requests import pytz from django.utils import timezone class UserTimezoneMiddleware(object): def process_request(self, request): try: freegeoip_response = requests.get('http://freegeoip.net/json/') freegeoip_response_json = freegeoip_response.json() user_time_zone = freegeoip_response_json['time_zone'] timezone.activate(pytz.timezone(user_time_zone)) except: pass return None Add the `UserTimezoneMiddleware` class to settings.py `MIDDLEWARE_CLASSES` variable. Now you can get the date/time based on user's timezone: timezone.localtime(timezone.now() timezone.localtime(settings_.under_construction_until) --------------------------------------------------------

+ Timestamp from datetime field (Sept. 4, 2016, 11:35 p.m.)

You can do it in template or in view. Template: ------------ {% now "U" %} {{ value|date:"U" }} ------------------------------------------------------------------ View: ------- from django.utils.dateformat import format format(mymodel.mydatefield, 'U') OR import time time.mktime(mydate.timetuple())

+ Manually create a POST/GET QueryDict from a dictionary (Aug. 27, 2016, 1:41 a.m.)

from django.http import QueryDict, MultiValueDict get_data = {'p_type': request.GET['p_type'], 'facilities': request.GET.getlist('facilities')} OR get_data = dict(request.GET.iteritems()) qdict = QueryDict('', mutable=True) qdict.update(MultiValueDict({'facilities': get_data['facilities']})) qdict.update(post_data) request.POST = qdict

+ Django Dumpdata Field (Aug. 26, 2016, 2:13 a.m.)

https://github.com/bitmazk/django-dumpdata-field 1- pip install django-dumpdata-field 2- INSTALLED_APPS = ( 'dumpdata_field', ) 3- dumpdata_field facemelk.province --fields=id,province_name > /home/mohsen/Projects/facemelk/facemelk/fixtures/provinces_fields.json

+ Ajax File Upload (Aug. 22, 2016, 8:50 p.m.)

<form action="{% url 'glasses:upload-face' %}" method="POST" id="upload-face-form" enctype="multipart/form-data"> {% csrf_token %} <input type="file" id="upload-face" name="face" /> </form> ------------------------------------------------------- $('#upload-face').change(function() { var form = $('#upload-face-form'); var form_data = new FormData(form[0]); $.ajax({ type: form.attr('method'), url: form.attr('action'), data: form_data, contentType: false, cache: false, processData: false, dataType: 'json', success: function(image) { }, error: function(error) { } }); }); ------------------------------------------------------- def upload_face(request): if request.is_ajax(): image = request.FILES.get('face') if image: face = open('face.jpg', 'wb') for chunk in image.chunks(): face.write(chunk) face.close() return JsonResponse({'hi': 'hi'}) else: return HttpResponseRedirect(reverse('home')) -------------------------------------------------------

+ Django Grappelli (May 16, 2016, 2:34 a.m.)

Official Website: http://grappelliproject.com/ ------------------------------------------------- Documentation https://django-grappelli.readthedocs.io/en/latest/ ------------------------------------------------- Installation: pip install django-grappelli ------------------------------------------------- Setup: 1- INSTALLED_APPS = ( 'grappelli', 'django.contrib.admin', ) 2-Add URL-patterns: urlpatterns = [ url(r'^grappelli/', include('grappelli.urls')), url(r'^admin/', include(admin.site.urls)), ] 3-Add the request context processor (needed for the Dashboard and the Switch User feature): TEMPLATES = [ { ... 'OPTIONS': { 'context_processors': [ ... 'django.template.context_processors.request', ... ], }, }, ] 4-Collect the media files: python manage.py collectstatic ------------------------------------------------- Custmoization: http://django-grappelli.readthedocs.io/en/latest/customization.html ------------------------------------------------- Dashboard Setup: http://django-grappelli.readthedocs.io/en/latest/dashboard_setup.html ------------------------------------------------- Third Party Applications: http://django-grappelli.readthedocs.io/en/latest/thirdparty.html

+ Views - Receive and parse JSON data from a request using django-cors-headers (May 4, 2016, 1:49 a.m.)

import json from django.views.decorators.csrf import csrf_exempt @csrf_exempt def update_note(request): request_json_data = bytes.decode(request.body) request_data = json.loads(request_json_data) print(request_data) ------------------------------------------------------------------ You need to install a plugin too: https://github.com/ottoyiu/django-cors-headers 1- pip install django-cors-headers 2- INSTALLED_APPS = ( ... 'corsheaders', ... ) 3- MIDDLEWARE = [ # Or MIDDLEWARE_CLASSES on Django < 1.10 ... 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', ... ] 4- CORS_ORIGIN_WHITELIST = ( 'http://localhost:8000', )

+ Internationalization (May 2, 2016, 9:26 p.m.)

urls.py: from django.conf.urls.i18n import i18n_patterns urlpatterns += i18n_patterns() ---------------------------------------------------------------------- settings.py: MIDDLEWARE = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.locale.LocaleMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.security.SecurityMiddleware', ) ---------------------------------------------------------------------- And finally in a context_processors.py file, add some snippet like this: def change_language(request): if '/admin/' not in request.get_full_path(): if '/fa/' not in request.get_full_path(): activate('en') else: activate('fa') return {} else: return {} ---------------------------------------------------------------------- {% get_language_info for LANGUAGE_CODE as lang %} {% get_language_info for "pl" as lang %} You can then access the information: Language code: {{ lang.code }}<br /> Name of language: {{ lang.name_local }}<br /> Name in English: {{ lang.name }}<br /> Bi-directional: {{ lang.bidi }} Name in the active language: {{ lang.name_translated }} There are also simple filters available for convenience: {{ LANGUAGE_CODE|language_name }} (“German”) {{ LANGUAGE_CODE|language_name_local }} (“Deutsch”) {{ LANGUAGE_CODE|language_bidi }} (False) {{ LANGUAGE_CODE|language_name_translated }} (“německy”, when active language is Czech) <form action="{% url 'set_language' %}" method="post">{% csrf_token %} <input name="next" type="hidden" value="{{ redirect_to }}" /> <select name="language"> {% get_current_language as LANGUAGE_CODE %} {% get_available_languages as LANGUAGES %} {% get_language_info_list for LANGUAGES as languages %} {% for language in languages %} <option value="{{ language.code }}"{% if language.code == LANGUAGE_CODE %} selected="selected"{% endif %}> {{ language.name_local }} ({{ language.code }}) </option> {% endfor %} </select> <input type="submit" value="Go" /> </form> from django.utils import translation user_language = 'fr' translation.activate(user_language) request.session[translation.LANGUAGE_SESSION_KEY] = user_language from django.http import HttpResponse def hello_world(request, count): if request.LANGUAGE_CODE == 'de-at': return HttpResponse("You prefer to read Austrian German.") else: return HttpResponse("You prefer to read another language.") ---------------------------------------------------------------------- from django.conf import settings from django.utils import translation class ForceLangMiddleware: def process_request(self, request): request.LANG = getattr(settings, 'LANGUAGE_CODE', settings.LANGUAGE_CODE) translation.activate(request.LANG) request.LANGUAGE_CODE = request.LANG ----------------------------------------------------------------------

+ Admin - Access ModelForm properties (April 23, 2016, 7:39 a.m.)

def __init__(self, *args, **kwargs): initial = kwargs.get('initial', {}) initial['material'] = 'Test' kwargs['initial'] = initial super(ArtefactForm, self).__init__(*args, **kwargs) ----------------------------------- for field in self.fields.items(): print(field[0]) # Prints field names print(field[1].label) # Prints field labels

+ View - Replace/Populate POST data (April 19, 2016, 10:08 a.m.)

If the request was the result of a Django form submission, then it is reasonable for POST being immutable to ensure the integrity of the data between the form submission and the form validation. However, if the request was not sent via a Django form submission, then POST is mutable as there is no form validation. mutable = request.POST._mutable request.POST._mutable = True request.POST['some_data'] = 'test data' request.POST._mutable = mutable ---------------------------------------------------------------- In an HttpRequest object, the GET and POST attributes are instances of django.http.QueryDict, a dictionary-like class customized to deal with multiple values for the same key. This is necessary because some HTML form elements, notably <select multiple>, pass multiple values for the same key. The QueryDicts at request.POST and request.GET will be immutable when accessed in a normal request/response cycle. To get a mutable version you need to use .copy(). ---------------------------------------------------------------- request.POST = request.POST.copy() request.POST['some_key'] = 'some_value' ---------------------------------------------------------------- Methods QueryDict implements all the standard dictionary methods because it’s a subclass of dictionary. Exceptions are outlined here: QueryDict.__init__(query_string=None, mutable=False, encoding=None)[source] Instantiates a QueryDict object based on query_string. >>> QueryDict('a=1&a=2&c=3') <QueryDict: {'a': ['1', '2'], 'c': ['3']}> If query_string is not passed in, the resulting QueryDict will be empty (it will have no keys or values). Most QueryDicts you encounter, and in particular those at request.POST and request.GET, will be immutable. If you are instantiating one yourself, you can make it mutable by passing mutable=True to its __init__(). Strings for setting both keys and values will be converted from encoding to unicode. If encoding is not set, it defaults to DEFAULT_CHARSET. QueryDict.__getitem__(key) Returns the value for the given key. If the key has more than one value, __getitem__() returns the last value. Raises django.utils.datastructures.MultiValueDictKeyError if the key does not exist. (This is a subclass of Python’s standard KeyError, so you can stick to catching KeyError.) QueryDict.__setitem__(key, value)[source] Sets the given key to [value] (a Python list whose single element is value). Note that this, as other dictionary functions that have side effects, can only be called on a mutable QueryDict (such as one that was created via copy()). QueryDict.__contains__(key) Returns True if the given key is set. This lets you do, e.g., if "foo" in request.GET. QueryDict.get(key, default=None) Uses the same logic as __getitem__() above, with a hook for returning a default value if the key doesn’t exist. QueryDict.setdefault(key, default=None)[source] Just like the standard dictionary setdefault() method, except it uses __setitem__() internally. QueryDict.update(other_dict) Takes either a QueryDict or standard dictionary. Just like the standard dictionary update() method, except it appends to the current dictionary items rather than replacing them. For example: >>> q = QueryDict('a=1', mutable=True) >>> q.update({'a': '2'}) >>> q.getlist('a') ['1', '2'] >>> q['a'] # returns the last ['2'] QueryDict.items() Just like the standard dictionary items() method, except this uses the same last-value logic as __getitem__(). For example: >>> q = QueryDict('a=1&a=2&a=3') >>> q.items() [('a', '3')] QueryDict.iteritems() Just like the standard dictionary iteritems() method. Like QueryDict.items() this uses the same last-value logic as QueryDict.__getitem__(). QueryDict.iterlists() Like QueryDict.iteritems() except it includes all values, as a list, for each member of the dictionary. QueryDict.values() Just like the standard dictionary values() method, except this uses the same last-value logic as __getitem__(). For example: >>> q = QueryDict('a=1&a=2&a=3') >>> q.values() ['3'] QueryDict.itervalues() Just like QueryDict.values(), except an iterator. In addition, QueryDict has the following methods: QueryDict.copy()[source] Returns a copy of the object, using copy.deepcopy() from the Python standard library. This copy will be mutable even if the original was not. QueryDict.getlist(key, default=None) Returns the data with the requested key, as a Python list. Returns an empty list if the key doesn’t exist and no default value was provided. It’s guaranteed to return a list of some sort unless the default value provided is not a list. QueryDict.setlist(key, list_)[source] Sets the given key to list_ (unlike __setitem__()). QueryDict.appendlist(key, item)[source] Appends an item to the internal list associated with key. QueryDict.setlistdefault(key, default_list=None)[source] Just like setdefault, except it takes a list of values instead of a single value. QueryDict.lists() Like items(), except it includes all values, as a list, for each member of the dictionary. For example: >>> q = QueryDict('a=1&a=2&a=3') >>> q.lists() [('a', ['1', '2', '3'])] QueryDict.pop(key)[source] Returns a list of values for the given key and removes them from the dictionary. Raises KeyError if the key does not exist. For example: >>> q = QueryDict('a=1&a=2&a=3', mutable=True) >>> q.pop('a') ['1', '2', '3'] QueryDict.popitem()[source] Removes an arbitrary member of the dictionary (since there’s no concept of ordering), and returns a two value tuple containing the key and a list of all values for the key. Raises KeyError when called on an empty dictionary. For example: >>> q = QueryDict('a=1&a=2&a=3', mutable=True) >>> q.popitem() ('a', ['1', '2', '3']) QueryDict.dict() Returns dict representation of QueryDict. For every (key, list) pair in QueryDict, dict will have (key, item), where item is one element of the list, using same logic as QueryDict.__getitem__(): >>> q = QueryDict('a=1&a=3&a=5') >>> q.dict() {'a': '5'} QueryDict.urlencode(safe=None)[source] Returns a string of the data in query-string format. Example: >>> q = QueryDict('a=2&b=3&b=5') >>> q.urlencode() 'a=2&b=3&b=5' Optionally, urlencode can be passed characters which do not require encoding. For example: >>> q = QueryDict(mutable=True) >>> q['next'] = '/a&b/' >>> q.urlencode(safe='/') 'next=/a%26b/'

+ Admin - Hide fields dynamically (April 11, 2016, 5:37 p.m.)

def get_fields(self, request, obj=None): fields = admin.ModelAdmin.get_fields(self, request) if settings.DEBUG: return fields else: return ('parent', 'name_en', 'name_fa', 'content_en', 'content_fa', 'ordering', 'languages', 'header_image', 'project_thumbnail')

+ Error ==> Permission denied when trying to access database after restore (migration) (April 10, 2016, 9:17 p.m.)

Enter the commands in postgresql shell: psql mohsen_notesdb -c "GRANT ALL ON ALL TABLES IN SCHEMA public to mohsen_notes;" psql mohsen_notesdb -c "GRANT ALL ON ALL SEQUENCES IN SCHEMA public to mohsen_notes;" psql mohsen_notesdb -c "GRANT ALL ON ALL FUNCTIONS IN SCHEMA public to mohsen_notes;"

+ Admin - Reisze Image Signal (April 5, 2016, 10:21 a.m.)

Create a file `resize_image.py` with this content: from PIL import Image from django.conf import settings def resize_image(sender, instance, created, **kwargs): if instance.position == 't': width = settings.TOP_ADS_WIDTH height = settings.TOP_ADS_HEIGHT else: width = settings.BOTTOM_ADS_WIDTH height = settings.BOTTOM_ADS_HEIGHT img = Image.open(instance.image.path) if img.mode != 'RGB': img = img.convert('RGB') img.resize((width, height), Image.ANTIALIAS).save(instance.image.path, format='JPEG') -------------------------------------------------------------------------------------------- After model definition in your models.py file, import `resize_image` and: models.signals.post_save.connect(resize_image, sender=TheModel)

+ Admin - Hide model in admin dynamically (Feb. 29, 2016, 8:20 a.m.)

class AccessoryCategoryAdmin(admin.ModelAdmin): def get_model_perms(self, request): perms = admin.ModelAdmin.get_model_perms(self, request) if request.user.username == settings.SECOND_ADMIN: return {} return perms

+ Admin - Display readonly fields based on conditions (Feb. 28, 2016, 1:32 p.m.)

class AccessoryAdmin(admin.ModelAdmin): list_display = ('name', 'category', 'price', 'quantity', 'ordering', 'display') list_filter = ('category', 'display') def get_readonly_fields(self, request, obj=None): if request.user.username == settings.SECOND_ADMIN: readonly_fields = ('category', 'name', 'image', 'price', 'main_image', 'description', 'ordering', 'url_name') return readonly_fields else: return self.readonly_fields

+ Form - How to add a star after fields (Feb. 27, 2016, 9:17 p.m.)

Add the `required_css_class` property to Form class like this: class ProfileForm(forms.Form): required_css_class = 'required' first_name = forms.CharField(label=_('first name'), max_length=30) last_name = forms.CharField(label=_('last name'), max_length=30) cellphone_number = forms.CharField(label=_('cellphone'), max_length=20) Then use the property `label_tag` of form fields to set the titles: {{ form.first_name.errors }} {{ form.first_name.label_tag }} {{ form.last_name.errors }} {{ form.last_name.label_tag }} {{ form.cellphone_number.errors }} {{ form.cellphone_number.label_tag }} Use it in CSS to style it or add an asterisk: <style type="text/css"> .required:after { content: " *"; color: red; } </style>

+ Decorators (Jan. 29, 2016, 3:04 p.m.)

Create a python file named `decorators.py` in the app and write your decorators as follows: def login_required(view_func): def wrap(request, *args, **kwargs): if request.user.is_authenticated(): return view_func(request, *args, **kwargs) else: return render(request, 'issue_tracker/access_denied.html', {'login_required': 'yes'}) return wrap ----------------------------------------------------------- from django.utils.functional import wraps def can_participate_poll(view): @wraps(view) def inner(request, *args, **kwargs): print(kwargs) # Prints {'qnum': 11, 'qid': 23} return view(request, *args, **kwargs) return inner This will print the args which are passed to the view. @can_participate_poll def poll_view(request, qid, qnum): pass ----------------------------------------------------------- from django.contrib.auth.decorators import user_passes_test @user_passes_test(lambda u: u.is_superuser) def my_view(request): pass -----------------------------------------------------------

+ Admin - Change Header Title (Jan. 14, 2016, 7:14 p.m.)

In the main urls.py file: admin.site.site_header = _('YouStone Administration')

+ Change app name for admin (Jan. 27, 2016, 10:21 p.m.)

1- Create a python file named `apps.py` in the app: from django.apps import AppConfig from django.utils.translation import ugettext_lazy as _ class CourseConfig(AppConfig): name = 'course' verbose_name = _('course') 2- Edit the __init__.py file within the app: default_app_config = 'course.apps.CourseConfig'

+ Save File/Image (Dec. 1, 2015, 1:46 p.m.)

import uuid from PIL import Image as PILImage import imghdr import os from django.conf import settings from manager.home.models import Image def save_image(img_file, width=0, height=0): # Generate a random image name img_name = uuid.uuid4().hex + '.' + img_file.name.split('.')[-1] # Saving the picture on disk img = open(settings.IMG_ROOT + img_name, 'wb') for chunk in img_file.chunks(): img.write(chunk) img.close() img = open(img.name) # Is the saved image a valid image file!? if not imghdr.what(img) or imghdr.what(img).lower() not in ['jpg', 'jpeg', 'gif', 'png']: os.remove(img.name) return {'is_image': False} else: if width or height: # Resizing the image pil_img = PILImage.open(img.name) if pil_img.mode != 'RGB': pil_img = pil_img.convert('RGB') pil_img.resize((width, height), PILImage.ANTIALIAS).save(img.name, format='JPEG') # Saving the image location on the database img = Image.objects.create(name=img_name) return {'is_image': True, 'image': img} def create_unique_file_name(path, file_name): while os.path.exists(path + file_name): if '.' in file_name: file_name = file_name.replace('.', '_.', -1) else: file_name += '_' return file_name

+ Custom Middleware Class (Nov. 21, 2015, 9:09 p.m.)

Create a file named `middleware.py` in a module and add your middleware like this: from django.shortcuts import render from nespresso.models import Settings class UnderConstruction: def process_request(self, request): settings_ = Settings.objects.all() if settings_ and settings_[0].under_construction: return render(request, 'nespresso/under_construction.html') After defining a middleware, add it to the settings: MIDDLEWARE_CLASSES = MIDDLEWARE_CLASSES + ( 'nespresso.middleware.UnderConstruction', ) -------------------------------------------------------------- Django 2: from django.shortcuts import HttpResponseRedirect from django.urls import reverse class UnderConstructionMiddleWare: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): response = self.get_response(request) # Do the conditions here return HttpResponseRedirect(reverse('under_construction:home')) In settings.py: Add the name to MIDDLEWARE --------------------------------------------------------------

+ Add Action Form to Action (Oct. 13, 2015, 10:18 a.m.)

from django.contrib.admin.helpers import ActionForm from django.contrib import messages class ChangeMembershipTypeForm(ActionForm): MEMBERSHIP_TYPE = ( ('1', _('Gold')), ('2', _('Silver')), ('3', _('Bronze')), ('4', _('Basic')) ) membership_type = forms.ChoiceField(choices=MEMBERSHIP_TYPE, label=_('membership type'), required=False) class CompanyAdmin(admin.ModelAdmin): action_form = ChangeMembershipTypeForm def change_membership_type(self, request, queryset): membership_type = request.POST['membership_type'] queryset.update(membership_type=membership_type) self.message_user(request, _('Successfully updated membership type for selected rows.'), messages.SUCCESS) change_membership_type.short_description = _('Change Membership Type')

+ Admin - Hide action (Oct. 8, 2015, 10:26 a.m.)

class MyAdmin(admin.ModelAdmin): def has_delete_permission(self, request, obj=None): return False def get_actions(self, request): actions = super(MyAdmin, self).get_actions(request) if 'delete_selected' in actions: del actions['delete_selected'] return actions -------------------------------------------------------------------- def get_actions(self, request): actions = admin.ModelAdmin.get_actions(self, request) if request.user.username == settings.SECOND_ADMIN: return [] else: return actions

+ Model - Disable the Add and / or Delete action for a specific model (March 10, 2016, 9:32 p.m.)

def has_add_permission(self, request): perms = admin.ModelAdmin.has_delete_permission(self, request) if request.user.username == settings.SECOND_ADMIN: return else: return perms def has_delete_permission(self, request, obj=None): perms = admin.ModelAdmin.has_delete_permission(self, request) if request.user.username == settings.SECOND_ADMIN: return else: return perms

+ URLS - Redirect (Oct. 6, 2015, 10:57 a.m.)

from django.views.generic import RedirectView url(r'^$', RedirectView.as_view(url='/online-calls/'), name='home'),

+ Send HTML email using send_mail (Sept. 28, 2015, 4:18 p.m.)

from django.template import loader from django.core.mail import send_mail html = loader.render_to_string('nespresso/admin_order_notification.html', {'order': order}) send_mail('Nespresso New Order from - %s' % order.customer.user.get_full_name(), '', 'mail@buynespresso.ir', OrderingEmail.objects.all().values_list('email', flat=True), html_message=html)

+ Admin - Many to Many Inline (Sept. 28, 2015, 9:53 a.m.)

class OrderInline(admin.TabularInline): model = Order.items.through class OrderItemAdmin(admin.ModelAdmin): inlines = [OrderInline] class OrderAdmin(admin.ModelAdmin): list_display = ('customer', 'get_order_url',) exclude = ('items',) inlines = [OrderInline] admin.site.register(OrderItem) admin.site.register(Order, OrderAdmin)

+ Admin - Override User Form (Sept. 15, 2015, 12:43 p.m.)

from django.contrib import admin from django.contrib.auth.admin import UserAdmin from django.contrib.auth.forms import UserChangeForm, UserCreationForm from django import forms from .models import Supervisor class SupervisorChangeForm(UserChangeForm): class Meta(UserChangeForm.Meta): model = Supervisor class SupervisorCreationForm(UserCreationForm): class Meta(UserCreationForm.Meta): model = Supervisor def clean_username(self): username = self.cleaned_data['username'] try: Supervisor.objects.get(username=username) except Supervisor.DoesNotExist: return username raise forms.ValidationError(self.error_messages['duplicate_username']) class SupervisorAdmin(UserAdmin): form = SupervisorChangeForm add_form = SupervisorCreationForm fieldsets = ( (None, {'fields': ('username', 'password')}), ('Personal info', {'fields': ('first_name', 'last_name', 'email')}), ('Permissions', {'fields': ('is_active',)}), (None, {'fields': ('allowed_online_calls',)}), ) exclude = ['user_permission'] admin.site.register(Supervisor, SupervisorAdmin) ------------------------------------------------------------------------------------ If you need to override the form fields: class SupervisorChangeForm(UserChangeForm): def __init__(self, *args, **kwargs): super(UserChangeForm, self).__init__(*args, **kwargs) self.fields['allowed_online_calls'] = forms.ModelMultipleChoiceField( queryset=Choices.objects.filter(choice='customer'), widget=forms.CheckboxSelectMultiple()) class Meta(UserChangeForm.Meta): model = Supervisor

+ Models - Ranges of IntegerFields (Aug. 21, 2015, 8:52 p.m.)

BigIntegerField: A 64 bit integer, much like an IntegerField except that it is guaranteed to fit numbers from -9223372036854775808 to 9223372036854775807 ------------------------------------------------------------- IntegerField: Values from -2147483648 to 2147483647 are safe in all databases supported by Django. ------------------------------------------------------------- PositiveIntegerField: Like an IntegerField, but must be either positive or zero (0). Values from 0 to 2147483647 are safe in all databases supported by Django. The value 0 is accepted for backward compatibility reasons. ------------------------------------------------------------- PositiveSmallIntegerField: Like a PositiveIntegerField, but only allows values under a certain (database-dependent) point. Values from 0 to 32767 are safe in all databases supported by Django. ------------------------------------------------------------- SmallIntegerField: Like an IntegerField, but only allows values under a certain (database-dependent) point. Values from -32768 to 32767 are safe in all databases supported by Django. -------------------------------------------------------------

+ Admin - Adding Action to Export/Download CSV file (Aug. 24, 2015, 11:34 a.m.)

class VirtualOfficeAdmin(admin.ModelAdmin): actions = ['download_csv'] list_display = ('persian_name', 'english_name', 'office_type', 'active') list_filter = ('office_type', 'active') def download_csv(self, request, queryset): import csv from django.http import HttpResponse import StringIO from django.utils.encoding import smart_str f = f = StringIO.StringIO() writer = csv.writer(f) writer.writerow( ["owner", "office type", "persian name", "english name", "cellphone number", "phone number", "address"]) for s in queryset: owner = smart_str(s.owner.get_full_name()) persian_name = smart_str(s.persian_name) # Office Type office_type = s.office_type if office_type == 're': office_type = smart_str(ugettext('Real Estate')) elif office_type == 'en': office_type = smart_str(ugettext('Engineer')) elif office_type == 'ar': office_type = smart_str(ugettext('Architect')) else: office_type = office_type writer.writerow( [owner, office_type, persian_name, s.english_name, '09' + s.owner.username, s.phone_number, s.address]) f.seek(0) response = HttpResponse(f, content_type='text/csv') response['Content-Disposition'] = 'attachment; filename=stat-info.csv' return response download_csv.short_description = _("Download CSV file for selected stats.") --------------------------------------------------------------------------------------------- from django.contrib.admin.helpers import ActionForm from django import forms from django.utils.translation import ugettext_lazy as _ from django.contrib import messages class ChangeMembershipTypeForm(ActionForm): MEMBERSHIP_TYPE = ( ('1', _('Gold')), ('2', _('Silver')), ('3', _('Bronze')), ('4', _('Basic')) ) membership_type = forms.ChoiceField(choices=MEMBERSHIP_TYPE, label=_('membership type'), required=False) class CompanyAdmin(admin.ModelAdmin): action_form = ChangeMembershipTypeForm actions = ['change_membership_type'] def change_membership_type(self, request, queryset): membership_type = request.POST['membership_type'] queryset.update(membership_type=membership_type) self.message_user(request, _('Successfully updated membership type for %d rows') % (queryset.count(),), messages.SUCCESS) change_membership_type.short_description = _('Change Membership Type')

+ Custom Template Tags & FIlters (April 6, 2016, 1 p.m.)

1- Create a module named `templatetags` in an app. 2- Create a py file with a desired name. (I usually choose the app name for this python file name) 3- Write the methods you need, in the python file. 4- There is no need to introduce these methods or files in `settings.py`. ---------------------------------------------------------------------------------------------------- ================= Template Filters Examples ================= from django.template import Library register = Library() @register.filter def trim_value(value): value = str(value) if value.endswith('.0'): return value.replace('.0', '') else: return value ---------------------------------------------------------------------------------------------------- @register.filter def get_decimal(value): if value: import decimal return str(decimal.Decimal('{0:.4f}'.format(value))) else: return '0' ---------------------------------------------------------------------------------------------------- @register.filter def get_minutes(total_seconds): if total_seconds: return round(total_seconds / 60, 2) else: return 0 ---------------------------------------------------------------------------------------------------- @register.filter def get_acd(request): if request: minutes = get_minutes(request.session['total_seconds']) if minutes: return round(minutes / request.session['total_calls'], 2) else: return 0 else: return 0 ---------------------------------------------------------------------------------------------------- @register.filter def round_values(value, digit): if digit and digit.isdigit(): return round(value, int(digit)) else: return value ---------------------------------------------------------------------------------------------------- @register.filter def calculate_currency_rate(value, invoice): from decimal import Decimal if invoice.rate_currency: return round(Decimal(value) * Decimal(invoice.rate), 2) else: return value ---------------------------------------------------------------------------------------------------- ================= Template Tags Examples ================= Important Hint: You can return anything you like from a tag, including a queryset. However, you can't use a tag inside the for tag ; you can only use a variable there (or a variable passed through a filter). from django.template import Library, Node, TemplateSyntaxError, Variable from youstone.models import Ad register = Library() class AdsNode(Node): def __init__(self, usage, position, province): self.usage, self.position, self.province = Variable(usage), Variable(position), Variable(province) def render(self, context): usage = self.usage.resolve(context) position = self.position.resolve(context) province = self.province.resolve(context) ads = Ad.objects.filter(active=True, usage=usage) if position: ads = ads.filter(position=position) if province: print('PROVINCE', province) context['ads'] = ads return '' @register.tag def get_ads(parser, token): try: tag_name, usage, position, province, _as, var_name = token.split_contents() except ValueError: raise TemplateSyntaxError( 'get_ads takes 4 positional arguments but %s were given.' % len(token.split_contents())) if _as != 'as': raise TemplateSyntaxError('get_ads syntax must be "get_ads <usage> <position> <province> as <var_name>."') return AdsNode(usage, position, province) ---------------------------------------------------------------------------------------------------- Then you can use the template tag like this in the template: {% get_ads usage position province as ads %} {% for ad in ads %} {% endfor %} ----------------------------------------------------------------------------------------------------

+ Resize Image (Aug. 9, 2015, 9:04 p.m.)

Create a python module named resize_image.py and copy & paste this snippet: --------------------------------------------------------------------------------------------- from PIL import Image from django.conf import settings def resize_image(sender, instance, created, **kwargs): width = settings.SLIDER_WIDTH height = settings.SLIDER_HEIGHT img = Image.open(instance.image.path) if img.mode != 'RGB': img = img.convert('RGB') img.resize((width, height), Image.ANTIALIAS).save(instance.image.path, format='JPEG') Note that resize() returns a resized copy of an image. It doesn't modify the original. So do not write codes like this: img.resize((width, height), Image.ANTIALIAS) img.save(instance.image.path, format='JPEG') -------------------------------------------------------------------------------------------- In the settings: # Slider Image Size SLIDER_WIDTH = 1000 SLIDER_HEIGHT = 600 --------------------------------------------------------------------------------------------- In models.py: from resize_image import resize_image class Slider(models.Model): pass models.signals.post_save.connect(resize_image, sender=Slider) --------------------------------------------------------------------------------------------

+ Extending User Model using OneToOne relationship (Aug. 5, 2015, 3:13 p.m.)

from django.db.models.signals import post_save from django.conf import settings class Customer(models.Model): user = models.OneToOneField(settings.AUTH_USER_MODEL, unique=True, primary_key=True) def create_customer(sender, instance, created, **kwargs): if created: Customer.objects.get_or_create(user=instance) post_save.connect(create_customer, sender=settings.AUTH_USER_MODEL)

+ Admin - Overriding admin ModelForm (Nov. 30, 2015, 2:19 p.m.)

class MachineCompareForm(forms.ModelForm): def __init__(self, *args, **kwargs): super(MachineCompareForm, self).__init__(*args, **kwargs) self.model_fields = [['field_%s' % title.pk, title.feature, title.pk] for title in CompareTitle.objects.all()] for field in self.model_fields: self.base_fields[field[0]] = forms.CharField(max_length=400, label='%s' % field[1], required=False) self.fields[field[0]] = forms.CharField(max_length=400, label='%s' % field[1], required=False) if self.instance.pk: feature = CompareFeature.objects.filter(machine=self.instance.machine.pk, feature=field[2]) if feature: self.base_fields[field[0]].initial = feature[0].value self.fields[field[0]].initial = feature[0].value def save(self, commit=True): instance = super(MachineCompareForm, self).save(commit=False) for field in self.model_fields: if CompareFeature.objects.filter(machine=self.cleaned_data['machine'], feature=field[2]): CompareFeature.objects.filter(machine=self.cleaned_data['machine'], feature=field[2]).update( feature_id=field[2], machine=self.cleaned_data['machine'], value=self.cleaned_data[field[0]]) else: CompareFeature.objects.create(feature_id=field[2], machine=self.cleaned_data['machine'], value=self.cleaned_data[field[0]]) if commit: instance.save() return instance class Meta: model = MachineCompare exclude = [] class MachineCompareAdmin(admin.ModelAdmin): form = MachineCompareForm def get_form(self, request, obj=None, **kwargs): return MachineCompareForm --------------------------------------------------------------------------------------------- class SpecialPageAdmin(admin.ModelAdmin): list_display = ('company', 'url_name', 'active',) search_fields = ('company__name', 'url_name') form = SpecialPageForm def get_form(self, request, obj=None, **kwargs): return SpecialPageForm class SpecialPageForm(forms.ModelForm): def __init__(self, *args, **kwargs): super(SpecialPageForm, self).__init__(*args, **kwargs) for i in range(1, 16): self.fields['image-%s' % i] = forms.ImageField(label='%s %s' % (_('Image'), i)) self.base_fields['image-%s' % i] = forms.ImageField(label='%s %s' % (_('Image'), i)) class Meta: model = SpecialPage exclude = [] ---------------------------------------------------------------------------------------------

+ Model - Overriding delete method in model (Nov. 28, 2015, 10:59 a.m.)

from django.db.models.signals import pre_delete from django.dispatch.dispatcher import receiver @receiver(pre_delete, sender=MyModel) def _mymodel_delete(sender, instance, **kwargs): print "deleting"

+ Union of querysets (July 20, 2015, 3:44 p.m.)

import itertools result = itertools.chain(qs1, qs2, qs3, qs4) ------------------------------------------------------------------- records = query1 | query2 OR records = (queryset1 | queryset2) -------------------------------------------------------------------

+ Template - nbsp template tag (Replace usual spaces in string by non breaking spaces) (July 9, 2015, 1:15 a.m.)

from django import template from django.utils.safestring import mark_safe register = template.Library() @register.filter() def nbsp(value): return mark_safe("&nbsp;".join(value.split(' '))) ------------------------------------------------------ Usage: {% load nbsp %} {{ user.full_name|nbsp }} OR {{ note.note|nbsp|linebreaksbr }}

+ Views - Delete old uploaded file/image before saving the new one (July 8, 2015, 6:54 p.m.)

import os from django.conf import settings try: os.remove(settings.BASE_DIR + logo.image.name) logo.delete() except (OSError, IOError): pass

+ Admin - list_display with a callable (Jan. 3, 2016, 8:47 a.m.)

class ExcelFile(models.Model): file = models.FileField(_('excel file'), upload_to='excel-files/', validators=[validate_excel_file]) companies = models.ManyToManyField(Company, verbose_name=_('companies'), blank=True) business = models.ForeignKey(BusinessTitle, verbose_name=_('business')) def __str__(self): return '%s' % self.business.title def get_file_name(self): return self.file.name.split('/')[1] get_file_name.short_description = _('File Name') ------------------------------------------------------------------------------------------ class ExcelFileAdmin(admin.ModelAdmin): list_display = ['get_file_name', 'business'] ------------------------------------------------------------------------------------------ def change_order(self): return '<a href="review/">%s</a>' % _('Edit Order') change_order.short_description = _('Edit Order') change_order.allow_tags = True ------------------------------------------------------------------------------------------

+ Admin - Hide fields (July 8, 2015, 12:01 p.m.)

from django.contrib import admin from .models import ExcelFile class ExcelFileAdmin(admin.ModelAdmin): exclude = ['companies'] admin.site.register(ExcelFile, ExcelFileAdmin)

+ Model - Validators (Jan. 27, 2016, 10:33 p.m.)

from django.core.exceptions import ValidationError def validate_excel_file(file): try: xlrd.open_workbook(file_contents=file.read()) except xlrd.XLRDError: raise ValidationError(_('%s is not an Excel File') % file.name) class ExcelFile(models.Model): excel_file = models.FileField(_('excel file'), upload_to='excel-files/', validators=[validate_excel_file]) ------------------------------------------------------------------- from django.core import validators mobile_number = models.CharField( _('mobile number'), blank=True, max_length=11, validators=[ validators.RegexValidator( regex=r'^09[0-9]{9}$', message=_('Please enter a valid mobile number.') ) ] ) -------------------------------------------------------------------

+ Admin - Allow only one instance of object to be created (July 8, 2015, 11:11 a.m.)

def validate_only_one_instance(obj): model = obj.__class__ if model.objects.count() > 0 and obj.id != model.objects.get().id: raise ValidationError( _('Can only create 1 %s instance') % model.__name__ ) class Settings(models.Model): banner = models.ImageField(_('banner'), upload_to='images/machines/settings', help_text=_('The required image size is 960px in 250px.')) def __str__(self): return '%s' % _('Settings') def clean(self): validate_only_one_instance(self) --------------------------- ANOTHER ONE --------------------------------------------- class ExcelFile(models.Model): excel_file = models.FileField(_('excel file'), upload_to='excel-files/', validators=[validate_excel_file]) companies = models.ManyToManyField(Company, verbose_name=_('companies'), blank=True) business = models.ForeignKey(BusinessTitle, verbose_name=_('business')) def __str__(self): return '%s' % self.business.title def clean(self): model = self.__class__ validation_error = _("Can only create 1 %s instance") % self.business.title business = model.objects.filter(business=self.business) # If the user is updating/editing an object if self.pk: if business and self.pk != business[0].pk: raise ValidationError(validation_error) # If the user is inserting/creating an object else: if business: raise ValidationError(validation_error)

+ Django Analytical (June 7, 2015, 3:22 p.m.)

1-easy_install django-analytical 2- INSTALLED_APPS = [ ... 'analytical', ... ] 3-In the base.html {% load analytical %} <!DOCTYPE ... > <html> <head> {% analytical_head_top %} ... {% analytical_head_bottom %} </head> <body> {% analytical_body_top %} ... {% analytical_body_bottom %} </body> </html> 4-Create an account on this site: http://clicky.com/66453175 I have already registered: Username is Mohsen_Hassani and the password MohseN4301 5-There are some javascript codes which should be taken from clicky.com to you template. Those are like: This should be before the </body> </html> tags: <script src="//static.getclicky.com/js" type="text/javascript"></script> <script type="text/javascript">try{ clicky.init(100851091); }catch(e){}</script> <noscript><p><img alt="Clicky" width="1" height="1" src="//in.getclicky.com/100851091ns.gif" /></p></noscript>

+ Templates - Do Mathematic (Jan. 14, 2016, 12:44 p.m.)

http://slacy.com/blog/2010/07/using-djangos-widthratio-template-tag-for-multiplication-division/ Using Django’s widthratio template tag for multiplication & division. I find it a bit odd that Django has a template filter for adding values, but none for multiplication and division. It’s fairly straightforward to add your own math tags or filters, but why bother if you can use the built-in one for what you need? Take a closer look at the widthratio template tag. Given {% widthratio a b c %} it computes (a/b)*c So, if you want to do multiplication, all you have to do is pass b=1, and the result will be a*c. Of course, you can do division by passing c=1. (a=1 would also work, but has possible rounding side effects) Note: The results are rounded to an integer before returning, so this may have marginal utility for many cases. So, in summary: to compute A*B: {% widthratio A 1 B %} to compute A/B: {% widthratio A B 1 %} And, since add is a filter and not a tag, you can always to crazy stuff like: compute A^2: {% widthratio A 1 A %} compute (A+B)^2: {% widthratio A|add:B 1 A|add:B %} compute (A+B) * (C+D): {% widthratio A|add:B 1 C|add:D %}

+ URLS - Allow entering dot (.) in url pattern (Dec. 2, 2014, 8:33 p.m.)

[-\w.]+

+ Change the value of QuerySet (Nov. 18, 2014, 12:47 a.m.)

If you change the value of QuerySet you will get an error: “This QueryDict instance is immutable” So this is how you should change the value of it: (the whole of it or any item inside) mutable = request.POST._mutable request.POST._mutable = True request.session['search_criteria']['region'] = rid request.session.save() request.POST = request.session['search_criteria'] request.POST._mutable = mutable

+ Templates - Conditional Extend (Sept. 22, 2014, 11:15 a.m.)

{% extends supervising|yesno:"supervising/tasks.html,desktop/tasks_list.html" %} {% extends variable %} uses the value of variable. If the variable evaluates to a string, Django will use that string as the name of the parent template. If the variable evaluates to a Template object, Django will use that object as the parent template.

+ Adding CSS class in a ModelForm (Sept. 12, 2014, 11:45 p.m.)

self.fields['specie'].widget.attrs['class'] = 'autocomplete'

+ Models - Overriding save method (Aug. 21, 2014, 11:33 a.m.)

from tastypie.utils.timezone import now from django.contrib.auth.models import User from django.db import models from django.utils.text import slugify class Entry(models.Model): user = models.ForeignKey(User) pub_date = models.DateTimeField(default=now) title = models.CharField(max_length=200) slug = models.SlugField() body = models.TextField() def __unicode__(self): return self.title def save(self, *args, **kwargs): # For automatic slug generation. if not self.slug: self.slug = slugify(self.title)[:50] return super(Entry, self).save(*args, **kwargs)

+ auto_now / auto_now_add (Aug. 21, 2014, 11:32 a.m.)

created_at = models.DateTimeField(_('created at'), auto_now_add=True) updated_at = models.DateTimeField(_('updated at'), auto_now=True) ------------------------------------------------------------------------------ class Blog(models.Model): title = models.CharField(max_length=100) added = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) auto_now_add tells Django that when you add a new row, you want the current date & time added. auto_now tells Django to add the current date & time will be added EVERY time the record is saved. ------------------------------------------------------------------------------ auto_now Automatically set the field to now every time the object is saved. Useful for “last-modified” timestamps. The field is only automatically updated when calling Model.save(). The field isn’t updated when making updates to other fields in other ways such as QuerySet.update(), though you can specify a custom value for the field in an update like that. ------------------------------------------------------------------------------ auto_now_add Automatically set the field to now when the object is first created. Useful for the creation of timestamps. Even if you set a value for this field when creating the object, it will be ignored. If you want to be able to modify this field, set the following instead of auto_now_add=True: - For DateField: default=date.today -> from datetime.date.today() - For DateTimeField: default=timezone.now -> from django.utils.timezone.now() ------------------------------------------------------------------------------

+ Query - Call a field name by dynamic values (Aug. 21, 2014, 11:28 a.m.)

properties = Properties.objects.filter(**{'%s__age_status' % p_type: request.POST['age_status']})

+ Settings - Set a settings for shell (Aug. 21, 2014, 11:26 a.m.)

DJANGO SETTINGS MODULE for shell: python manage.py shell --settings=nimkatonline.settings -------------------------------------------------------------------------- import os os.environ.setdefault("DJANGO_SETTINGS_MODULE", "nimkatonline.settings") --------------------------------------------------------------------------

+ Admin - Deleting the file/image on deleting an object (Aug. 21, 2014, 11:24 a.m.)

1-Create a file named `clean_up.py` with the following contents: import os from django.conf import settings def clean_up(sender, instance, *args, **kwargs): for field in sender._meta.get_fields(): field_types = ['FileBrowseField', 'ImageField', 'FileField'] if field.__class__.__name__ in field_types: try: os.remove(settings.MEDIA_ROOT + str(getattr(instance, field.name))) except (OSError, IOError): pass -------------------------------------------------------------------------------------------- 2- Open the models.py file: Import the `clean_up` function from the `clean_up` module and add the following line at the bottom of each model having a FileField or ImageField or FileBrowseField: models.signals.post_delete.connect(clean_up, sender=Ads)

+ URLS - Redirect to a URL in urls.py (Aug. 21, 2014, 11:23 a.m.)

from django.views.generic import RedirectView from django.core.urlresolvers import reverse_lazy (r'^one/$', RedirectView.as_view(url='/another/')), OR url(r'^some-page/$', RedirectView.as_view(url=reverse_lazy('my_named_pattern'))),

+ Forms - Overriding and manipulating fields (Nov. 30, 2015, 11:05 a.m.)

class CheckoutForm(forms.ModelForm): def __init__(self, request, *args, **kwargs): super(CheckoutForm, self).__init__(*args, **kwargs) self.request = request print(request.user) class Meta: model = Address exclude = ('fax_number',) ------------------------------------------------- class ProfileForm(forms.Form): required_css_class = 'required' ------------------------------------------------- def __init__(self, request, *args, **kwargs): super(InstituteRegistrationForm, self).__init__(*args, **kwargs) self.request = request ------------------------------------------------- if request.user.cellphone: self.fields['cell_phone_number'].widget.attrs['readonly'] = 'true' ------------------------------------------------- if request.user.email: self.fields['email'].widget.attrs['readonly'] = 'true' ------------------------------------------------- self.fields['city'].queryset = City.objects.filter(province__allow_delete=False) self.fields['city'].initial = '1' ------------------------------------------------- self.fields['first_name'].required = True self.fields['first_name'].widget.attrs['required'] = True ------------------------------------------------- for field in self.fields.values(): field.widget.attrs['required'] = True field.required = True ------------------------------------------------- self.fields['national_team'].empty_label = None ------------------------------------------------- self.fields['allowed_online_calls'] = forms.ModelMultipleChoiceField( queryset=Choices.objects.filter(choice='customer'), widget=forms.CheckboxSelectMultiple()) ------------------------------------------------- Hide a field: self.fields['state'].widget = forms.HiddenInput() ------------------------------------------------- class UpdateShare(forms.ModelForm): class Meta: model = ManualEntries exclude = ['dt'] widgets = { 'description': forms.Textarea(attrs={'rows': 3}), } ------------------------------------------------- class QuestionnaireForm(forms.ModelForm): class Meta: model = Questionnaire fields = ['code', 'title', 'grades', 'description', 'enable'] widgets = { 'grades': forms.CheckboxSelectMultiple } ------------------------------------------------- self.fields['amount'].help_text = 'AAA' ------------------------------------------------- Change ModelChoiceField items text: self.fields['parent'].label_from_instance = lambda obj: obj.other_name ------------------------------------------------- def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) ------------------------------------------------- When passing instance in render, like: {'form': ProfileForm(instance=request.user)} if you needed to change values in __init__ of ModelForm use "self.initial": self.initial['first_name'] = 'aa' ------------------------------------------------- class CertificateForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) date = self['date'].value() if date and not isinstance(date, str): self.initial['date'] = '-'.join([str(x) for x in list(get_persian_date(date).values())]) ------------------------------------------------- Change max_length validator error message: caller_id.validators[-1].message = _('The text is too long.') ------------------------------------------------- Get the label of a choice in ChoiceField dict(form.fields['city'].choices)[data['city']] ------------------------------------------------- Validate a form field: class CDRSearchForm(forms.Form): from_date = forms.CharField(label=_('from date'), max_length=50) to_date = forms.CharField(label=_('to date'), max_length=50) def clean_to_date(self): from_date = self.cleaned_data['from_date'] to_date = self.cleaned_data['to_date'] return self.cleaned_data['to_date'] -------------------------------------------------