Добавление слагов в шаблон URL - PullRequest
1 голос
/ 28 апреля 2020

[Исходное сообщение]

Я хочу, чтобы пользователи получали доступ к сообщениям, используя значение PK или Slug. Я могу заставить http://localhost: 8000 / должность / 8 / работать, но не http://localhost: 8000 / должность / работа в Малайзии / .

Я просмотрел несколько сообщений о переполнении стека, но я не хочу http://localhost: 8000 / post / 8 / working-in-malaysia . И я не хочу, чтобы это касалось работы ПК. Или слизняк работает. Я хочу, чтобы пользователь мог войти либо.

Ниже вы можете увидеть мои неудачные попытки.

urls.py

path('post/<int:pk>/', views.post_detail, name='post-detail'),
#path('post/<slug:the_slug>/', views.post_detail, name='post-detail-slug'),
#path('post/<slug:slug>/', views.post_detail, name='post-detail-slug'),
#path('post/(?P<slug>[-\w]+)/$', views.post_detail, name='post-detail-slug'),
path('<slug:slug>', views.post_detail, name='post-detail-slug'),

enter image description here

[Обновления после просмотра комментариев Дэниела Морелла]

views.py

class PostDetailView(DetailView):
    model = Post

    def dispatch(pk_slug):
        if pk_slug.isdigit():
          post = Post.objects.filter(id=pk_slug).first()
        else:
          post = Post.objects.filter(slug=pk_slug).first()

        #post = get_object_or_404(Post)
        comments = post.comments.filter(active=True, slug=slug)
        new_comment = None

        if request.method == 'POST':
            comment_form = CommentForm(data=request.POST)
            if comment_form.is_valid():
                new_comment = comment_form.save(commit=False)
                new_comment.post = post
                new_comment.save()
            else:
                comment_form = CommentForm()
                return render(request, post_detail.html, {'post': post,
                                           'comments': comments,
                                           'new_comment': new_comment,
                                          'comment_form': comment_form})

urls.py

path('', PostListView.as_view(), name='blog-home'),
path('post/<slug:pk_slug>', views.post_detail, name='post-detail'),
path('post/new/', PostCreateView.as_view(), name='post-create'),

models.py

def get_absolute_url(self):
        #return reverse('article_detail', kwargs={'slug': self.slug})
        return reverse('post-detail', kwargs={'pk': self.pk})

[Обновления после просмотра Даниэля Морелла 2-й лот комментариев]

views.py

 pk_slug = self.kwargs.get(self.slug_url_kwarg)
        # If the pk_slug is not None and it is just digits treat as pk
        # Otherwise if it is not None treat as slug
        if pk_slug is not None and pk_slug.isdigit():
          queryset = queryset.filter(pk=pk_slug)
        else pk_slug is not None:
          slug_field = self.get_slug_field()
          queryset = queryset.filter(**{slug_field: pk_slug})

enter image description here

Командная строка

File "C:\Users\HP\django_project3\blog\views.py", line 55
    else pk_slug is not None:
               ^

SyntaxError: invalid syntax

[Проблема решена]

По неизвестным причинам у меня были FBV (представление на основе функций) и CBV (представление на основе классов) с похожим кодом. Оригинальное предложение Даниэля Морелла сработало в предположении, что я использую FBV.

Я, к сожалению, потратил впустую его время, показав ему свой код с CBV. Что означало, что он переписал свое решение. Затем я обнаружил, что код FBV является избыточным, а код CBV - правильным.

Ниже мой последний набор кода. Эта ссылка на оригинальное предложение Дэниела Морелла - { ссылка }.

Я новичок с Python и даже не знал, что вчера означало аббревиатура CBV.

views.py

