Django custom decorator user_passes_test() can it obtain url parameters?
<p>Can Django's <code>user_passes_test()</code> access view parameters?</p>

<p>For example I have view that receives an <code>id</code> to retrieve specific record:</p>

<pre><code>def property(request, id):
    property = Property.objects.get(id=int(id))
</code></pre>

<p>The record has a field named user_id that contains the id for user that originally created record. I want users to be able to view only their own records otherwise be redirected.</p>

<p>I'd like to use a custom decorator which seems simple and clean.</p>

<p>For custom decorator is there some variation of something like this that will work? </p>

<pre><code>@user_passes_test(request.user.id = Property.objects.get(id=int(id)).id, login_url='/index/')
def property(request, id):
    property = Property.objects.get(id=int(id))
</code></pre>

<p>I have tried creating separate <code>test_func</code> named <code>user_is_property_owner</code> to contain logic to compare current user to property record user_id</p>

<pre><code>@user_passes_test(user_is_property_owner(id), login_url='/index/')
def property(request, id):
    property = Property.objects.get(id=int(id))


def user_is_property_owner(property_id):
    is_owner = False
    try:
        Property.objects.filter(id=property_id, user_id=user_id).exists()
        is_owner = True
    except Property.DoesNotExist:
        pass
</code></pre>

<p>But having trouble getting current user id and the property id from the request into the  <code>user_is_property_owner</code> decorator function.</p>

<hr>

<p>EDIT to add solution I was using. I did test inside each view test was required. It is simple. i thought using a decorator might be prettier and slightly more simple. </p>

<pre><code>def property(request, id):

    # get object 
    property = Property.objects.get(id=int(id))

    # test if request user is not user id on property record    
    if request.user.id != property.user_id:
        # user is not same as property user id so redirect to index
        return redirect('index')

    # rest of the code if request user is user_id on property record 
    # eg it is ok to let user into view 
</code></pre>

<p>Typically, (using class based views), I'll handle this in the <code>get_queryset</code> method so it would be something like</p>

<pre><code>class PropertyDetail(DetailView):
    def get_queryset(self):
        return self.request.user.property_set.all()
</code></pre>

<p>and that will give a 404 if the property isn't for the current user. You might prefer to use a project like <a href="https://github.com/django-guardian/django-guardian" rel="nofollow">django-guardian</a> if you end up with more permission relationships than just <code>Property</code>.</p>

<p>If you take a look at <a href="https://github.com/django/django/blob/c1aec0feda73ede09503192a66f973598aef901d/django/contrib/auth/mixins.py" rel="nofollow">UserPassesTestMixin</a> you'll see that it processes the <code>test_func</code> before calling <code>dispatch</code> so you'll have to call <code>self.get_object(request)</code> yourself if you decide to go that route.</p>

python django