Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fields that are ForeignKeys to other models render as pk, not as the string representation of that model #41

Open
joshuadavidthomas opened this issue Feb 7, 2024 · 6 comments · May be fixed by #56

Comments

@joshuadavidthomas
Copy link
Contributor

In the object_list and object_detail templatetags, a field's value is rendered using the field's value_to_string method. On fields that are a ForeignKey to another model, this just renders that model's primary key, not the string representation of the model.

Before:

image
image

If you change how the field's value is rendered by getting the attribute and rendering to string, you can get that related model's string representation.

After:

image
image

See this relevant commit for what this would look like.

@carltongibson
Copy link
Owner

Hey @joshuadavidthomas — yes, makes sense. Is this something you'd do a PR for?

@wassafshahzad
Copy link

I this open to take ?

@carltongibson
Copy link
Owner

@wassafshahzad Yes, great.

Please keep the fix to just this issue here, not blending with #39 and #40, as the linked commit does. (I need to look at those separately.

A test case for the change will be needed.

Thanks! Let me know if you get stuck anywhere.

@nanuxbe
Copy link
Contributor

nanuxbe commented Jun 15, 2024

@carltongibson any specific reason you didn't use
str(getattr(object, f)) instead of object._meta.get_field(f).value_to_string(object) here: https://github.com/carltongibson/neapolitan/blame/main/src/neapolitan/templatetags/neapolitan.py#L59C17-L59C66 ?

It looks to me like a pretty simple fix but I'm fearing it's too simple

@carltongibson
Copy link
Owner

No real reason. It just didn't occur to me when I was bashing it together.

This is probably a change we should make yes.

There are a couple of related issues about the table generation and the actions links that likely go together. The reason they're still here is I didn't get a chance to totally think them through yet, but happy to have input.

joshuadavidthomas added a commit to joshuadavidthomas/neapolitan that referenced this issue Jul 24, 2024
@PARTHIB-DEB
Copy link

PARTHIB-DEB commented Jul 24, 2024

A possible solution for rendering Foreignkey as PK #41

Hey , I am Parthib. Saw the project architechture and tried to give an approach to solve -

def value_to_string(obj:object):
    '''
    If you want to get the Foreignkey or Primary key of another model. Then -
    1. You have to define this function separately
    2. Here 'obj' is that Object whose Primary Key is Foreign key for the current Model
    3. This function will return the Foreign-key in the 'fields' of 'object_list' function
    
    But where is the models.py file, so I just gave the possible way to solve the problem
    '''
# naepolitan.py

from django import template
from django.utils.safestring import mark_safe

from neapolitan.views import Role

register = template.Library()


def action_links(view, object):
    actions = [
        (url, name)
        for url, name in [
            (Role.DETAIL.maybe_reverse(view, object), "View"),
            (Role.UPDATE.maybe_reverse(view, object), "Edit"),
            (Role.DELETE.maybe_reverse(view, object), "Delete"),
        ] if url is not None
    ]
    links = [f"<a href='{url}'>{anchor_text}</a>" for url, anchor_text in actions]
    return mark_safe(" | ".join(links))


@register.inclusion_tag("neapolitan/partial/detail.html")
def object_detail(object, fields):
    """
    Renders a detail view of an object with the given fields.

    Inclusion tag usage::

        {% object_detail object fields %}

    Template: ``neapolitan/partial/detail.html`` - Will render a table of the
    object's fields.
    """

    def iter():
        for f in fields:
            mf = object._meta.get_field(f)
            yield (mf.verbose_name, mf.value_to_string(object))

    return {"object": iter()}

def value_to_string(obj:object):
    '''
    If you want to get the Foreignkey or Primary key of another model. Then -
    1. You have to define this function separately
    2. Here 'obj' is that Object whose Primary Key is Foreign key for the current Model
    3. This function will return the Foreign-key in the 'fields' of 'object_list' function
    
    But where is the models.py file, so I just gave the possible way to solve the problem
    '''


@register.inclusion_tag("neapolitan/partial/list.html")
def object_list(objects, view):
    """
    Renders a list of objects with the given fields.

    Inclusion tag usage::

        {% object_list objects view %}

    Template: ``neapolitan/partial/list.html`` — Will render a table of objects
    with links to view, edit, and delete views.
    """

    fields = view.fields
    headers = [objects[0]._meta.get_field(f).verbose_name for f in fields]
    object_list = [
        {
            "object": object,
            "fields": [
                value_to_string(object) for f in fields
            ],
            "actions": action_links(view, object),
        }
        for object in objects
    ]
    return {
        "headers": headers,
        "object_list": object_list,
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants