views:

30

answers:

2

I have a model which needs to store URLs which will be part of the Django environment. If I was storing normal URLs, I'd use models.URLField, and use verify_exists to make sure the URL actually exists.

However, this doesn't work that great in development, since the dev server is single-threaded, it hangs indefinitely, since it can't process two requests at once.

I was hoping to do something using resolve(), but am having difficulty adapting the function myview at the end of that documentation page to a version which does not take a request, since I want to check that a given local URL can be resolved, and called without a 404 being raised, from a blank session.

I was hoping to do this with a validator, something like this:

def validate_local_url(value):
    try:
        view, args, kwargs = resolve(value)
        view(*args, **kwargs)
    except Resolver404:
        raise ValidationError(u'%s is not a local URL (not a valid URL)' % value)
    except Http404:
        raise ValidationError(u'%s is not a local URL (does not exist)' % value)

However, this fails without a valid request object being passed into kwargs. How do I generate a dummy (blank) request object? I've tried just using django.http.HttpRequest.

A: 

Just a wild idea, not sure if it will be helpful. Have you considered naming the urls and using reverse()? Reverse will work if the URL is valid and will fail when it is not.

Manoj Govindan
I'm not sure how I'd get this to work - users would need to know the names of views and how they get their parameters.
Dominic Rodger
A: 

Are you cool with using the django test Client?

If so, this should do it:

from django.test.client import Client

def validate_local_url(path):
    c = Client()
    try:
        resp = c.get(path)
        if resp.status_code == 404:
            raise ValidationError(u'%s is not a local URL (does not exist)' % value)
    except:
        raise ValidationError(u'%s is not a local URL (not a valid URL)' % value)

Just, you know, make sure under penalty of death that validate_local_url can never be called by a local GET request, otherwise someone can trivially set your server on an infinite loop:

# urls.py
url('^infinite_loop/$', 'myapp.infinite_loop', 'infinite_loop')

#views.py
def infinite_loop_view(request, template_name="blah.html", form_class=MyForm):
    my_form = form_class(request.REQUEST or None) # yes, admittedly this is dumb
    if my_form.is_valid():
        return HttpResponse("Congratulations! Your path was totally valid.")
    return render_to_response(template_name, locals(), RequestContext(request))

And then:

http://example.com/infinite_loop/?path_field=infinite_loop

Jordan Reiter
Although I suppose even then it would be okay, since the second call wouldn't send in the path variables, right?Even so, I would be wary of this decision. Personally, I'd be content with making sure that they created a local URL that points to a valid URL (i.e. doesn't raise Resolver404) and be accepting of the occasional 404.
Jordan Reiter