Skip to content

Instantly share code, notes, and snippets.

@jamesbrobb
Created October 4, 2023 15:18
Show Gist options
  • Save jamesbrobb/255d3d0465147b45cd6f46d6eb36fdd5 to your computer and use it in GitHub Desktop.
Save jamesbrobb/255d3d0465147b45cd6f46d6eb36fdd5 to your computer and use it in GitHub Desktop.

Revisions

  1. jamesbrobb created this gist Oct 4, 2023.
    49 changes: 49 additions & 0 deletions linkify.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,49 @@
    from typing import Optional

    from django.contrib import admin
    from django.contrib.contenttypes.models import ContentType
    from django.db.models import ManyToManyField, ForeignKey, Model
    from django.urls import reverse
    from django.utils.html import format_html


    def create_link(linked_obj, app_label: str, label_prop: Optional[str] = None) -> str:
    linked_content_type = ContentType.objects.get_for_model(linked_obj)
    model_name = linked_content_type.model
    view_name = f"admin:{app_label}_{model_name}_change"
    link_url = reverse(view_name, args=[linked_obj.pk])
    return "<a href='%s'>%s</a>" % (link_url, getattr(linked_obj, label_prop) if label_prop else linked_obj)


    def linkify(field_name: str, label_prop: Optional[str] = None, short_description: Optional[str] = None, as_html_list: bool = False):
    def _linkify(obj: Model):
    content_type = ContentType.objects.get_for_model(obj)
    app_label = content_type.app_label
    field_type = obj._meta.get_field(field_name)
    items = None

    if isinstance(field_type, ManyToManyField):
    items = list(getattr(obj, field_name).all())
    elif isinstance(field_type, ForeignKey):
    items = [getattr(obj, field_name)]
    else:
    print(f'field_name {field_name} is not ManyToManyField or ForeignKey')

    links = [create_link(itm, app_label, label_prop) for itm in items if itm is not None]

    if len(links) > 1:
    if as_html_list:
    html = "<ul>"
    for link in links:
    html += f'<li>{link}</li>'
    html += "</ul>"
    else:
    html = ", ".join(links)
    else:
    html = links[0]

    return format_html(html)

    _linkify.short_description = [short_description, field_name.replace("_", " ").capitalize()][short_description is None]

    return _linkify