def post_detail(request, pk_slug):
    template_name = 'post_detail.html'



    if pk_slug.isdigit():
      post = Post.objects.filter(id=pk_slug).first()
    else:
      post = Post.objects.filter(url=pk_slug).first()

    comments = Comment.objects.filter(post=post.id ,active=True)
    #post = Post.objects.get(pk=pk)
    new_comment = None
    # Comment posted
    if request.method == 'POST':
        comment_form = CommentForm(data=request.POST)
        if comment_form.is_valid():

            # Create Comment object but don't save to database yet
            new_comment = comment_form.save(commit=False)
            # Assign the current post to the comment
            new_comment.post = post
            # Save the comment to the database
            new_comment.save()
    else:
        comment_form = CommentForm()

    return render(request, template_name, {'post': post,
                                           'comments': comments,
                                           'new_comment': new_comment,
                                           'comment_form': comment_form})

urls.py

path('post/<slug:pk_slug>/', views.post_detail, name='post-detail'),

Ответы [ 2 ]

1 голос
/ 28 апреля 2020

Существует способ упростить настройку URL-адреса. <slug:__> будет соответствовать любой строке букв ASCII, цифр, дефисов или подчеркиваний. Это означает, что вы можете использовать slug для соответствия первичному ключу.

Это немного отличается. Поэтому вы должны добавить комментарий к вашему urlpatterns, пояснив, что он соответствует pk и slug.

Вот пример.

# urls.py

urlpatterns = [
    # This matches both the primary key and the slug.
    path('post/<slug:pk_slug>/', views.PostDetailView.as_view(), name='post-detail')
]
# views.py

from django.db.models import Q

class PostDetailView(DetailView):
    model = Post
    slug_url_kwarg = 'pk_slug'

    def get_object(self, queryset=None):
        # This function overrides DetialView.get_object()

        # Use a custom queryset if provided; this is required for subclasses
        if queryset is None:
            queryset = self.get_queryset()

        # Next, look up our primary key or slug
        pk_slug = self.kwargs.get(self.slug_url_kwarg)

        # If the pk_slug is not None and it is just digits treat as pk
        if pk_slug is not None and pk_slug.isdigit():
            queryset = queryset.filter(pk=pk_slug)

        # Otherwise if it is not None treat as slug
        elif pk_slug is not None:
            slug_field = self.get_slug_field()
            queryset = queryset.filter(**{slug_field: pk_slug})

        # Raise an error if there is no pk_slug in the URLconf
        if pk_slug is None:
            raise AttributeError(
                "Generic detail view %s must be called with an object "
                "pk_slug in the URLconf." % self.__class__.__name__
            )

        try:
            # Get the single item from the filtered queryset
            obj = queryset.get()
        except queryset.model.DoesNotExist:
            raise Http404(_("No %(verbose_name)s found matching the query") %
                          {'verbose_name': queryset.model._meta.verbose_name})
        return obj

The * Метод 1014 * возвращает значение true, если каждый символ в строке является ди git, а строка содержит хотя бы один символ.

Таким образом, все следующие URL-адреса будут использоваться для соответствия первичному ключу ...

  • /post/123/
  • /post/4/
  • /post/80/

И все последующие будут интерпретироваться как слизни ...

  • /post/my-first-post/
  • /post/23-a-post-slug/
  • /post/123b/

Примечание: это не будет работать со слагом который состоит из всех цифр.

Вы должны добавить правило проверки в вашу форму сообщения, чтобы убедиться, что слаг имеет не-ди git символ в нем.

1 голос
/ 28 апреля 2020

Этого можно добиться, используя метод djangos re_path и регулярные выражения. Документы:

https://docs.djangoproject.com/en/3.0/topics/http/urls/#nested -аргументы https://docs.djangoproject.com/en/3.0/ref/urls/#re -path

Было бы что-то вроде этого, хотя это не сработает, просто чтобы дать вам представление:

re_path(r'^post/(?P<pk:int>\d+)|(?P<slug:slug>\w+)/$', ...)

Вы можете попробовать регулярное выражение с помощью таких инструментов, как https://regexr.com/. Просто создайте несколько URL-адресов, которые вы ожидаете, и используйте платформу, чтобы найти правильный шаблон регулярных выражений. Я сам не пробовал, поэтому не могу точно сказать, как это делается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...