【问题标题】:Django-MPTT full path to child pages how to make?Django-MPTT子页面的完整路径如何制作?
【发布时间】:2012-05-05 09:51:43
【问题描述】:

我开始使用 Django-MPTT 应用程序在我的 Django 站点页面上获取基于树的方法。

例如。我有带有子页面的页面:

恍惚:

  • Vocal Trance(子页面)
  • Hard Trance(子页面)

休息:

  • Atmo Breaks(子页面)
  • 渐进式休息(子页面)

如何从 urls.py 访问它们? 什么模式会有所帮助? 我需要将 Full_path 存储在模型中还是可以通过 url 模式完成?

【问题讨论】:

    标签: django-urls django-mptt


    【解决方案1】:

    我假设你的意思是你想做这样的 URL:

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

    如果是这样,最好将 url 片段存储在模型中。比如:

    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)
    

    然后添加一个 URL 模式:

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

    在您看来,您只需获取正确的页面:

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

    【讨论】:

    • 当你修改一个根/分支 slug 并且需要更新后代 url 时怎么办?
    【解决方案2】:

    感谢您关注我的问题。 看看,我最后是怎么做到的。

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

    诀窍在于我们必须检查页面是否真的存在通过 full_slug 访问它:

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

    否则,只允许通过 slug 进行检查可能是错误的。

    【讨论】:

      【解决方案3】:

      还有一个 django 应用程序可以为您完成工作:django-mptt-urls

      【讨论】:

      • 是的,将 'an app' 替换为 'a django app' 是一个非常值得的编辑! anatoly techtonik,现在我会为你和@Forethinker 祈祷
      【解决方案4】:
      def get_absolute_url(self):
          return '/'.join([x['slug'] for x in self.get_ancestors(include_self=True).values()])
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-01-16
        • 2011-04-22
        • 2020-08-03
        • 2018-12-04
        • 1970-01-01
        • 1970-01-01
        • 2021-03-28
        • 1970-01-01
        相关资源
        最近更新 更多