Django P3로 구축된 리테일 웹사이트 (2020-02-07)

22888 단어 djangodailynotes

장고:




urls.py에서 어느 것이 먼저 가는지 주의하세요.




app_name = 'boutique'
urlpatterns = [
    # show index page
    path('', views.IndexView.as_view(), name='index'),

    # show a specific item
    path('item_<int:item_pk>/', views.ItemDetailView.as_view(), name='item'),

    # show categories of products for men or women
    path('<slug:gender>/', views.CategoryListView.as_view(), name='show-all'),

    # show a specific category for men or women
    path('<slug:gender>/cat_<int:category_pk>/', views.CategoryListView.as_view(), name='category'),

    # show a specific subcategory under a specific category for men or women
    path('<slug:gender>/cat_<int:category_pk>/subcat_<int:subcategory_pk>/', views.CategoryListView.as_view(), name='subcategory'),

]


이 파일에서 item 뒤에 subcategory를 넣으면 item 보기가 올바른 페이지를 렌더링하지 않습니다.


모델 - 성별 선택



아래 예:

class Category(models.Model):
    '''Category for men's and women's items'''
    gender = models.IntegerField(choices=[
        (1, 'Women'),
        (2, 'Men'),
    ], default=1)
    name = models.CharField(max_length=100)
    description = models.CharField(max_length=300, blank=True)
    uploaded_date = models.DateTimeField(
        auto_now_add=True, null=True, blank=True)

    class Meta():
        verbose_name_plural = 'Categories'

    def __str__(self):
        return self.get_gender_display() + ' ' + self.name

    def get_category_url(self):
        return reverse('boutique:category', kwargs={'gender': self.get_gender_display(), 'category_pk': self.pk})


이 예에서 주목해야 할 몇 가지 사항은 다음과 같습니다.


  • 성별 선택:
    *ListView는 소문자
    * choices는 튜플
  • 이 포함된 목록입니다.
  • 성별 선택에 액세스: choices를 사용하여 필드 선택에 액세스할 수 있습니다. this에서 자세한 내용
  • 을 확인하세요.



    def get_absolute_url()의 get_FOO_display()



    models.py

    from django.urls import reverse
    
    class SomeModel(models.Model):
        <---snip--->
    
        # it can be any name you like because it doesn't seem to be inheriting from anything
        def get_absolute_url(self):
            return reverse('app_name:view_name', kwargs={'key': self.field_name})
            # reverse returns a string for href content
    


    URL을 html 태그로 구현할 때 SomeModel이 액세스 가능한지 확인하십시오(반복을 통해 또는 컨텍스트를 통해 전달된 객체임).
    *html

    <a href="{{ SomeModel.get_absolute_url }}">link</a>
    


    동적 처리 URL: 내가 게시한 SO 질문을 확인하세요.



    Mathias의 답변에 따르면 django-middleware-global-request을 설치하지 않으면 불가능합니다.
    그런 다음 다음을 수행할 수 있습니다.

    from django_global_request.middleware import get_request
    
    class TestModel(models.Model):
    
        ...
    
        def get_absolute_url(self):
            request = get_request()
    
            if request.GET.get('whatever'):
                return ...
            else:
                return ...
    


    You just need to make sure, you could still access this method without any available request. So make sure it's fail save and has a fallback in case of the absence of a request (like in a shell, upgrade, etc.)




    get_context_data(self, **kwargs)의 models.py 및 get_queryset(self) - CCBV


  • _ ListViewget_queryset() 에서 더 유용합니다. 렌더링할 템플릿에 대한 쿼리 세트를 반환하기 때문입니다. ListView 가 컨텍스트를 통해 자동으로 전달됩니다! _

  • 모델이 CBV에 정의되어 있으면 queryset가 자동으로 실행되고 get_queryset()를 획득합니다.

  •   class SomeView(ListView):
        <---snip--->
        # context_object_name represents the result of get_queryset()
        # you can directly access this from the template even if you do not set context_object_name
        context_object_name = 'coobna'
    
    
        def get_queryset(self):
          # if you still need the default functionality of this function
          # it's like to inherite from it's superior, instead of writing a whole new function
          queryset = super().get_queryset()
    
          # before returning the queryset, you can print(queryset) to debug or for referencing purposes
          return queryset.filter(........)
    
    
        def get_context_data(self, **kwargs):
          # inherite the functionality from its 'superior'
          context = super().get_context_data(**kwargs)
    
          # now you can add more context to it
          new_context = Category.objects.all()
          context['new_context'] = new_context
    
          # you can always print out the context for debugging
          print(context)
          return context
    



  • ListView의 예:

  •   class CategoryListView(ListView):
        '''display a list of items'''
        model = Category
        template_name = 'boutique/items.html'
        # context_object_name is actually the result of `get_queryset()`
        context_object_name = 'category_shown'
        # paginate_by = 12
    
        def get_queryset(self):
            # get original queryset: Category.objects.all()
            qs = super().get_queryset()
    
            # filter men/women
            if self.kwargs.get('gender') == 'Women':
                qs = qs.filter(gender=1)
            elif self.kwargs['gender'] == 'Men':
                qs = qs.filter(gender=2)
    
            if self.kwargs.get('category_pk'):
                qs = qs.filter(pk=self.kwargs.get('category_pk'))
    
            # print('\nqs= ', qs, '\n')
            return qs
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            # add categories for navbar link texts
            context['categories'] = Category.objects.all()
    
            if self.kwargs.get('subcategory_pk'):
                context['subcategory_shown'] = get_object_or_404(
                    SubCategory, pk=self.kwargs.get('subcategory_pk'))
                context['item_list'] = Item.objects.filter(
                    subcategory=self.kwargs.get('subcategory_pk'))
                # print('\ncontext with subcat= ', context, '\n')
                return context
    
            # Because context_object_name actually represents the result of `get_queryset()`
            # Therefore, if context_object_name is set to the same name as the context name
            # the following expression can be omitted
            # context['category_shown'] = self.get_queryset()
            # The benefit of this is you don't need to run get_queryset() again!!
    
            if self.kwargs.get('category_pk'):
                context['item_list'] = Item.objects.filter(
                    category=self.kwargs.get('category_pk'))
    
            # print('\ncontext= ', context, '\n')
            return context
    



    CCBV의 상세보기



    예시

    class ItemDetailView(DetailView):
        '''display an individual item'''
        model = Item
        template_name = 'boutique/item.html'
        # no need to specify as default context_object_name depends on the model
        # they are actually the same (with lower case first letter)
        # context_object_name = 'item'
    


    몇 가지 참고 사항:
  • context_object_name(위 설명 참조)
  • 항목의 표준 DetailView를 표시하려면 두 줄이면 충분합니다.
    ### 하지만:
    CBV로 전달되는 URL 값(StackO의 체크아웃my question)에 대해 매우 주의해야 합니다.
    url.py

  • urlpatterns = [
        path('item_<int:pk>/', views.ItemDetailView.as_view(), name='item'),
    ]
    


    나는 model.objects.all()를 사용했기 때문에 작동하지 않았습니다. DetailView가 작동하려면 path('item_<int:item_pk>/'...)를 전달하거나 <pk>의 CBV를 지정해야 합니다. docs

    좋은 웹페이지 즐겨찾기