Django 中的自定义 url 模式

Posted

技术标签:

【中文标题】Django 中的自定义 url 模式【英文标题】:custom url patterns in Django 【发布时间】:2019-07-03 02:22:02 【问题描述】:

我有一个我正在尝试建立供个人使用的网站,它有两个 id,一个用于会议(进行比赛),一个用于活动(比赛编号)。事件id的形式为“123456_01”,作为Event模型的主键传入模型中,如下图...

class Event(models.Model):
    meeting = models.CharField(max_length=500)
    meetingID = models.ForeignKey(Meeting, on_delete='CASCADE', related_name='races')
    eventID = models.CharField(max_length=300, primary_key=True)
    venue = models.CharField(max_length=600, null=True)
    race_no = models.CharField(max_length=2)
    event_time = models.TimeField()
    status = models.CharField(max_length=100)
    distance = models.CharField(max_length=600)

我目前的视图文件设置如下:

class EventDetailView(DetailView,LoginRequiredMixin):
    context_object_name = 'race_detail'
    template_name = 'event.html'
    model = models.Event
    slug_url_kwarg = 'eventID'

我还设置了我的前端,以便目前当我点击某个比赛时,它会自动导航到带有链接 http://127.0.0.1:8000/app/123456_01/ 的页面,因此该部分正在通过 HTML 中的此配置工作:

% url 'bettingUI:race' eventID=events.eventID %

我似乎遇到的问题是 urls.py 文件的配置,可能是我在 views.py 文件中缺少的东西。

我的 urls.py 文件设置如下:

from django.urls import path, include
from . import views

app_name = 'bettingUI'

urlpatterns = [
    path('',views.DashListView.as_view(),name='dashboard'),
    path('<eventID>/', views.EventDetailView.as_view(), name='race'),   

]

我在阅读文档时认为我需要使用 slug,因为我传入的 ID 中包含“_”字符,但我在浏览器中不断收到错误消息,指出它无法解析关键字“slug”进入领域。选项有:dro_eventID、dro_meetingID、dro_meetingID_id、event_time、meeting、race_no、runners、status、venue(**模型的字段)。如果我将 urls.py 文件更改为以下内容,我会收到相同的错误:

   path('<slug:eventID>/', views.EventDetailView.as_view(), name='race'),

我有点迷路了,所以希望得到一些指导。

谢谢。


我算出来了,答案是输入&lt;slug:pk&gt;

但现在我的仪表板页面出现错误(我登陆以点击进入比赛页面的页面):

NoReverseMatch at /app/
Reverse for 'race' with keyword arguments ''eventID': '1216859_01'' not found. 1 pattern(s) tried: ['app/(?P<pk>[-a-zA-Z0-9_]+)/$']

【问题讨论】:

我觉得应该是&lt;slug:eventID&gt; 不,那行不通 【参考方案1】:

所以我现在再次给它工作版本:

首先,您应该在事件模型中添加一个slug 字段,这样您就可以使用 slug,因此您的模型将如下所示:

from django.utils.text import slugify

class Event(models.Model):
    meeting = models.CharField(max_length=500)
    meetingID = models.ForeignKey(Meeting, on_delete='CASCADE', related_name='races')
    eventID = models.CharField(max_length=300, primary_key=True)
    venue = models.CharField(max_length=600, null=True)
    race_no = models.CharField(max_length=2)
    event_time = models.TimeField(null=True)
    status = models.CharField(max_length=100, null=True)
    distance = models.CharField(max_length=600, null=True)
    slug = models.SlugField(max_length=50, null=True)

    def save(self, *args, **kwargs):
        self.slug = slugify(self.eventID, allow_unicode=True)
        return super(Event, self).save(*args, **kwargs)

注意save() 函数,我们添加了一个 slugify() 方法来在事件保存时对 eventID 字段进行 slugify。

那么您的视图应该如下所示:

from .models import Event, Meeting

class EventList(ListView):
    model = Event
    template_name = 'event_list.html'
    context_object_name = 'race_list'    

class EventDetailView(DetailView,LoginRequiredMixin):
    context_object_name = 'race_detail'
    template_name = 'myusers1/event.html' # this could be only event.html if the template is in yourapp/templates/ folder directly
    model = Event
    slug_url_kwarg = 'slug'

请注意,在上面的视图中,我们现在实际上使用 默认 slug 定义。

我将 listview url 放在 races/ 子 url 下,但你可以将它放在任何你想要的地方。在您的 urls.py 中,您现在可以正确使用 slug 值,例如:

path('races/<slug:slug>/', views.EventDetailView.as_view(), name='race'),
path('races/', views.EventList.as_view(), name='race_list'),

在我的试用应用中,模板如下所示:listview 模板:

% extends 'myusers1/base.html' %

% block content %

<div class"container">
  <div class="col col-lg-2">
    <h2>Races</h2>
        <ul>
            % for race in race_list %
                <div class="col-xs-12 .col-md-8"><li><a href="% url 'Myusers1:race' slug=race.slug %">  race.venue  </a> </li></div>
            % endfor %
        </ul>
  </div>
</div>

% endblock %

详细模板如下所示:

% extends 'myusers1/base.html' %

% block content %

<div class"container">
  <div class="col col-lg-2">

    <h2>Race Details</h2>

            <div class="col-xs-12 .col-md-8"> <h4>Venue name: </h4>  race_detail.venue </div>
            <div class="col-xs-12 .col-md-8"> <h4>Event ID: </h4>  race_detail.eventID  </div>
            <div class="col-xs-12 .col-md-8"> <h4>Meeting name: </h4>  race_detail.meeting  </div>
            <div class="col-xs-12 .col-md-8"> <h4>Meeting ID: </h4>  race_detail.meetingID.id  </div>

  </div>
</div>

% endblock %

以及关于动态 url 如何使用上述内容的视觉结果:

我希望以上内容可以帮助您现在完成您的应用列表和详细信息视图。干杯。

【讨论】:

【参考方案2】:

我想我在这里找到了解决方案,试试这个:

url.py:

 path('<slug:eventID>/', views.EventDetailView.as_view(), name='race')

现在您可以使用get_object 方法在您的EventDetailView 通用视图中简单地获取Event 的实例,如下所示:

class EventDetailView(DetailView, LoginRequiredMixin):
     context_object_name = 'race_detail'
     template_name = 'event.html'
     model = models.Event

     def get_object(self):          
         e1 = Event.objects.get(eventID=self.kwargs['eventID'])
         print (e1.eventID) # or e1.pk gives: 123456_01
         return e1

您还可以将您的 eventIDCharField 更改为 SlugField。并且仍然可以正常工作。

【讨论】:

以上是关于Django 中的自定义 url 模式的主要内容,如果未能解决你的问题,请参考以下文章

具有父 url 参数的自定义 Django 管理站点

如何使用 django-filters 过滤 ModelViewSet 中的自定义 url

JWT 身份验证不适用于 Django 中的自定义控制器

如何在 django 的自定义过滤器中使用 % url % 来显示主题标签

django admin changelist_view 中的自定义 html 字段

django的自定义权限