views:

230

answers:

3

I know that I can pass object values through a URL pattern and use them in view functions. For instance:

(r'^edit/(?P<id>\w+)/', edit_entry),

can be utilized like:

def edit_entry(request, id):
        if request.method == 'POST':
                a=Entry.objects.get(pk=id)
                form = EntryForm(request.POST, instance=a)
                if form.is_valid():
                        form.save()
                        return HttpResponseRedirect('/contact/display/%s/' % id)
        else:
                a=Entry.objects.get(pk=id)
                form = EntryForm(instance=a)
        return render_to_response('edit_contact.html', {'form': form})

But how do I pass a value from a model field (other than "id") in the url? For instance, I have an abstract base model with a field "job_number" that is shared by child models "OrderForm" and "SpecReport". I want to click on the "job_number" on the order form and call the Spec Report for that same job number. I can create an

href="/../specifications/{{ record.job_number }}

to pass the info to the url, but I already know that this regex syntax is incorrect:

(r'^specifications/(?P<**job_number**>\w+)/', display_specs),

nor can I capture the job_number in the view the same way I could an id:

def display_specs(request, job_number):
    records = SpecReport.objects.filter(pk=job_number)
    tpl = 'display.html'
    return render_to_response(tpl, {'records': records })

Is there an easy approach to this or is it more complicated than I think it is?

the amended code is as follows:

(r'^specdisplay/?agencyID=12/', display_specs),

and:

def display_specs(request, agencyID):
    agencyID= request.GET.get('agencyID')
    records = ProductionSpecs.objects.filter(pk=id)
    tpl = 'display_specs.html'
    return render_to_response(tpl, {'records': records })

not sure how to filter. pk is no longer applicable.

+1  A: 

Not knowing what your model structure is like ... why couldn't you just pass the particular job's id and then pick it up with a query?

Afaik every model automatically has an id field that autoincrements and is a unique identifier of a row (an index if you will), so just change the href creation to {{record.id}} and go from there.

Try passing the job_number through the url then, especially if you don't care about pretty url's too much just do this:

url:  /foo/bar/?job_number=12

no special markup to catch this btw, the regex is r'^foo/bar/'

And then read it in the view like this:

job_number= request.GET.get('job_number')
Swizec Teller
Because the id for the OrderForm object will not necessarily be the same as the id for the SpecForm object. If I have order forms for every job - but spec forms for only some jobs, I don't think I can be sure that the ids will always match. But the job numbers always will. That was my logic anyway. Could be wrong. I'll try the id route and see if it works.
kjarsenal
because I couldn't make this comment readable enough, I've edited the answer, hope that's alright
Swizec Teller
thanks for the help. I tried to amend the code with respect to your advice. Still not quite there. Can you take a quick look at the amended code above and tell me if I'm on the right track? Thanks. Also- replacing "job_number" with "agencyID" as this is the fields actual name.
kjarsenal
A: 

I really don't understand your question. What's the difference between passing id and passing job_number in a URL? If you can do one, why can't you do the other? And once the job_number is in the view, why can't you do a normal filter:

records = SpecReport.objects.filter(job_number=job_number)
Daniel Roseman
ok, so I'm now filtering this way. thank you.
kjarsenal
There seems to be a difference if job_number is actually not a number so much as a code (like "EMP-AS-15751"), which unfortunately is the way that a lot of businesses identify their products. I don't think it's that I can't pass the info – it's just that I don't think I can use the same regex as for <id>.
kjarsenal
+2  A: 

Yes, you are making this a little more complicated that it is.

In your urls.py you have:

(r'^edit/(?P<id>\w+)/', edit_entry),

Now you just need to add the almost identical expression for display_specs:

(r'^specifications/(?P<job_number>\w+)/', display_specs),

Parenthesis in the regex identifies a group and the (?P<name>...) defines a named group which will be named name. This name is the parameter to your view.

Thus, your view will now look like:

def display_specs(request, job_number):
   ...

Finally, even though this will work, when you redirect to the view, instead of using:

HttpResponseRedirect('/path/to/view/%s/' % job_number)

Use the more DRY:

HttpResponseRedirect(
    reverse('display_specs', kwargs={'job_number': a.job_number}))

Now if you decide to change your resource paths your redirect won't break.

For this to work you need to start using named urls in your urlconf like this:

url(r'^specifications/(?P<job_number>\w+)/', display_specs, name='display_specs'),
Van Gale
I tried this first. But django throws an 404 error. If the "agencyID" is "EMP-INT-37914" and the url is written (r'^specdisplay/(?P<agencyID>\w+)/', display_specs), — Django says :Request URL: http://localhost:8000/specdisplay/EMP-INT-37914/Tried the following urls:^specdisplay/(?P<agencyID>\w+)/...this is why I assumed you couldn't write the expression the same way as <id>.
kjarsenal
It's true that I don't understand named groups as well as I'd like (I'm working on it). But it seems that the crux of this problem is that this syntax "(?P<whatever>\w+)" only works when the data inside the angle braces is in integer format? When my agencyIDs are string data (as all of mine are) django threw errors. The only thing I could think that was different than <id> was string vs integer. When I changed "EMP-INT-37914" to "5", it worked like a charm. Unfortunately, it doesn't help me because my agencyID data is string data and I still can't figure out how to pass it.
kjarsenal
The pattern '\w' means any alphanumeric character and underscore, i.e. [a-zA-Z0-9_]. Try this pattern: /(?P<job_number>[A-Z0-9-]+)/ or maybe (assuming display specs always start with EMP-INT) /(?P<job_number>EMP-INT-\d+)/
Van Gale
See http://www.amk.ca/python/howto/regex/ or http://diveintopython.org/regular_expressions/index.html
Van Gale
thank you. I think this is what I need.
kjarsenal
worked famously. VG you da man!
kjarsenal