简体   繁体   中英

Django: two foreign keys to users in model, get the one that's not the user who loaded the page

I have two models that go something like:

class UserProfile(models.Model):
    account = models.ForeignKey(MyUser, related_name='profiles') # MyUser is my custom user model
    display_name = models.CharField(max_length=30)
    ...
    def get_all_contracts(self):
        #returns all contracts associated with the profile

class Contract(models.Model):
    ...
    employee = models.ForeignKey(UserProfile, related_name='employee_contracts')
    employer = models.ForeignKey(UserProfile, related_name='employer_contracts')
    ...

I want to write a method inside the Contract model that returns the UserProfile instance that is not the one accessing the view, so that if it's the employee accessing the dashboard, this method would return the employer and vice versa, so that I can use it like so:

{% for contract in user_profile.get_all_contracts %}
    <h2>The other user is {{ contract.other_user.display_name }}</h2>
{% endfor %}

In this example, other_user would be the method.

Is there a way to do that? I can't figure out how to detect from the method which profile is the one that loaded the page.

any help appreciated :)

You can do this as a template tag. Something like:

from django import template

register = template.Library()

@register.simple_tag
def get_other_user_display_name(user, contract):
    try:
        return [obj for obj in [contract.employee, contract.employer] \
                if obj != user][0].display_name

        # if you don't like list comprehensions, you could do:
        # set([contract.employee, contract.employer]) - set([user])
        # but I find this syntax to be less than obvious
    except IndexError:
        return ''

Then in your template loop:

{% for contract in user_profile.get_all_contracts %}
    <h2>The other user is {% get_other_user_display_name request.user contract %}</h2>
{% endfor %}

If you're 100% confident that the contract.employee and contract.employer relationships won't be null, you can eliminate that IndexError exception handler.

Alternatively, you could do this as an assignment tag if you need to access other properties of the other_user :

@register.assignment_tag(takes_context=True)
def get_other_user(context, contact):
    # you can get request.user from the context

    user = context['request'].user

    return [obj for obj in [contract.employee, contract.employer] if obj != user][0]

Then in your loop you can access whatever properties you want.

{% for contract in user_profile.get_all_contracts %}
    {% get_other_user contract as other_user %}
    <h2>The other user is {{ other_user.display_name }}</h2>
    <p>Their email is: {{ other_user.email }}</p>
{% endfor %}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM