Django 项目中的动态子域和 url 路径

Dynamic subdomains and url paths in django project

我正在尝试在我的 django 项目中实现动态子域和 urls 系统。

一般来说,每个用户都有自己的域,例如。 myusername.example.com 用户可以定义动态 URL,例如:

但我在 example.com 上也有我的网站 运行,其中有 urls like example.com/contact、example.com/about-us 等等。

我希望所有这些 URL 都指向我的自定义视图(基于 class),我在其中执行一些数据库查询和 return 动态内容。这个 somethin1/something2 部分是完全动态的,可能有任何东西。由用户定义。

我有这样的东西:

urls.py

from web.views import HomeView, ContactView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('contact', ContactView.as_view()),
    path('', HomeView.as_view()),
    re_path('.*', HomeView.as_view())
]

web.views.py

class HomeView(TemplateView):
    template_name = 'home.html'

    def dispatch(self, request, *args, **kwargs):

        SERVICE_DOMAIN = settings.DOMAIN

        http_host = str(request.META.get('HTTP_HOST'))

        if SERVICE_DOMAIN in http_host:
            subdomains = http_host.split(SERVICE_DOMAIN)[0]
            subdomain = slugify.slugify(subdomains)
        else:
            subdomain = False

        if subdomain:
            print('Our subdomain is {}'.format(subdomain))
            kwargs['subdomain'] = subdomain
            return CustomUrlView.as_view()(self.request, *args, **kwargs)

        if not subdomain:
            print('run normally')
            return super().dispatch(request, *args, **kwargs)

class CustomUrlView(View):
    def dispatch(self, request, *args, **kwargs):
        subdomain = kwargs.get('subdomain')
        url = request.META.get('PATH_INFO').lower().strip().replace('/', '', 1)
        # here I do some queries in DB with my url variable - it has own model etc.

一般来说,几乎所有用户定义的 urls 一切正常... 问题是当访问者打开 myusername.example.com/contact - 它总是匹配 urls.py 中定义的 url 并且它没有被我的 HomeView 捕获。

我该如何解决?当请求来自子域时,我不想使用我在 urls.py 中定义的任何基于 class 的视图的 url。

您需要有两个不同的 urls 文件。一个用于域,第二个用于子域。

  • 在两个 url 文件中拆分域和子域视图。如果您有适用于两者的观点,例如登录,创建一个 "common" 文件并包含在两个 url 中。
  • 您可以选择要使用的 url,因此创建一个中间件并检查主机 request.META.get('HTTP_HOST')。如果请求来自子域,则只需加载适当的 urls request.urlconf = 'path.to_subdomain.urls'

注意: 确保 settings.py 中的 ROOT_URLCONF 指向“域” url。此外,在你的中间件中,你应该检查子域是否存在,如果不存在,则 return 404不存在。