Django-MPTT full path to child pages how to make?

前端 未结 4 1995
失恋的感觉
失恋的感觉 2021-02-04 18:21

I\'m start using Django-MPTT app to get a tree-based approach on my Django-site pages.

For ex. I have pages with sub pages:

Trance:

  • Vocal Trance(su
相关标签:
4条回答
  • 2021-02-04 18:47

    I assume you mean you want to do URLs like this:

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

    If so, it's probably best to store the url fragment in your model. Something like:

    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)
    

    Then add a URL pattern:

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

    And in your view you can just fetch the right page:

    def show_page(request, page_url=None):
        page = get_object_or_404(Page, url=page_url)
        ...
    
    0 讨论(0)
  • 2021-02-04 18:50

    There's also a django app that will do the work for you: django-mptt-urls

    0 讨论(0)
  • 2021-02-04 18:58

    Thank you for your attention to my problem. See,How I finally do it.

    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))
    

    The trick is in we have to check if the page really exists accessing to it via full_slug:

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

    Otherwise, it could be wrong allowing to check only by slug.

    0 讨论(0)
  • 2021-02-04 19:11
    def get_absolute_url(self):
        return '/'.join([x['slug'] for x in self.get_ancestors(include_self=True).values()])
    
    0 讨论(0)
提交回复
热议问题