简体   繁体   English

在 Django 模板中分页时如何正确显示与其父模型字段关联的所有内联字段?

[英]How to properly display all inline fields associated with its parent model fields when paginating in Django template?

I'm a student and a Django newbie, and we have a project that we're trying to build using Django.我是一名学生和 Django 新手,我们有一个项目正在尝试使用 Django 构建。 In my journey to building the project I stumbled upon a problem and got stuck for weeks now.在我构建项目的过程中,我偶然发现了一个问题,现在卡住了好几个星期。

I want to display all the inline fields associated with its parent field on one page as I paginate.我想在分页时在一页上显示与其父字段关联的所有内联字段。 When I tried to paginate a model with 2 additional models that have foreign keys to it I got a weird result in my template.当我尝试使用具有外键的 2 个附加模型对模型进行分页时,我在模板中得到了一个奇怪的结果。 I can't seem to figure out how to fix it.我似乎无法弄清楚如何解决它。 I tried several methods on the Internet and have read numerous forums and discussions but to no avail, none has worked so far.我在互联网上尝试了几种方法,并阅读了许多论坛和讨论,但无济于事,到目前为止都没有奏效。 Below are my files and a few Images:以下是我的文件和一些图片:


(models.py) (模型.py)

from django.db import models

class History(models.Model):
   BARANGAY = (
     ('Alegria','Alegria'),
     ('Bagacay','Bagacay'),
     ('Baluntay','Baluntay'),
     ('Datal Anggas','Datal Anggas'),
     ('Domolok','Domolok'),
     ('Kawas','Kawas'),
     ('Ladol','Ladol'),
     ('Maribulan','Maribulan'),
     ('Pag-Asa','Pag-Asa'),
     ('Paraiso','Paraiso'),
     ('Poblacion','Poblacion'),
     ('Spring','Spring'),
     ('Tokawal','Tokawal')
   )
  barangay_name = models.CharField(max_length=100,choices=BARANGAY,default='Alegria')
  barangay_img = models.ImageField(upload_to='history_imgs',blank=True)
  barangay_info = models.TextField()

class GeoHazard(models.Model):
  history = models.ForeignKey(History,related_name='geohazards',on_delete=models.CASCADE)
  geohazard_img = models.ImageField(upload_to='history_imgs',blank=True)
  date_published = models.CharField(max_length=100, null=True)
  geohazard_info = models.TextField()

class Assessment(models.Model):
   RATINGS = (
      ('HIGH','HIGH'),
      ('HIGH (Mitigated)','HIGH (Mitigated)'),
      ('MODERATE','MODERATE'),
      ('MODERATE (Mitigated)','MODERATE (Mitigated)'),
      ('LOW','LOW'),
      ('UNKNOWN','UNKNOWN'),
   )

   history = models.ForeignKey(History,related_name='assessment',on_delete=models.CASCADE)
   purok_name = models.CharField(max_length=50)
   purok_coordinates = models.CharField(max_length=100,default='unknown')
   flood_rating = models.CharField(max_length=100,choices=RATINGS,default='UNKNOWN')
   landslide_rating = models.CharField(max_length=100,choices=RATINGS,default='UNKNOWN')

In my models.py I have the parent model 'History' and two additional models 'GeoHazard' and 'Assessment' both having foreign keys.在我的 models.py 中,我有父模型“History”和两个附加模型“GeoHazard”和“Assessment”,它们都具有外键。


admin-dashboard.png管理仪表板.png

(admin.py) (管理员.py)

from django.contrib import admin

from auxiliary.models import (
   History, 
   GeoHazard,
   Assessment
)
class GeoHazardInline(admin.StackedInline):
   model = GeoHazard
   extra = 0

class AssessmentInline(admin.StackedInline):
   model = Assessment
   extra = 0

class HistoryAdmin(admin.ModelAdmin):
   inlines = [GeoHazardInline,AssessmentInline]

admin.site.register(History,HistoryAdmin)

In my admin.py I am using 'StackedInline'.在我的 admin.py 中,我使用的是“StackedInline”。 I structured it this way so that the parent model 'History' can have multiple inline fields associated with it.我以这种方式构造它,以便父模型“历史”可以有多个与之关联的内联字段。


(views.py #1) (views.py #1)

class history(ListView):
   model = History
   template_name = 'auxiliary/history.html'
   context_object_name = 'histories'
   paginate_by = 1

Initially, I used 'ListView' to take advantage on its pre-built pagination method 'paginate_by' but by doing so the template resulted to this (see image below).最初,我使用“ListView”来利用其预先构建的分页方法“paginate_by”,但这样做模板导致了这一点(见下图)。 As u guys can see the inline fields are paginated_by '1' as well, and the other inline fields got separated from the first page.正如你们所看到的,内联字段也是 paginated_by '1',并且其他内联字段与第一页分开。

template-views1.png)模板-views1.png)


