Display relevant records from many to many in djan

2019-08-10 03:03发布

OK, so I have an Item class that has a many-to-many attribute to User through a 'Roles' class. I am trying to create a django-table for the Items such that out of any of the roles attached to the item, if the current User is attached to that role, the name of the role displays. I hope that makes some sort of sense. Here's what I have so far, which I didn't really expect to work because I don't see how the Table class can know about the request/user. I'm stuck.

models.py

class Item(models.Model):
    name    = models.CharField(max_length=255)
    owner   = models.ForeignKey(User, related_name='Owner')
    roles   = models.ManyToManyField(User, through='Role')
class Role(models.Model):
    role_type   = models.ForeignKey(RoleType)
    user        = models.ForeignKey(User)
    item        = models.ForeignKey(Item)

tables.py

class OwnedTable(tables.Table):
    roles = tables.Column()
    user = request.user
    def render_roles(self):
        for role in roles:
            if role.User == user:
                return role.role_type
            else:
                pass

    class Meta:
        model = Item
        attrs = {"class": "paleblue"}

        fields = ('id', 'name', 'owner', 'roles')

3条回答
做自己的国王
2楼-- · 2019-08-10 03:40

Another solution is shown on https://github.com/bradleyayers/django-tables2/issues/156, which worked for me after some adjustments for my setup.

Given that a Person would have an M2M to Contacts, and you want to display all contacts for that Person in django-tables2, then the following would do:

class PersonTable(tables.Table):
    person_contacts = tables.Column(accessor="contacts", verbose_name="Contacts")

    def render_person_contacts(self, value, table):
        clist = ""
        cfirst = True

        conts = list(value.all())

        for c in conts:
            if not cfirst:
                clist += "<br />"
            else:
                cfirst = False

            print c.id
            uri = reverse('cont_detail', kwargs={'pk': c.id})
            clist += '<a href="' + uri + '">' + c.name + '</a>' + ' (' + c.relation + ')'

        return mark_safe(clist)

You basically add a column with a non-existent name, set the accessor to the M2M field name, then call render_<newly_added_column> where you obtain what you need from value.

查看更多
我命由我不由天
3楼-- · 2019-08-10 03:51

You can get the request object from self.context. So if you only need request.user, that's one way to do it.

class OwnedTable(tables.Table):
    roles = tables.Column(empty_values=())

    def render_roles(self):
        user = self.context["request"].user
        ...

Otherwise, @mariodev's solution works.

查看更多
一夜七次
4楼-- · 2019-08-10 04:00

It seems like there's no way of using auth user without some overriding.

You can override __init__ for our table class like this:

class OwnedTable(tables.Table):
    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user', None)
        super(OwnedTable, self).__init__(*args, **kwargs)

then, inside view, you call table with user argument, like so

table = OwnedTable(Person.objects.all(), user=request.user)

now you can use self.user inside render_roles method to refer to the currently logged in user.

查看更多
登录 后发表回答