2

I have an extended admin model that creates action buttons. I have created a view to do pretty much the same thing. I have used tables2 and everything is just fine except for the actions column. I cannot find a way to generate the same button in the table. Is there a way to do this at all?

tables.py

from .models import Ticket
import django_tables2 as tables
'''from .admin import river_actions, create_river_button'''

class TicketTable(tables.Table):

    class Meta:
        model=Ticket
        template_name='django_tables2/table.html'
        fields = ('id','subject','request_type','material_type','productline','business','measurement_system',
            'created_at','updated_at','status','river_action','project') # fields to display
        attrs = {'class': 'mytable'}
        '''attrs = {"class": "table-striped table-bordered"}'''
        empty_text = "There are no tickets matching the search criteria..."

admin.py (the part that includes the model etc)

# Define a new User admin to get client info too while defining users
class UserAdmin(BaseUserAdmin):
    inlines = (UserExtendInline, )


def create_river_button(obj,proceeding):
        return '''
            <input
                type="button"
                style=margin:2px;2px;2px;2px;"
                value="%s"
                onclick="location.href=\'%s\'"
                />
        '''%(proceeding.meta.transition,
             reverse('proceed_ticket',kwargs={'ticket_id':obj.pk, 'next_state_id':proceeding.meta.transition.destination_state.pk})
             )

class TicketAdmin(admin.ModelAdmin):

    list_display=('id','client','subject','request_type','material_type','productline','business','measurement_system', \
                  'created_at','updated_at','created_by','status','river_actions')

    #list_display_links=None if has_model_permissions(request.user,Ticket,['view_ticket'],'mmrapp')==True else list_display

    #list_display_links=list_display #use None to remove all links, or use a list to make some fields clickable
    #search_fields = ('subject','material_type')
    list_filter=[item for item in list_display if item!='river_actions'] #exclude river_actions since it is not related to a field and cannot be filtered

    #Using fieldset, we can control which fields should be filled by the user in the ADD method. This way, created_by will be the
    #logged in user and not a drop down choice on the admin site
    fieldsets = [
        (None, { 
            'fields': ('client','subject','description','request_type','material_type', \
                       'productline','business','measurement_system', 'project') 
            } ), #to make some field appear horizontal, put them into a []
    ]

    formfield_overrides = {
        models.CharField: {'widget': TextInput (attrs={'size':'40'})},
        models.TextField: {'widget': Textarea(attrs={'rows':4, 'cols':80})},}


    def get_list_display(self, request):
        self.user=request.user
        return super(TicketAdmin,self).get_list_display(request)


    def river_actions(self,obj):
        content=""
        for proceeding in obj.get_available_proceedings(self.user):
            content+=create_river_button(obj, proceeding)

        return content

    river_actions.allow_tags=True

    #override save_model method to save current user since it is not on the admin page form anymore
    def save_model(self, request, obj, form, change):
        if not change:
            # the object is being created and not changed, so set the user
            obj.created_by = request.user
        obj.save()

views.py

def display_tickets(request):
    table = TicketTable(Ticket.objects.all())
    RequestConfig(request).configure(table)
    '''table = CustomerTable(Customer.objects.filter(self.kwargs['company']).order_by('-pk'))'''
    return render(request,'mmrapp/ticket_display.html',{'table':table})

buttons created in admin page: enter image description here

table created using tables2 in views missing buttons: enter image description here

Ibo
  • 4,081
  • 6
  • 45
  • 65

1 Answers1

1

You must pass empty_values=() to the column, because by default, django-tables2 only renders the column if the value is not contained in empty_values for that column.

import django_tables2 as tables

from .admin import river_actions, create_river_button
from .models import Ticket


class TicketTable(tables.Table):
    river_action = tables.Column(empty_values=())

    class Meta:
        model=Ticket
        template_name='django_tables2/table.html'
        fields = (
            'id', 'subject', 'request_type', 'material_type', 'productline', 'business', 'measurement_system',
            'created_at', 'updated_at', 'status', 'river_action', 'project'
        ) # fields to display
        attrs = {'class': 'mytable'}
        empty_text = "There are no tickets matching the search criteria..."

    def render_river_action(self, record):
        return create_river_button(record, ...)

This is also documented as Table.render_foo methods

Jieter
  • 4,101
  • 1
  • 19
  • 31
  • Thanks for the answer. I tried and it seems sth is not working. I did not get a specific error because it cannot be rendered. I received `This site can’t be reached 127.0.0.1 refused to connect.`. Those 3 dots you have put is a part of the code or you wanted me to replace it with sth? – Ibo Aug 14 '18 at 17:17
  • Yes, I was not sure what the second argument was supposed to be exactly, you need to replace that with the proper argument. – Jieter Aug 14 '18 at 18:17
  • first off, we created `render_river_action` but we never used it anywhere, and `create_river_button` has been defined in `admin.py` you can have look, do we need to pass the same objects or we should be fine if we just use `record`? – Ibo Aug 14 '18 at 18:20
  • I am new to django so excuse me if I look clueless! – Ibo Aug 14 '18 at 18:33
  • I found out that importing `river_actions` was the problem and I removed it. I tried with no extra argument = `return create_river_button(record)` and in the column it returns `None` for all the rows. – Ibo Aug 14 '18 at 18:49
  • also I tried `return create_river_button(record, obj, proceeding)` while I imported `admin`, but it is still the same. I even replaced the `create_button` function from `admin.py` in `tables.py`, but nothing changed. Do we need to do sth in the templates? why does it return `None` instead of the buttons? – Ibo Aug 14 '18 at 19:28
  • Can you try to just return a static string from the `render_river_action` method? – Jieter Aug 15 '18 at 07:54
  • I tried `return "hello"` in the method, but it is still showing `None` in the table, so the method is not working – Ibo Aug 15 '18 at 16:40
  • should we use `TemplateColumn`? I saw sth here, but I cannot figure out how to do it on my side using a methdo that I already have in admin, we can re-define the button in `tables.py` too if it worked I don't mind. https://stackoverflow.com/questions/12192004/django-tables2-add-button-per-row – Ibo Aug 15 '18 at 16:41
  • do you think I should create the table myself and forget about `tables2`? – Ibo Aug 16 '18 at 17:11
  • No, I don't, but it's hard to debug pieces of code I cannot see. So it might be worth it to update the question with what you have now, or start a new one, in order for me / us to see what's going on. – Jieter Aug 16 '18 at 19:51
  • is it possible for you to debug if I deployed a demo or that won't help much too? – Ibo Aug 16 '18 at 20:35