Skip to content

Instantly share code, notes, and snippets.

@jacklinke
Created January 13, 2021 14:41
Show Gist options
  • Save jacklinke/168b6c014cefffefb04c993b125f8dab to your computer and use it in GitHub Desktop.
Save jacklinke/168b6c014cefffefb04c993b125f8dab to your computer and use it in GitHub Desktop.

Revisions

  1. jacklinke created this gist Jan 13, 2021.
    197 changes: 197 additions & 0 deletions cheatsheet.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,197 @@
    import uuid
    from django.db import models
    # Use the import below instead, if using GeoDjango fields
    # from django.contrib.gis.db import models
    from django.utils.translation import ugettext_lazy as _

    from django.contrib.postgres.fields import (
    ArrayField,
    CICharField,
    CIEmailField,
    CITextField,
    HStoreField,
    IntegerRangeField,
    BigIntegerRangeField,
    DecimalRangeField,
    DateTimeRangeField,
    DateRangeField,
    )


    def file_directory_path(instance, filename):
    # file will be uploaded to MEDIA_ROOT/my_files/{id}/{year}/{month}/{filename}
    return f"my_files/{instance.id}/{timezone.now().date().strftime('%Y/%m')}/{filename}"


    def create_rand_value(app_label, model_name, prefix=None, suffix_len=10):
    """
    Just an example function, used to demonstrate overriding save()
    It generates an easily readable, unique string
    """

    code = ""

    if prefix is not None:
    code = code.join(prefix).join("-")

    while True:
    code = code.join(random.SystemRandom().choice("23456789BCDFGHJKMNPQRSTVWXYZ") for _ in range(suffix_len))
    Model = apps.get_model(app_label=app_label, model_name=model_name)

    try:
    present = Model.objects.first()
    except Model.DoesNotExist:
    present = None

    if present is not None:
    if not Model.objects.filter(code=code).exists():
    return code


    # https://docs.djangoproject.com/en/3.1/topics/db/managers/#from-queryset
    class MyModelQuerySet(models.QuerySet):
    """Used when we need to return a queryset that has been filtered in some way"""
    def manager_and_queryset_method(self):
    return


    class MyModelManager(models.Manager):
    """Used when we need a table-level method that does NOT return a queryset"""
    def manager_only_method(self):
    return


    CombinedMyModelManager = MyModelManager.from_queryset(MyModelQuerySet)


    class MyModel(models.Model):
    """Comment"""

    class CompanyType(models.TextChoices):
    PUBLIC_LIMITED_COMPANY = 'PLC', _('Public Limited Company')
    PRIVATE_COMPANY_LIMITED = 'LTD', _('Private Company limited by shares')
    LIMITED_LIABILITY_PARTNERSHIP = 'LLP', _('Limited Liability Partnership')
    __empty__ = _('(Unknown)')

    # https://docs.djangoproject.com/en/3.1/ref/models/fields/
    boolean_field = models.BooleanField(_("Boolean"), default=False)
    char_field = models.CharField(_("Character"), max_length=100, blank=True)
    char_field_choice = models.CharField(_("Character Choices"), choices=CompanyType.choices, default=CompanyType.__empty__, max_length=100, blank=True)
    date_field = models.DateField(_("Date"), null=True, blank=True)
    datetime_field = models.DateTimeField(_("DateTime"), null=True, blank=True)
    decimal_field = models.DecimalField(_("Decimal"), max_digits=5, decimal_places=2, null=True)
    duration_field = models.DurationField(_("Duration"), )
    email_field = models.EmailField(_("Email"), max_length=254, blank=True)
    file_field = models.FileField(_("File"), upload_to=file_directory_path, max_length=100)
    float_field = models.FloatField(_("Float"), null=True)
    generic_ip_address_field = models.GenericIPAddressField(_("Generic IP"), protocol='both', unpack_ipv4=False, null=True) # 'both', 'IPv4' or 'IPv6'
    image_field = models.ImageField(_("Image"), upload_to=file_directory_path, height_field=None, width_field=None, max_length=100)
    integer_field = models.IntegerField(_("Number"), null=True)
    json_field = models.JSONField(_("JSONField"), default=dict)
    pos_int_field = models.PositiveIntegerField(_("Positive Integer"), )
    pos_small_int_field = models.PositiveSmallIntegerField(_("Positive Small Integer"), )
    slug_field = models.SlugFiels(_("Slug"), max_length=50, blank=True)
    small_int_field = models.SmallIntegerField(_("Small Integer"), )
    text_field = models.TextField(_("Text"), blank=True)
    time_field = models.TimeField(_("Time"), null=True, blank=True)
    url_field = models.URLField(_("URL"), max_length=200,)
    uuid_field = models.UUIDField(_("UUID"), default=uuid.uuid4)

    # Relationships
    # https://docs.djangoproject.com/en/3.1/ref/models/fields/#module-django.db.models.fields.related
    oto = models.OneToOneField(AA, on_delete=models.CASCADE, null=True, blank=True)
    fk = models.ForeignKey(BB, on_delete=models.CASCADE, related_name="xxs", null=True, blank=True)
    mtm = models.ManyToManyField(CC, blank=True)

    # Auto-date fields
    # https://docs.djangoproject.com/en/3.1/ref/models/fields/#datefield
    created = models.DateTimeField(_("DateTime Created"), auto_now_add=True, help_text=_("When this item was created"))
    modified = models.DateTimeField(_("DateTime Modified"), auto_now=True, help_text=_("When this item last updated"))

    # Postgres-specific range fields
    # https://docs.djangoproject.com/en/3.1/ref/contrib/postgres/fields/
    integer_range_field = IntegerRangeField(_("IntegerRange"))
    big_integer_range_field = BigIntegerRangeField(_("BigIntegerRange"))
    decimal_range_field = DecimalRangeField(_("DecimalRange"))
    date_time_range_field = DateTimeRangeField(_("DateTimeRange"))
    date_range_field = DateRangeField(_("DateRange"))

    # GeoDjango fields
    # https://docs.djangoproject.com/en/3.1/ref/contrib/gis/model-api/
    point = models.PointField(srid=4326)
    multi_point = models.MultiPointField()
    polygon = models.PolygonField()
    multi_polygon = models.MultiPolygonField()
    linestring = models.LineStringField()
    multi_linestring = models.MultiLineStringField()
    geometry_collection = models.GeometryCollectionField()
    raster = models.RasterField()

    objects = CombinedMyModelManager()

    class Meta:
    # https://docs.djangoproject.com/en/3.1/ref/models/options/
    verbose_name = _("My Model")
    verbose_name_plural = _("My Models")
    # abstract = True # https://docs.djangoproject.com/en/3.1/topics/db/models/#abstract-base-classes
    # proxy = True # https://docs.djangoproject.com/en/3.1/topics/db/models/#proxy-models

    db_table = 'my_model'

    # Specifies the default field(s) to use in your model Manager’s latest() and earliest() methods.
    get_latest_by = ['-datetime_field']

    # The default ordering for the object, for use when obtaining lists of objects:
    ordering = ['-datetime_field']

    unique_together = [
    ['char_field', 'slug_field']
    ]
    index_together = [
    ["created", "char_field"],
    ]

    # https://docs.djangoproject.com/en/3.1/ref/models/indexes/
    indexes = [
    models.Index(fields=['char_field', 'text_field']),
    models.Index(fields=['url_field'], name='url_field_idx'),
    ]

    # https://docs.djangoproject.com/en/3.1/ref/models/constraints/
    constraints = [
    models.CheckConstraint(check=models.Q(integer_field__gte=18), name='integer_gte_18'),
    models.UniqueConstraint(fields=['created', 'slug_field'], name='unique_slug_created'),
    models.UniqueConstraint(
    fields=['fk'],
    condition=Q(char_field_choice=CompanyType.LIMITED_LIABILITY_PARTNERSHIP),
    name='unique_llc_for_fk'
    ),
    ]

    def __str__(self):
    # https://docs.djangoproject.com/en/3.1/ref/models/instances/#str
    return f'{self.char_field} {self.char_field}'

    def save(self, *args, **kwargs):
    # https://docs.djangoproject.com/en/3.1/topics/db/models/#overriding-model-methods
    if not self.pk: # this will ensure that the object is new
    self.slug_field = create_rand_value(
    app_label=self._meta.app_label,
    model_name=self.__class__.__name__,
    prefix="",
    suffix_len=10
    )
    super().save(*args, **kwargs)

    def get_absolute_url(self):
    # https://docs.djangoproject.com/en/3.1/ref/models/instances/#get-absolute-url
    from django.urls import reverse
    return reverse('people.views.details', args=[str(self.id)])

    @property
    # https://docs.djangoproject.com/en/3.1/glossary/#term-property
    def char_slug(self):
    return self.char_field.lower().replace(' ','-')

    def process_invoices(self):
    do_something()