为啥在 Django 中更新我的 HTML 之前必须重新加载两次?

Posted

技术标签:

【中文标题】为啥在 Django 中更新我的 HTML 之前必须重新加载两次?【英文标题】:Why do I have to reload twice before my HTML gets updated in Django?为什么在 Django 中更新我的 HTML 之前必须重新加载两次? 【发布时间】:2021-11-15 14:59:44 【问题描述】:

我正在 Django 上开发一个视频游戏网上商店,目前正在购物车中。

这是系统的基本组成部分:

一个视频游戏模型,包含视频游戏的基本信息(名称、图片、价格、库存等)

一个购物车中的物品模型,包含一个整数字段(数量)和一个电子游戏的一对一字段。这样做的想法是建立一个模型,其中包含特定客户将视频游戏添加到购物车的次数

Visiting Client 模型,包含访问者的 IP 作为 ID 和 Item in Cart 模型的多对多字段

型号:

class Videogame(models.Model):
  name = models.CharField(max_length=50, blank=False, unique=True)
  image = models.ImageField(upload_to='products_images/', blank=False)
  category =  models.ManyToManyField(Category)
  description = models.TextField(blank=True)
  stock = models.DecimalField(blank=True, null=True, max_digits=3, decimal_places=0, default=0)
  price = models.DecimalField(blank=False, max_digits=6, decimal_places=2, default=0.00)
  visible = models.BooleanField(blank=False, default=True)
  class Meta:
    verbose_name_plural = 'Videogames'
  def __str__(self):
        return self.name

class ItemInCart(models.Model):
  amount = models.PositiveIntegerField(default=1)
  product = models.OneToOneField(to=Videogame, on_delete=CASCADE)
  id = models.TextField(primary_key=True)
  class Meta:
    verbose_name_plural = 'Items In Cart'
  def __str__(self):
    return self.id

class VisitingClient(models.Model):
  id = models.GenericIPAddressField(primary_key=True)
  amount_of_visits = models.IntegerField(default=1)
  first_visit = models.DateTimeField(auto_now_add=True)
  last_visit = models.DateTimeField(auto_now=True)
  items_in_cart = models.ManyToManyField(ItemInCart)

  def __init__(self,*args,**kwargs):
        super(VisitingClient, self).__init__(*args, **kwargs)
        if self.amount_of_visits is None:
            self.amount_of_visits = self.amount_of_visits
            
  def __str__(self):
        return self.id

现在,在我的目录部分的 html 中,我有这个:

<div id="videogames_in_category">
  % for videogame in videogames %
    % if videogame.visible is True %
      <div class="videogame_container" style="background-image: url(videogame.image.url);">
        <div class="videogame_data">
          <span class="videogame_name"> videogame.name </span>
          <span class="videogame_price">$ videogame.price </span>
          <div class="videogame_buttons">
            <button class="info_button" title="Información del producto"></button>
            <button class="add_to_cart_button" title="Añadir al carrito" data-assigned_product=" videogame.name "></button>
          </div>
        </div>
      </div>
    % endif %
  % endfor %
</div>

如果用户触摸添加到购物车客户端,这会在 JS 中发生:

$(".add_to_cart_button").on("click", function() 
  const csrftoken = Cookies.get('csrftoken');
  let requested_item = $(this).attr("data-assigned_product");
  $.ajax(
    method: 'POST',
    headers: 'X-CSRFToken': csrftoken,
    data: 
        "result": requested_item
    ,
    dataType: "json",
    success: RefreshPage()
  ).done(function(data) 
    if (data.success) 
      window.location.href = data.url;
    
  )
);

这就是我的看法

def category_view(request, selected_category):
  videogames_in_category = Videogame.objects.filter(category = Category.objects.get(name=selected_category))

  client_id = request.session.get('client_id', request.META['REMOTE_ADDR'])
  if not ClientExists(client_id):
    CreateClient(client_id)
  current_client_object = VisitingClient.objects.get(pk=client_id)
  UpdateClientAmountOfVisits(current_client_object)

  context = 
    'called_category': selected_category,
    'videogames': videogames_in_category,
    'items_in_cart': current_client_object.items_in_cart.all()
  

  requested_game_in_cart = request.POST.get('result')
  if requested_game_in_cart != None:
    asked_videogame = Videogame.objects.get(name=requested_game_in_cart)
    if ItemInCart.objects.filter(id=asked_videogame).exists():
      cart_item = ItemInCart.objects.get(id=asked_videogame)
      cart_item.amount = cart_item.amount + 1
      cart_item.save()
    else:
      cart_item = ItemInCart.objects.create(id=requested_game_in_cart, product=asked_videogame)
      current_client_object.items_in_cart.add(cart_item)
      current_client_object.save()
    return JsonResponse(
            'success': True,
            'url': '/catalog/' + selected_category + '/'
        )

在这里,我基本上是为了客户的存在,如有必要,创建它,然后等待 AJAX POST,然后用购物车中的新项目更新客户端对象,并将成功标志发送到 AJAX,我继续重新加载页面,以便使用新项目更新 HTML。

显然,我必须重新加载两次才能显示该项目。这是怎么回事?为什么只有一次重新加载不起作用?谢谢!

【问题讨论】:

【参考方案1】:

RefreshPage() 会调用(大概)一个函数来刷新页面。

然后你说一旦它有done,你将再次刷新页面(window.location.href = data.url;)。

RefreshPage()
  ).done(function(data) 
    if (data.success) 
      window.location.href = data.url;
    

因此向服务器调用两个 GET 请求并“重新加载”两次。

【讨论】:

以上是关于为啥在 Django 中更新我的 HTML 之前必须重新加载两次?的主要内容,如果未能解决你的问题,请参考以下文章

为啥logged_out.html在django注册中没有覆盖?

为啥css文件不适用于html文件 - Django

django -- 实现ORM登录

为啥每当我尝试将图像添加到我的 django 项目时都会出错?

为啥 Django 不使用我的 registration/reset_password_done.html 模板?

Django 为啥我的静态 JS 文件没有加载