(views.py #2) (views.py #2)

class HistoryView(ListView):
   model = History
   template_name = 'auxiliary/history.html'
   context_object_name = 'histories'
   paginate_by = 1

def get_context_data(self, **kwargs):
       context = super(HistoryView, self).get_context_data(**kwargs)
       context.update({
           'geohazards': GeoHazard.objects.all(),
           'assessments': Assessment.objects.all()
          })

       return context

So I tried a different approach;所以我尝试了一种不同的方法; now by having 3 models passed in my 'ListView' by overriding the 'context' using get_context_data.现在通过使用 get_context_data 覆盖“上下文”,在我的“ListView”中传递 3 个模型。 In this approach all the inline fields are displayed in my template template-views2-A.png , but this time it raises a new issue, even though all the inline fields are displayed in the template It wasn't with their associated parent fields.在这种方法中,所有内联字段都显示在我的模板template-views2-A.png中,但这一次引发了一个新问题,即使所有内联字段都显示在模板中,但它并没有与其关联的父字段一起显示。 Now when selecting a new page in my pagination buttons the parent field changes template-views2-B.png but the inline fields remain the same.现在,在我的分页按钮中选择新页面时,父字段会更改template-views2-B.png但内联字段保持不变。

In addition, I also tried 'GeoHazard.objects.filter(history_id=1)' when updating the 'context' dictionary but this is not the solution, since this only grabs the inline fields from the parent fields with the specific id.此外,我还在更新“上下文”字典时尝试了“GeoHazard.objects.filter(history_id=1)”,但这不是解决方案,因为这只会从具有特定 ID 的父字段中获取内联字段。 Then I tried to use custom template tags, django custom template-tags but it didn't work.然后我尝试使用自定义模板标签, django 自定义模板标签,但它不起作用。


(template.html) Here's my template btw: (template.html) 这是我的模板顺便说一句:

 {% for history in histories %} <div class="row m-0"> <div class="col-md-3 col-sm-12 mt-4"> <div class="card bg-transparent border-0"> <div class="car-body text-center"> <h3><u>{{ history.barangay_name}}</u></h3> <img src="{{ history.barangay_img.url }}" width="180" height="180" class="rounded-circle"> </div> </div> </div> <div class="col-md-8 col-sm-12 mt-4" style="display: grid;place-items:center;"> <div class="card bg-transparent border-0"> <div class="car-body"> <p style="text-align:justify;">{{ history.barangay_info}}</p> </div> </div> </div> </div> <hr> {% endfor %} {% if geohazards %} {% for hazard in geohazards %} <div class="row m-0"> <div class="col-md-3 col-sm-12 mt-4"> <div class="card bg-transparent border-0"> <div class="car-body text-center"> <img src="{{hazard.geohazard_img.url}}" height="200" width="300"> </div> </div> </div> <div class="col-md-8 col-sm-12 mt-4" style="display: grid;place-items:center;"> <div class="card bg-transparent border-0"> <div class="car-body"> <h4>{{hazard.date_published}}</h4> <p style="text-align:justify;">{{hazard.geohazard_info}}</p> </div> </div> </div> </div> {% endfor %} <hr>

template-with-labels.png In this pic I labeled each fields that I'm trying to display in my template. template-with-labels.png在这张图片中,我标记了我试图在我的模板中显示的每个字段。

Been at it for ages and looking forward to anyone who can help.多年来一直在努力,期待任何可以提供帮助的人。 Really eager to find the solution to this for the Project's deadline is right at our doorsteps.真正渴望在项目的最后期限内找到解决方案就在我们家门口。 Thanks in advance!提前致谢!

You should be able to access the related GeoHazard and Assessment objects by their related_name :您应该能够通过相关related_name访问相关的GeoHazardAssessment对象:

{% for history in histories %}
    {{ history.barangay_name}
    {# other history information #}

    {% for hazard in history.geohazards.all %}
        {{ hazard.geohazard_info }}
        {# other hazard information #}
    {% endfor %}

   {% for assessment in history.assessment.all %}
        {{ assessment.purok_name }}
        {# other assessment information #}
    {% endfor %}
{% endfor %}

Accessing the attribute that is defined by related_name will return an instance of a RelatedManager that has methods like all() (same as objects on a model).访问由related_name定义的属性将返回一个相关管理器的实例,该实例具有类似RelatedManager all()的方法(与模型上的objects相同)。

Note that for this to work you don't need to add any additional stuff in the context, but performance-wise it might make sense to use prefetch_related() otherwise for every History instance additional queries are performed to fetch the related objects.请注意,要使其正常工作,您不需要在上下文中添加任何其他内容,但在性能方面,使用prefetch_related()可能是有意义的,否则对于每个History实例执行额外的查询以获取相关对象。

class HistoryView(ListView):
   model = History
   template_name = 'auxiliary/history.html'
   context_object_name = 'histories'
   paginate_by = 1


   def get_queryset(self):
       histories = super().get_queryset()
       histories = histories.prefetch_related("geohazards", "assessment")
       return histories

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM