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

Auto-fill talk with publication info #1200

Open
jonfroehlich opened this issue Oct 16, 2024 · 3 comments
Open

Auto-fill talk with publication info #1200

jonfroehlich opened this issue Oct 16, 2024 · 3 comments

Comments

@jonfroehlich
Copy link
Collaborator

When you add a talk or video from the publication admin interface, we should auto-fill the info.

image image
@jonfroehlich
Copy link
Collaborator Author

jonfroehlich commented Oct 16, 2024

Maybe some possibilities here. Two approaches: (1) use GET by pasing in variables to Talk; (2) using get_form

https://stackoverflow.com/questions/529890/django-how-to-prepopulate-admin-form-fields

Gemini suggets get_form. I want to figure this out without adding a different talk button like Gemini suggests.

Here's how you can achieve your goal of pre-populating the Talk form fields with data from the Publication in the Django admin interface:

1. Modify the Talk model admin class:

Instead of opening a blank Talk admin form, we will customize the Talk admin class to pre-populate the fields based on the selected publication.

from django.contrib import admin
from .models import Talk, Publication

class TalkAdmin(admin.ModelAdmin):
  # Pre-populate specific fields based on the selected Publication
  def formfield_for_foreignkey(self, db_field, request, **kwargs):
    if db_field.name == 'publication':
      kwargs['queryset'] = Publication.objects.filter(pk=request.GET.get('publication_id'))
    return super().formfield_for_foreignkey(db_field, request, **kwargs)

  def formfield_for_manytomanyfield(self, db_field, request, **kwargs):
    # This can be used to pre-populate authors field if needed
    # ...
    return super().formfield_for_manytomanyfield(db_field, request, **kwargs)

  def get_form(self, request, obj=None, **kwargs):
    form = super().get_form(request, obj, **kwargs)
    # Access the selected publication through request.GET
    publication = Publication.objects.get(pk=request.GET.get('publication_id'))
    if publication:
      # Pre-populate specific fields
      form.initial['title'] = publication.book_title
      form.initial['date'] = publication.date
      form.initial['forum_name'] = publication.forum_name
      form.initial['forum_url'] = publication.forum_url
      form.initial['location'] = publication.location
      # ... (pre-populate other relevant fields)
    return form

admin.site.register(Talk, TalkAdmin)

Explanation:

  • formfield_for_foreignkey method checks if the field being edited is the publication field. If yes, it filters the queryset to only include the publication with the pk value from the URL parameter publication_id. This ensures only the selected publication is available for selection.
  • get_form method retrieves the selected publication based on the publication_id in the URL parameter. It then iterates through the desired fields and sets them in the form's initial dictionary using the publication's data. This pre-populates the form fields when displayed.

2. Modify the Publication admin interface:

In the Publication admin form, we need to modify the talk field to include a link that opens the pre-populated Talk admin form.

from django.urls import reverse

class PublicationAdmin(admin.ModelAdmin):
  # ... other fields

  talk = admin.ForeignKeyModelChoiceField(
    'talk',
    on_delete=models.DO_NOTHING,
    blank=True,
    null=True,
    related_name='publications',
  )

  def talk_link(self, obj):
    if obj.talk_id:
      url = reverse('admin:your_app_name_talk_change', args=[obj.talk_id])
      return f'<a href="{url}">Edit Talk</a>'
    return '-'

  talk_link.short_description = 'Talk'
  talk_link.allow_tags = True

  # ... other methods

admin.site.register(Publication, PublicationAdmin)

Explanation:

  • We define a custom method talk_link that takes a publication object as input.
  • If the publication has an associated talk (talk_id), it generates a URL using reverse that points to the edit view of the Talk admin with the talk's ID.
  • The method returns an HTML anchor tag with the URL and text "Edit Talk".
  • In the PublicationAdmin class, we define talk as an admin.ForeignKeyModelChoiceField and assign the talk_link method to the short_description property. This displays the generated link instead of the default text representation of the foreign key field.

Remember:

  • Replace your_app_name with the actual name of your app where the Talk model resides.

This approach allows you to pre-populate the Talk form with data from the selected Publication in the Django admin interface, making the process more efficient and consistent.

@jonfroehlich
Copy link
Collaborator Author

OK, my solution is quite fun and interesting combining some basic JavaScript that passes the pub ID via GET param to the talk admin page. And then we have the following in TalkAdmin

def get_changeform_initial_data(self, request):
        # _logger.debug("******* get_changeform_initial_data ***********")
        # _logger.debug(f"request is {request} and request.GET is {request.GET}")

        initial = super().get_changeform_initial_data(request)
        publication_id = request.GET.get('publication_id')
        if publication_id:
            _logger.debug(f"publication_id is {publication_id}")
            try:
                publication = Publication.objects.get(id=publication_id)
                initial.update({
                    'title': publication.title,
                    'date': publication.date,
                    'forum_name': publication.forum_name,
                    'forum_url': publication.forum_url,
                    'location': publication.location,

                })
                # For ManyToManyField, set the initial data as a list of IDs
                initial['authors'] = publication.authors.all().values_list('id', flat=True)
                initial['projects'] = publication.projects.all().values_list('id', flat=True)
                initial['project_umbrellas'] = publication.project_umbrellas.all().values_list('id', flat=True)
                initial['keywords'] = publication.keywords.all().values_list('id', flat=True)
            
                if publication.pub_venue_type == PubType.CONFERENCE:
                    initial['talk_type'] = TalkType.CONFERENCE_TALK

            except Publication.DoesNotExist:
                pass
        return initial

@jonfroehlich
Copy link
Collaborator Author

Reopening until we test on -test server

@jonfroehlich jonfroehlich reopened this Oct 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant