【问题标题】:How to check request.user against an unrelated model in Django如何在 Django 中针对不相关的模型检查 request.user
【发布时间】:2021-03-03 17:39:29
【问题描述】:

我的问题有点难以解释,但我会尽力而为。请问有什么需要澄清的。

我有三个模型,Exercise、Area 和 Workout:

class Exercise(models.Model):
    name = models.CharField(max_length=100)

class Area(models.Model):
    user = models.ForeignKey(Profile, on_delete=models.CASCADE)
    name = models.CharField(max_length=100)
    exercise = models.ManyToManyField(Exercise, blank=True)

class Workout(models.Model):
    weight = models.DecimalField(default=0.0)
    reps = models.PositiveIntegerField(default=0)
    exercise = models.ForeignKey(Exercise, on_delete=models.CASCADE)

用户将填写一个将对象添加到区域的表单。然后,他们可以进入该对象并填写一个新表格,将对象添加到练习中,这些对象也通过 M2M 附加到特定区域。为了只显示这个特定用户创建的练习,我在练习模板中有一个 if 语句:

{% if area.user.user == request.user %}`
    {{ exercise.name }}
{% endif %}

我希望用户现在能够进入锻炼对象并填写添加到锻炼的表单。我可以做到这一点,但我的问题是如何确保只显示登录用户的锻炼? area.user.user 没有影响,因为区域与此模板无关,我无法将用户添加到锻炼模型。

编辑

class WorkoutView(DetailView):
    model = Exercise
    template_name = 'tracker/workouts.html'

    def get_context_data(self, **kwargs):
        context = super(WorkoutView, self).get_context_data(**kwargs)
        context['profile'] = Profile.objects.get(user=self.request.user)
        context['form'] = form
        return context


from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)

【问题讨论】:

  • 您能否编辑您的问题以显示您的观点。
  • 嗨@sgt_pepper85!通常你会在你的视图中而不是在模板中这样做。将login_required-decorator 或 Mixin 添加到您的视图中,这样只有登录的用户才能访问它。在视图中,使用请求用户request.user 过滤您的数据。我看到你在 Area 中提到的不是 djangos 用户模型,而是一个名为 Profile 的模型,你能不能也给我们一些相关信息?
  • 感谢 Lewis 和 @Yves Hary 的回复。我已经编辑了我的问题以显示显示锻炼的视图,以及我的个人资料模型的 sn-p,根据要求将用户链接到 auth 用户模型
  • 如果我没听错请告诉我:您想显示属于当前登录用户的所有锻炼对象吗?
  • 是的,没错

标签: django request m2m


【解决方案1】:

根据您的信息,我认为此解决方案可能是合适的。首先,如果你想显示多个对象,django 提供了ListView 更适合你的需要。除了你的视野之外,一切都可以保持原样。

from django.views.generic.list import ListView
from django.contrib.auth.mixins import LoginRequiredMixin

class WorkoutView(LoginRequiredMixin, ListView): 
# This mixin prevents access from not logged in users
   template_name = 'tracker/workouts.html'
   queryset = Workout.objects.all()

   def get_queryset(self):
      # Here we can modify the initial queryset and
      # filter it against the logged in user.
      # Beware that this is not tested and can have bugs.
      # Getting all areas related to the profile of the user
      qs_area = Area.objects.filter(user__user=self.request.user)
      # Getting all exercises related to these areas
      qs_exercises = Exercise.objects.filter(area__in=qs_area)
      # Getting all workouts related to these exercises
      # Django will use subqueries to do this
      self.queryset = self.queryset.filter(exercise__in=qs_exercises)

      return super().get_queryset()

您可以通过以下方式访问模板中检索到的数据:

{% for element in object_list %}
{{ element }}
{% endfor %}

说实话,用户的锻炼真的很难。也许您应该花一些额外的时间来改进您的数据库模型。

【讨论】:

  • 非常感谢您抽出宝贵时间来帮助我。我意识到这是一个真正的痛苦。昨天我花了一整天的时间来修改我的模型,但找不到更好的方法。我刚才运行了你的代码,收到了 AttributeError type object 'Exercise' has no attribute 'filter'
  • 哦,对不起,应该是Exercise.objects.filter(...)。我编辑了sn-p。一个好主意是将您当前的现实情况画在一张纸上,然后思考如何在数据库中对此进行建模。在我看来,您并不清楚您的用例。
  • 啊,是的。但现在我只看到一个空页面
  • 所以,从现在开始,您必须自己解决 :-) 使用您的调试器并查看当前登录的用户是否有匹配的锻炼......?
  • 哈哈,这很公平。我会从这里开始玩。再次感谢所有帮助
【解决方案2】:

解决方案是在我的锻炼模型中使用 Profile 的外键创建一个用户字段,然后实例化视图。感谢@Yves Hary 解决这个问题

【讨论】:

    最近更新 更多