2012-05-05 11 views
6

Inizio a utilizzare l'app Django-MPTT per ottenere un approccio basato sull'albero sulle pagine del mio sito Django.Django-MPTT percorso completo per pagine figlio come fare?

Per es. Ho pagine con pagine secondarie:

Trance:

  • Vocal Trance (sottopagina)
  • hard Trance (sottopagina)

Breaks:

  • Atmo Breaks (sotto pagina)
  • interruzioni progressive (sotto pagina)

Come posso accedervi da urls.py? Quale modello sarà d'aiuto? Devo memorizzare Full_path nel modello o può essere eseguito tramite url pattern?

risposta

7

Presumo vuoi dire che si vuole fare gli URL come questo:

/trance/ 
/trance/vocal-trance/ 
/trance/hard-trace/ 
/breaks/ 
/breaks/atmo-breaks/ 
/breaks/progressive-breaks/ 

Se è così, è probabilmente meglio per memorizzare il frammento di URL nel modello. Qualcosa di simile:

from mptt.models import MPTTModel 
from django.db import models 
from django.template.defaultfilters import slugify 

class Page(MPTTModel): 
    name = models.CharField(max_length=50) 
    slug = models.CharField(max_length=50,null=True) 
    url = models.CharField(max_length=255,null=True) 

    def save(self, *args, **kwargs) 
     if self.slug is None: 
      # create a slug that's unique to siblings 
      slug = slugify(self.name) 
      self.slug = slug 
      siblings = self.get_siblings() 
      i = 1 
      while siblings.filter(slug=self.slug).exists(): 
       i += 1 
       self.slug = slug + '-%d' % i 

      # now create a URL based on parent's url + slug 
      if self.parent: 
       self.url = '%s/%s' % (self.parent.url, self.slug) 
      else: 
       self.url = self.slug 
     super(Page, self).save(*args, **kwargs) 

quindi aggiungere un modello URL:

(r'^pages/(?P<page_url>[\w\d_/-]+)/$', 'pages.views.show_page'), 

E secondo lei si può solo prendere giusta pagina:

def show_page(request, page_url=None): 
    page = get_object_or_404(Page, url=page_url) 
    ... 
+2

Che dire quando si modifica una radice/ramo lumaca e necessario aggiornare gli URL discendenti? – jozxyqk

6

Grazie per la vostra attenzione al mio problema . Vedi, come finalmente lo faccio.

models.py

class WebPage(MPTTModel): 

    slug=RuSlugField(max_length=20,unique=True) 
    title=models.CharField(max_length=50) 
    content=models.TextField() 
    parent=TreeForeignKey('self',null=True,blank=True,related_name='children') 

    class MPTTMeta: 
     order_insertion_by=['slug'] 

    def get_absolute_url(self):#TODO:: replace with get_ancestors 
     url = "/%s/" % self.slug 
     page = self 
     while page.parent: 
      url = "/%s%s" % (page.parent.slug,url) 
      page = page.parent 
     return url 

urls.py

urlpatterns = patterns('website.views', 
    url(r"^add/$", "add_page",name="add"), 
    url(r"^(?P<full_slug>.*)/add/$", "add_page",name="add"), 
    url(r"^(?P<full_slug>.*)/edit/$", "edit_page",name="edit"), 
    url(r'^$', ListView.as_view(model=WebPage,template_name='index.html',context_object_name="webpages_list",),name='index'), 
    url(r"^(?P<full_slug>.*)/$", "page", name="page"), 
) 

views.py

def page(request, full_slug): 

    # Make a list from full_slug. 
    # For ex. /trance/progressive_trance/fonarev -> ['trance','progressive_trance','fonarev'] 
    slugs=full_slug.split('/') 

    page=None 

    # Get a page by it's slug 
    if len(slugs)>1: 
     page=get_object_or_404(WebPage,slug=slugs[-1])#slugs=['trance','vocal_trance'] -> 'vocal_trance' 
    elif len(slugs)==1: 
     page=get_object_or_404(WebPage,slug=slugs[0])#slugs=['trance'] -> 'trance' 

    # Check if page url matches requested full_slug 
    if page.get_absolute_url().strip('/') == full_slug: 
     return render_to_response('page.html', {'page': page},context_instance=RequestContext(request)) 
    else: 
     raise Http404 

def edit_page(request,full_slug): 
    slugs=full_slug.split('/') 
    page=None 

    if len(slugs)>1: 
     page=get_object_or_404(WebPage,slug=slugs[-1]) 
    elif len(slugs)==1: 
     page=get_object_or_404(WebPage,slug=slugs[0]) 

    if not page.get_absolute_url().strip('/') == full_slug: 
     raise Http404 

    # Send POST data for update an existing page.Update a page. 
    if request.method=='POST': 
     form=WebPageForm(request.POST, instance=page) 
     if form.is_valid(): 
      form.save() 
     return HttpResponseRedirect(page.get_absolute_url()) 

    # Render a form to edit data for existing page 
    else: 
     form=WebPageForm(instance=page) 

    return render_to_response('edit_page.html',{'form':form,},context_instance=RequestContext(request)) 

def add_page(request,full_slug=None): 
    parent_page=None 
    slug=None 

    if full_slug: 
     slug=full_slug.split('/') 

    # If there is a slug in REQUEST(ex.'trance')->we need to add a new_page to her parent_page. 
    # So get a parent page. 
    if slug: 
     if len(slug)>1: 
      parent_page=get_object_or_404(WebPage,slug=slug[-1]) 
     elif len(slug)==1: 
      parent_page=get_object_or_404(WebPage,slug=slug[0]) 

    # Create a new_page 
    if request.method=='POST': 
     form=WebPageForm(request.POST) 
     if form.is_valid(): 
      new_page=form.save(commit=False) 
      if parent_page: 
       new_page.parent=parent_page 
      new_page.save() 
      return HttpResponseRedirect(new_page.get_absolute_url()) 

    # Return an unbounded form 
    else: 
     form=WebPageForm() 

return render_to_response('add_page.html',{'form':form,},context_instance=RequestContext(request)) 

Il trucco sta nel dobbiamo controllare se la pagina esiste davvero accedendo tramite full_slug:

if not page.get_absolute_url().strip('/') == full_slug: 
      raise Http404 

In caso contrario, potrebbe essere sbagliato consentendo di controllare solo da slug.

+0

+1 per mettere CRUD anche con questa funzionalità. – Soask

2

C'è anche un app Django che farà il lavoro per voi: django-mptt-urls

+0

SÌ, sostituire "un'app" in favore di "un'applicazione django" è DAVVERO EDITORE! anatoly techtonik, ora pregherò per te e per @Forethinker – MrKsn

0
def get_absolute_url(self): 
    return '/'.join([x['slug'] for x in self.get_ancestors(include_self=True).values()]) 
Problemi correlati