I want my page to be something like this:
Startpage with the newest project on the frontpage, links to the
categories in my portfolio (web, 3D, photo and so on). If the user
press a category they will get a listing of the 10 newest entries
inside the category. If the user press a project the will see the "full
story". The "full story" will also have links to the next and previous
project in that category (if there are any).
I have posted my model.py of my app called portfolio in
http://www.django.pastebin.com/744736
Are anyone able to help me, or point me in the right direction? My
portfolio app seems like it have disapeard from the admin page now, but
if I try http://mydomain.com/admin/portfolio/project/ it works just
fine. Strange
Django's view functions responsible for extracting the data you need
from the database (using the models you created), putting it into a
dictionary-like object (a Context) with the right names attached to each
item and then passing that context to a Template object, which turns a
template + context into some output (the HTML you end up sending to the
user).
So let's break that down into a few steps (and I'll use your example as
a rough guide):
(1) What information do you want to display? I'm not interested here in
*how* it is going to be displayed (that is the template's job); rather,
trying to work out what we need to extract from the database.
- on one page (one view) you want a list of each available
category, so you need to extract the distinct category names.
- without testing it (just looking at your models), this
would be
categories = Category.objects.all()
- in another view, you wanted the ten latest items for that
category, so you need to be able to filter out the latest items
for a category. Suppose you already have the category_id for
this category (if you have the category instance, it will be
category.id)
Project.objects.filter(category = category_id)[:10]
(I am exploiting the fact that you are already ordering by
"-created" here, so they come out in the right order).
(2) How will this information appear in the templates?
Your cases are simple enough that the "object_list" generic view will
probably work nicely for you. The queryset you pass to the generic view
will be, for example, the Category.objects.all() queryset above (for
your first page). If you do no customisation at all, your template will
be passed a variable called "object_list" that will be the list of
categories. So you can do things like "{% for object in object_list %}"
to loop over this list and each "object" will be a Category object, so
you can output it's name using "{{ object }}" and so forth.
You therefore just need to write a template to display this. Again, if
you do no customisation at all, the template needs to be called
"<app_label>/category_list.html" (obviously, replace <app_label>), but
you can customise that by passing in a "template_name" parameter to the
generic view (this is all described in the generic view documentation,
so I am not about to write it all out again here).
Note that the generic views take care of wrapping up the data in a
context and passing that into the template.
(3) How is a particular URL request made to call this view?
You need to set up a urls.py file that maps the URLs you want to use
onto the view functions. There are examples at the top of the generic
views documentation (although they are for date-based views, so they
contain more information than you need to supply). You might choose, for
example, to do something like this
info = {'queryset': Category.objects.all()}
urlpatterns = patterns('django.views.generic.list_detail',
(r'^overview/$', 'object_list', info),
)
Create a template with the right name and this should "just work",
without too much trouble.
So there are a few things that need to be done here, it looks like, but
none of them are particularly difficult. Extracting the data from the
database and into your models is described in the "database API"
documentation, the generic views have their own documentation (called
"generic views") and creating the templates is in the "template guide
for HTML authors" documentation.
The last half or so of tutorial #1 also gives some examples of using the
database API to work with models. And tutorial #3 talks about putting
that data into templates using views. If you have not worked your way
through the tutorials, you are at a grave disadvantage. If you have gone
through them, it might be worthwhile to revisit them again with this new
information in hand. Maybe things will become a bit clearer.
Regards,
Malcolm
I have managed to get out the slug name of my projects in
"mydomain/portfolio/". But I don't know how I write the view for the
detail page or how I get the right URL to the detail.
I want the URL to be "mydomain/portfolio/category_slug/project_slug"
like "mydomain/portfolio/3d/house/".
My urls.py looks like this:
from django.conf.urls.defaults import *
from myproject.portfolio.models import Project
from myproject.portfolio.models import Category
urlpatterns = patterns('',
# Polls:
(r'^polls/$', 'myproject.polls.views.index'),
(r'^polls/(?P<poll_id>\d+)/$', 'myproject.polls.views.detail'),
(r'^polls/(?P<poll_id>\d+)/results/$',
'myproject.polls.views.results'),
(r'^polls/(?P<poll_id>\d+)/vote/$', 'myproject.polls.views.vote'),
# Portfolio:
(r'^portfolio/$', 'myproject.portfolio.views.index'),
(r'^portfolio/(?P<categoy_slug>\d+)/$',
'myproject.portfolio.views.list'),
(r'^portfolio/(?P<categoy_slug>\d+)/(?P<project_slug>\d+)/$',
'myproject.portfolio.views.detail'),
# For homepage:
(r'^$', 'django.views.generic.simple.direct_to_template',
{'template': 'homepage.html'}),
# Uncomment this for admin:
(r'^admin/', include('django.contrib.admin.urls')),
)
My portfolio/view.py looks like this:
from django.shortcuts import render_to_response
from myproject.portfolio.models import Project
from myproject.portfolio.models import Category
# Create your views here.
def index(request):
latest_project_list = Project.objects.all().order_by('-created')
return render_to_response('portfolio/index.html',
{'latest_project_list': latest_project_list})
my portfolio/index.html looks like this:
<h2>Projects</h2>
{% if latest_project_list %}
<ul>
{% for project in latest_project_list %}
<li><a href="{{ category.slug }}/{{ project.slug }}">{{
project.title }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No Projects are available.</p>
{% endif %}
I don't think my urls.py is correct for this type of setup, but Im not
shure. Would really appreciate all the help I can get. And thank you
again Malcom for all your help!
My portfolio app is still missing from the main menu inside admin, but
still works if I type in the direct url to it.
"mydomain/admin/portfolio/project/" . If anyone could spot the error in
my model.py (posted in the first post) that is causing the portfolio
to disappear, please let me know!
OK, let's try fixing one problem at a time, instead of all 47 at
once. :-)
[...]
> urlpatterns = patterns('',
> # Portfolio:
> (r'^portfolio/$', 'myproject.portfolio.views.index'),
> (r'^portfolio/(?P<categoy_slug>\d+)/$',
> 'myproject.portfolio.views.list'),
> (r'^portfolio/(?P<categoy_slug>\d+)/(?P<project_slug>\d+)/$',
> 'myproject.portfolio.views.detail'),
Let's just focus on this bit.
> My portfolio/view.py looks like this:
>
> from django.shortcuts import render_to_response
>
> from myproject.portfolio.models import Project
> from myproject.portfolio.models import Category
>
> # Create your views here.
> def index(request):
> latest_project_list = Project.objects.all().order_by('-created')
> return render_to_response('portfolio/index.html',
> {'latest_project_list': latest_project_list})
You don't mention what does and doesn't work here, so let's ask a few
questions:
(1) Firstly, you refer to the view functions as
myproject.portfolio.views.* (with an 's' on views), but later on you say
the file is called portfolio/view.py. Is this a typo? You are creating
Python import paths here, so if your file is called view.py, you can't
refer to it as "views" in the import path in urlpattens.
(2) Assuming question (1) really is a typo, does accessing the
"portfolio/" URL work? From the code you posted, it looks like it should
work more or less correctly. If you are not sure if it is being called,
drop a print statement in there (if you are using the development
server, the print output will come out in the terminal window where the
development server is running).
The only potential problem is that your template path may or may not be
wrong depending upon how you've set up your TEMPLATE_DIR settings. You
basically have two choices:
(a) Put the templates under a directory in the TEMPLATE_DIR list
and then refer to them by their path (remove the "TEMPLATE_DIR"
prefix from the front). So if TEMPLATE_DIR =
('/home/malcolm/templates',) and I wanted to refer to my
template as 'portfolio/index.html', I could put it
in /home/malcolm/templates/portfolio/index.html.
(b) Put the templates inside an application directory in a
sub-directory called "templates". So you might put it in
myproject/portfolio/templates/ in your case. Again, Django will
strip off the bit up to and including the "templates/" portion
of the path, so you use the rest to refer to the template. If
you have a file called
myproject/portfolio/templates/portfolio/index.html you are fine
here.
Either (a) or (b) works. Generally, (b) is a good option for templates
that belong to a particular application (since then you can easily move
the templates around with the rest of the code), whereas (a) is good for
cross-application or site-wide templates (they belong to no particular
project or application).
Assuming you get this far, you now need to create list() and detail()
functions (inside views.py). The list() function, for example, would
start off as
def list(request, category_slug):
# ...
the name of the parameter here should match the name you use in the
reg-exp to capture that argument (currently it doesn't, but I am
assuming you have accidently misspelt "category" in your urls.py and
will fix that; but at least note that there is a possibly unexpected
typo there).
Also, as a stylistic issue, calling a function list() is risky. Python
already has a list() builtin so in that module, you have now lost access
to Python's list() function, which might cause unexpected problems down
the track.
If you get this far, then you probably have the hang of things. If you
are not getting this far, perhaps showing what errors you are seeing
will help.
Again, focus on getting one path right at a time and fixing one error at
a time.
Good luck,
Malcolm
I have managed to "render" project slug and project title into html. My
template is inside "/django/django_templates/portfolio/" and is called
"index.html". If I try to type in "mydomain.com/portfolio" I get the
nice list of project name, and inside the "a href" I get the project
slug. So far so good!
For my next step I need to get the project slug inside that same "a
href" so my links looks like this:
"mydomain/portfolio/category_slug/project_slug"
I have tried with <a href="{{ category.slug }}/{{ project.slug }}"> but
I think I need to write a new function inside views.py in my
"portfolio" app, that will bring out that category slug, because it's
not rendring out the category slug now.
That's step one, but then I'll only have the correct link the way I
want. Step 2 is getting that url to work. I understand I need to make a
"rule" inside urls.py, but Im not sure how I get the desired rule to
work.
My portfolio urls looks like this now (with corrected typos)
# Portfolio:
(r'^portfolio/$', 'myproject.portfolio.views.index'),
(r'^portfolio/(?P<category_slug>\d+)/$',
'myproject.portfolio.views.list'),
(r'^portfolio/(?P<category_slug>\d+)/(?P<project_slug>\d+)/$',
'myproject.portfolio.views.detail'),
if I try to type in "mydomain/portfolio/category_slug/"
(mydomain/portfolio/3d/) I only get a regular 404 Page not found error.
If I try "mydomain/portfolio/1/" (1 being the id for the first
category) I get a ViewDoesNotExist. That's fine, I don't want people to
be able to use the id of the category anyways, I want the category slug
instead. But if there is a easy way to do both it would be great.
-----
I still can't get anything from the category model, but here is what I
have tried to do on my own so far. :
----
This is the views.py in my portfolio app folder (if you know a better
name instead of "list", let me know):
----
from django.shortcuts import render_to_response
from myproject.portfolio.models import Project
from myproject.portfolio.models import Category
from django.http import HttpResponse
# Create your views here.
def index(request):
latest_project_list = Project.objects.all().order_by('-created')
return render_to_response('portfolio/index.html',
{'latest_project_list': latest_project_list})
def list(request, category_slug):
category_slug_list = Category.objects.all()
return render_to_response('portfolio/index.html',
{'category_slug_list': category_slug_list})
----
And here is my portfolio/index.html (inside /django_templates/)
----
<h2>Projects</h2>
{% if latest_project_list %}
<ul>
{% for project in latest_project_list %}
<li><a href="{{ category.slug }}/{{ project.slug }}">{{
project.title }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No Projects are available.</p>
{% endif %}
<h2>Categories<h2>
{% if category_slug_list %}
<ul>
{% for category in category_slug_list %}
<li>{{ category.slug }}</li>
{% endfor %}
</ul>
{% else %}
<p>No Category are available.</p>
{% endif %}
----
The only thing that is getting renderd is the project.slug and
project.title.
I have never coded in python before, and I've only done minor php
coding before. Im more the design/html/css guy. I think that's the
reason Im moving in such a slow pace.
I hope this is a bit clearer and will make it easier to help me :)
> I have tried with <a href="{{ category.slug }}/{{ project.slug }}"> but
> I think I need to write a new function inside views.py in my
> "portfolio" app, that will bring out that category slug, because it's
> not rendring out the category slug now.
That is because you are not passing any 'category' variable to the
template, but you don't need to. What you need to do is something like
this:
<a href="/portfolio/{{ project.category.slug }}/{{ project.slug }}">
You access the category of the current project with
'project.category'. I am assuming here that in your models you defined
a ForeignKey to Category in your Project model, i.e. that a Project
belongs to a Category, like this:
> My portfolio urls looks like this now (with corrected typos)
>
> # Portfolio:
> (r'^portfolio/$', 'myproject.portfolio.views.index'),
> (r'^portfolio/(?P<category_slug>\d+)/$',
> 'myproject.portfolio.views.list'),
> (r'^portfolio/(?P<category_slug>\d+)/(?P<project_slug>\d+)/$',
> 'myproject.portfolio.views.detail'),
The urls you see there are nothing more than regular expressions. In a
regular expression you can match a single digit with the expression
'd', and you can match one or more digits by putting the plus sign
after the 'd' ( ej. 'd+').
But in your case you need to match words, not digits. To match a word
you need to match one or more alphanumeric characters. The expression
for an alphanumeric character is 'w', to match one or more you put the
plus sign after it: w+.
Your urls could look like this:
(r'^portfolio/(?P<category_slug>\w+)/$', 'myproject.portfolio.views.list'),
(r'^portfolio/(?P<category_slug>\w+)/(?P<project_slug>\w+)/$',
'myproject.portfolio.views.detail'),
With the above urls you can match urls like /portfolio/web/school/,
where web is the category and school is the slug of the project. But
there's a problem. If your category or project slug contains two or
more words, those words will be separated by a - (hyphen) character.
For example, the url /portfolio/web/school-portal/ will not be matched
by the above urls.
You need to include the hyphen sign in your regular expression. To do
that you need to enclose the 'w' and the '-' in brackets and put the
plus sign after the closing bracket like this:
(r'^portfolio/(?P<category_slug>\[-w]+)/$', 'myproject.portfolio.views.list'),
(r'^portfolio/(?P<category_slug>\[-w]+)/(?P<project_slug>\[-w]+)/$',
'myproject.portfolio.views.detail'),
The above urls will now correctly match a path like /portfolio/web/site-portal/
> # Create your views here.
> def index(request):
> latest_project_list = Project.objects.all().order_by('-created')
> return render_to_response('portfolio/index.html',
> {'latest_project_list': latest_project_list})
>
> def list(request, category_slug):
> category_slug_list = Category.objects.all()
> return render_to_response('portfolio/index.html',
> {'category_slug_list': category_slug_list})
>
I see that you are using the same template (index.html) in both views.
Is that what you intended?
Also, the list() view is supposed to list the projects under the
specified Category. I'm guessing that what you want is to get the
Category that correspond to the specified category_slug and then list
the projects that belong to that category. In that case I would change
your list() view like this:
def list(request, category_slug):
# Get the category and the projects that belong
# to this category.
category = Category.objects.get(slug=category_slug)
projects = category.project_set.all()
return render_to_response('portfolio/category_projects.html',
{'category':category, 'projects': projects}
)
And the portfolio/category_projects.html would look like this:
<h1>{{ category }}</h1>
<h2>Projects in this category:</h2>
<ul>
{% for pro in projects %}
<li><a href="/portfolio/{{ category.slug }}/{{ pro.slug }}/">{{
pro.title }}</a></li>
{% endfor %}
</ul>
As for the index.html,
>
> <h2>Projects</h2>
>
> {% if latest_project_list %}
> <ul>
> {% for project in latest_project_list %}
> <li><a href="{{ category.slug }}/{{ project.slug }}">{{
> project.title }}</a></li>
> {% endfor %}
Change this:
<a href="{{ category.slug }}/{{ project.slug }}">
with this:
<a href="/portfolio/{{ project.category.slug }}/{{ project.slug }}">
I hope this makes things clearer.
Cheers!
Jorge
> a ForeignKey to Category in your Project model, i.e. that a Project
> belongs to a Category, like this:
Ooopss, I left something out there.
But any case I wanted to apologize for rushing with my previous email,
I did not read the email that Malcolm sent before and he is raising
very important points. Please take a close look at what he is saying
and asking there. You'll need to figure out that first.
Cheers,
Jorge
But I don't understand it good enough to write more url patterns. I
don't know how to write a pattern for listing projects inside a
spesific category. And I don't know how to make a pattern for the
detail page.
For my portfolio/models.py I use this code : http://phpfi.com/133790
I use this pattern now for listing all my projects:
info_dict = { 'queryset': Project.objects.all(), }
urlpatterns = patterns('',
(r'^portfolio/$', 'django.views.generic.list_detail.object_list',
dict(info_dict, template_name="portfolio/projects_list.html")),
)
I have tried adding this line:
(r'^portfolio/(?P<category_slug>[-\w]+)/$',
'django.views.generic.date_based.object_detail', dict(info_dict,
slug_field='slug',
template_name="portfolio/category_spesific_list.html")),
But I get the error" object_detail() got an unexpected keyword argument
'category_slug' " when I try mydomain.com/portfolio/3d
Im not shure how that would line would work for only listing project in
the given category anyway.
I have made a static dummy site so you can see what I want. In django
Im able to do like the frontpage here, but the rest I can't do.
http://tomasjacobsen.com/django-dummy/
I hope someone can help me further!
Regars Tomas
Rock and roll! Glad you're making progress. :-)
>
> But I don't understand it good enough to write more url patterns. I
> don't know how to write a pattern for listing projects inside a
> spesific category. And I don't know how to make a pattern for the
> detail page.
>
> For my portfolio/models.py I use this code : http://phpfi.com/133790
>
>
> I use this pattern now for listing all my projects:
>
> info_dict = { 'queryset': Project.objects.all(), }
>
> urlpatterns = patterns('',
>
> (r'^portfolio/$', 'django.views.generic.list_detail.object_list',
> dict(info_dict, template_name="portfolio/projects_list.html")),
> )
>
> I have tried adding this line:
>
> (r'^portfolio/(?P<category_slug>[-\w]+)/$',
> 'django.views.generic.date_based.object_detail', dict(info_dict,
> slug_field='slug',
> template_name="portfolio/category_spesific_list.html")),
>
> But I get the error" object_detail() got an unexpected keyword argument
> 'category_slug' " when I try mydomain.com/portfolio/3d
>
> Im not shure how that would line would work for only listing project in
> the given category anyway.
OK, now for some good news/bad news information: you can't get exactly
the effect you want with just generic views. This is because you are
wanting to do some computation based on the information in the URL and
then pass the results to the view function (for a start, your queryset
is dependent upon the URL). That's the bad news.
The good news is that it's about two lines of extra code to work out the
information you need and then you can pass the bulk of the work off to
generic views.
What you can do is write your own view function (yeah, you just got away
from your own views and now you have to go back... life's like that
sometimes) that accepts the category name as a parameter. This function
will work out the correct query set and pass that information (along
with the category name and whatever else you want) to the generic view
to extract the information and call your template.
Here's what your view might look like:
def category_view(request, cat_name):
queryset = Project.objects.filter(category__name = cat_name)
context = {'category_name': cat_name}
return object_detail(request, queryset, extra_context =
context)
Note that there are two underscores between "category" and "name" in the
filter. That syntax is explained in [1]. Once you have worked out the
query set, you pass that and the name (via extra_context) and the
original request object off to the generic view to work out the result.
I guess in your case you probably want to pass template_name into that
call to object_detail as well, but at that point it's all just a normal
function call, so you can look at the parameters the object_detail()
function takes (see [2]) and pass in whatever you like.
I wrote about this elsewhere ([3]) a little bit as well, although it
pretty much just says exactly what I wrote here, I suspect.
[1]
http://www.djangoproject.com/documentation/db_api/#lookups-that-span-relationships
[3]
http://www.pointy-stick.com/blog/2006/06/29/django-tips-extending-generic-views/
Best wishes,
Malcolm
My views.py in my portfolio app folder looks like this:
from django.views.generic.list_detail import object_list
from myproject.portfolio.models import Project
from myproject.portfolio.models import Category
categories = Category.objects.all()
#Views
def category_view(request, cat_slug):
queryset = Project.objects.filter(category__slug = cat_slug)
context = {'category_slug': cat_slug}
return object_detail(request, queryset, extra_context =
context)
I have changed name with slug, but I tried with name and I got the same
error.
My urls.py looks like this:
urlpatterns = patterns('',
# For homepage:
(r'^$', 'django.views.generic.simple.direct_to_template',
{'template': 'homepage.html'}),
# Uncomment this for admin:
(r'^admin/', include('django.contrib.admin.urls')),
#Portfolio
(r'^portfolio/$', 'django.views.generic.list_detail.object_list',
dict(info_dict, template_name="portfolio/projects_list.html")),
(r'^portfolio/(?P<category_slug>[-\w]+)/$',
'myproject.portfolio.views.category_view'),
When I try "mydomain.com/portfolio/category_slug" (My category_slug is
"3d") I get the error:
TypeError at /portfolio/3d/
category_view() got an unexpected keyword argument 'category_slug'
So I think Im doing something wrong in the urls.py.
You have named the group inside your regular expression
"category_slug" therefore djangp passes a parameter with this name to
the view. But in your view this parameter is named "cat_slug". So, If
you either change the name of your group in the reg-ex or change the
name of the parameter in the view so that they match each other, is
problem should be gone.
Martin
But now I get a new error:
NameError at /portfolio/3d/
global name 'object_detail' is not defined
Exception Location: /myproject/portfolio/views.py in category_view,
line 10
> NameError at /portfolio/3d/
> global name 'object_detail' is not defined
>
> Exception Location: /myproject/portfolio/views.py in category_view,
> line 10
That normally mean that you have not imported the name.
Do you have something like this in you views.py
from django.views.generic.list_detail import object_detail
Martin
The next step is getting the detail view of each project to work. Do I
need to write a new view for that, or can I use django generic view?
My urls looks like this now:
mydomain.com/portfolio = list all my projects
mydomain.com/portfolio/category_slug = list all projects inside the
given category
Now I want a url like this:
I've tried
(r'^portfolio/(?P<category_slug>[-\w]+)/(?P<project_slug>[-\w]+)$',
'myproject.portfolio.views.category_view'),
and
(r'^portfolio/(?P<category_slug>[-\w]+)/(?P<project_slug>[-\w]+)$',
'myproject.portfolio.views.category_view', dict(info_dict,
template_name="portfolio/detail_view.html")),
But I only get a Page not found (404) error, so I can't even reach the
page.
My urls looks like this now:
info_dict = {
'queryset': Project.objects.all(),
}
urlpatterns = patterns('',
#Portfolio
(r'^portfolio/$', 'django.views.generic.list_detail.object_list',
dict(info_dict, template_name="portfolio/all_projects_list.html")),
(r'^portfolio/(?P<category_slug>[-\w]+)/$',
'myproject.portfolio.views.category_view'),
(r'^portfolio/(?P<category_slug>[-\w]+)/(?P<project_slug>[-\w]+)$',
'myproject.portfolio.views.category_view', dict(info_dict,
template_name="portfolio/detail_view.html")),
}
the 2 first url rules works like they supposed, but I can't get the
detail view to work. I don't know If I need to use the same view I have
used for the category view or not.
Best regards,
Tomas
Since the first part of the URL mapping tuple is a Python regular
expression, you can experiment at the command line. Import the "re"
module and use the regular expression you are trying to get working to
match against the sorts of URLs you are going to be sending in.
Something like:
>>> import re
>>> p = re.compile(r'^portfolio/(?P<category_slug>[-\w]+)/(?P<project_slug>[-\w]+)$')
>>> s = 'portfolio/foo/blah/'
>>> m = p.match(s)
At this point, m will either be None (it did not match) or a reg-exp
match object (see the Python docs for the re module for details) that
you can poke about at to see what made it into various keyword
arguments, etc.
The fact that you are seeing a 404 means that the regular expression is
not picking up your URLs, so you need to start there.
Regards,
Malcolm
> Since the first part of the URL mapping tuple is a Python regular
> expression, you can experiment at the command line. Import the "re"
> module and use the regular expression you are trying to get working to
> match against the sorts of URLs you are going to be sending in.
> Something like:
>
> >>> import re
> >>> p = re.compile(r'^portfolio/(?P<category_slug>[-\w]+)/(?P<project_slug>[-\w]+)$')
> >>> s = 'portfolio/foo/blah/'
> >>> m = p.match(s)
>
> At this point, m will either be None (it did not match) or a reg-exp
> match object (see the Python docs for the re module for details) that
> you can poke about at to see what made it into various keyword
> arguments, etc.
>
> The fact that you are seeing a 404 means that the regular expression is
> not picking up your URLs, so you need to start there.
>
> Regards,
> Malcolm
The command line your talking about, is it the shell?
I've tried python manage.py shell and the code you wrote. But nothing
happends when I type them in. No errors either. Do I need to replace
'portfolio/foo/blah/' with a "real" url ? Or is it another command line
than the shell?
Thank you for your help!
Best Regards,
Tomas
Yes.
> I've tried python manage.py shell and the code you wrote. But nothing
> happends when I type them in. No errors either. Do I need to replace
> 'portfolio/foo/blah/' with a "real" url ?
Yes. Replace it with the sort of URL you are sending to your app.
Obviously the host name portion if stripped from the URL, but you
already have a couple of working URL patterns in that file, so you can
see how much to strip off the front.
Regards,
Malcolm
What is suppose to happen when I write that code in? Nothing is
happening here.
I tried to replace the 'portfolio/foo/blah/' with
'portfolio/web/web_project/' , but I don't see any "results" or erros
in the shell.
Regards,
Tomas
As I said in the original post, at the end of those commands, the
variable 'm' will either be None, indicating that nothing matched, or a
regular expression match object. In the latter case you can use the
Python re module's documentation (in particular,
http://docs.python.org/lib/match-objects.html ) to see what you have
captured.
> I tried to replace the 'portfolio/foo/blah/' with
> 'portfolio/web/web_project/' , but I don't see any "results" or erros
> in the shell.
In this case 'm' is None (have a look at the result of "type(m)" or "m
is None" after the final command).
The original regular expression you posted did not end with a trailing
slash, but it did require to match up to the end of the line (the final
'$'). Adding a trailing slash seems to improve things. That may well be
your only problem if those are the types of URLs you are expecting to
capture. For example,
>>> p = re.compile(r'^portfolio/(?P<category_slug>[-\w]+)/(?P<project_slug>[-\w]+)/$')
>>> m = p.match('portfolio/web/web_project/')
>>> m.groupdict()
{'category_slug': 'web', 'project_slug': 'web_project'}
Best wishes,
Malcolm
Don't I need a "custom" view that get the 'category_slug' and
'project_slug' ?
If I try this in my views.py:
def detail_view(request, project_slug):
queryset = Project.objects.filter(project_slug = project_slug)
context = {'project_slug': project_slug}
return object_detail(request, queryset, extra_context =
context)
I get:
TypeError at /portfolio/web/web_project/
detail_view() got an unexpected keyword argument 'category_slug'
Is there an easy way to just drop the 'category_slug' the detail_view,
or is it another/better way to do this?
If you want to use generic views you *have* to use only the parameters
described in the documentation for generic views, that's right. So as
soon as you want highly customised URLs like you are trying to create
here, you have left behind the ability to use purely generic views. But
that's okay. They're just an aid, not a requirement.
> Don't I need a "custom" view that get the 'category_slug' and
> 'project_slug' ?
Yes.
> If I try this in my views.py:
>
> def detail_view(request, project_slug):
> queryset = Project.objects.filter(project_slug = project_slug)
> context = {'project_slug': project_slug}
> return object_detail(request, queryset, extra_context =
> context)
>
> I get:
>
> TypeError at /portfolio/web/web_project/
> detail_view() got an unexpected keyword argument 'category_slug'
That error should be self-explanatory. The function only accepts a
project_slug parameter (along with the obligatory request parameter).
The view functions are standard Python functions: you need to tell them
what parameters to expect.
> Is there an easy way to just drop the 'category_slug' the detail_view,
> or is it another/better way to do this?
If you want a view that works with category_slug, just add another
parameter to the function call and work with it inside the function. If
you want a view that works with both (just project_slug or project_slug
+ category_slug), then make the function definition look like:
def detail_view(request, project_slug, category_slug = None):
...
and inside the function take different actions depending upon whether
category_slug is None or not.
Malcolm
I missed a 'in' there:" just drop the 'category_slug' in* the
detail_view "
Anyways, it seems like you got the idea.
Im trying to modify the view you wrote for me for the category view.
def detail_view(request, project_slug, category_slug = None):
queryset = Project.objects.filter(project_slug = project_slug ,
category__slug = category_slug)
context = {'project_slug': project_slug , 'category_slug':
category_slug}
return object_detail(request, queryset, extra_context =
context)
(Mind I don't have a clue what Im doing here, just trying things out,
that seems logic to me)
Then I get the error:
AttributeError at /portfolio/web/web_project/
Generic detail view must be called with either an object_id or a
slug/slug_field.
If I change the return object_detail to return object_list
I get this error:
TypeError at /portfolio/web/web_project/
Cannot resolve keyword 'project_slug' into field
I have this in the top of the view.py
from django.views.generic.list_detail import object_list
from django.views.generic.list_detail import object_detail
from myproject.portfolio.models import Project
from myproject.portfolio.models import Category
Is the view so wrong I think it is, or am I just importing the wrong
genric view?
Please step back from your project and spend a bit of time going through
a Python tutorial and the Django tutorials. I really cannot write all
your code for you in this thread.
You don't seem to be taking the necessary time to understand the errors
you are seeing -- whether they be thrown by Python or Djanog. I'm sorry,
but this thread is 22 emails long already and I don't think I am really
helping you to help yourself. So I am bowing out. Others may be able to
help you further.
Best wishes,
Malcolm
No problem. Thank you for all your help! I really appreciate what you
have done. Without your help, I probably would have given up on django
a long time ago. I will try to read more of the tutorials, It's just
that it isen't that easy to find a tutorial that covers what Im trying
to do.
Best regards,
Tomas
My recommendation (and Malcolm also said it) is that you first get to
know Python better and then tackle Django, one at a time. It will make
things easier in the long run, and you will be able to better
understand how Django works and why.
Here are some places to start:
http://pytut.infogami.com/
http://www.diveintopython.org/
http://www.awaretek.com/tutorials.html#begin
http://www.ferg.org/papers/debugging_in_python.html
Trust me, once you feel comfortable writing and debugging Python
programs, getting Django to do what you want it to do will be really
easy.
Cheers,
Jorge