【问题标题】:Fields of QuerySet are not accessible from views.py in Django无法从 Django 中的 views.py 访问 QuerySet 的字段
【发布时间】:2021-08-02 08:59:00
【问题描述】:

自过去两周以来,我一直在尝试创建跟踪报告,但我一直在失败。我有 3 个模型,StudentCourseFee。我想创建一个报告,它将这 3 个模型包含的所有数据以及它自己的 ID 放在一起。

模型:

class Student(models.Model):
    roll_number=models.IntegerField(primary_key=True)
    name=models.CharField(max_length=50)
    email=models.EmailField(max_length=60)
    city=models.CharField(max_length=20)

class CourseChoices(models.Model):
    courses=models.CharField(max_length=30, blank=True)

    def __str__(self):
        return self.courses

class Course(models.Model):
    roll_number=models.ForeignKey(Student, on_delete=CASCADE)
    course=models.ForeignKey(CourseChoices, on_delete=CASCADE)

class Fee(models.Model):
    roll_number=models.ForeignKey(Student, on_delete=CASCADE)
    amount_to_be_paid=models.DecimalField(max_digits=7, decimal_places=2, default=0)
    discount=models.DecimalField(max_digits=5, decimal_places=2, default=0)
    Final_amount_to_be_paid=models.DecimalField(max_digits=5, decimal_places=2, default=0)
    Amount_received=models.DecimalField(max_digits=5, decimal_places=2, default=0)
    Balance=models.DecimalField(max_digits=5, decimal_places=2, default=0)
    batch=models.IntegerField()

现在,学生可以分期付款,这样会在跟踪报告中创建多个实例。我希望用户使用主键/ID 跟踪每笔交易。下面是一个例子:

这里的一位成员建议我创建另一个名为 Report 的模型:

class Report(models.Model):
    id = models.CharField(max_length=7, primary_key=True)
    student = models.ForeignKey(Student, on_delete=models.CASCADE)
    course = models.ForeignKey(Course, on_delete=models.CASCADE)
    fee = models.ForeignKey(Fee, on_delete=models.CASCADE)

    def _get_next_id(self):
        last = self.objects.aggregate(max_id=models.Max('id'))['max_id']
        if last is None:
            last = 1
        self.id = "{}{:04d}".format('HB', last)

    def save(self, *args, **kwargs):
        if not self.id:
            self.id = self._get_next_id()
        super().save(*args, **kwargs)

然后当事务发生时 - 我保存了一个额外的 Report 实例,其中包含指向其他对象的链接。

Report.objects.create(student=student, fee=fee, course=course)

所以我写了一个收费视图如下:

def fee_view(request):
    if request.method=='POST':
        fm_fee=FeeForm(request.POST)
        if fm_fee.is_valid():
            fm_fee.save()
            fee=Fee.objects.all()
            print()
            print(fee)
            print()
            print(fee[1])
            Report.objects.create(student=fee.roll_number, fee=fee, course=Course.objects.get(roll_number=fee.roll_number))
            fm_fee=FeeForm()
        return render(request, 'account/fee.html', {'form1':fm_fee})
    else:
        fm_fee=FeeForm()
        return render(request, 'account/fee.html', {'form1':fm_fee})

这里的 QuerySet 不知何故不包含这些字段。当我打印它时,它会返回:

<QuerySet [<Fee: Fee object (1)>, <Fee: Fee object (2)>, <Fee: Fee object (3)>, <Fee: Fee object (4)>, <Fee: Fee object (5)>, <Fee: Fee object (6)>, <Fee: Fee object (7)>, <Fee: Fee object (8)>, <Fee: Fee object (9)>, <Fee: Fee object (10)>, <Fee: Fee object (11)>, <Fee: Fee object (12)>, <Fee: Fee object (13)>, <Fee: Fee object (14)>]>

回溯:

Environment:


Request Method: POST
Request URL: http://127.0.0.1:8000/fee/

Django Version: 3.2.6
Python Version: 3.9.6
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'account']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback (most recent call last):
  File "C:\Users\manoj\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\Users\manoj\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "F:\Sonu\Projects\Practice\test1\account\views.py", line 48, in fee_view
    Report.objects.create(student=fee.roll_number, fee=fee, course=Course.objects.get(roll_number=fee.roll_number))

Exception Type: AttributeError at /fee/
Exception Value: 'QuerySet' object has no attribute 'roll_number'

编辑 1:

新视图:

def fee_view(request):
    if request.method=='POST':
        fm_fee=FeeForm(request.POST)
        if fm_fee.is_valid():
            fee=fm_fee.save()
            print()
            print(fee)
            print()
            print(fee.roll_number)
            Report.objects.create(student=fee.roll_number, fee=fee, course=Course.objects.get(roll_number=fee.roll_number))
            fm_fee=FeeForm()
        return render(request, 'account/fee.html', {'form1':fm_fee})
    else:
        fm_fee=FeeForm()
        return render(request, 'account/fee.html', {'form1':fm_fee})

追溯:

Environment:


Request Method: POST
Request URL: http://127.0.0.1:8000/fee/

Django Version: 3.2.6
Python Version: 3.9.6
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'account']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback (most recent call last):
  File "C:\Users\manoj\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\Users\manoj\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "F:\Sonu\Projects\Practice\test1\account\views.py", line 50, in fee_view
    Report.objects.create(student=fee.roll_number, fee=fee, course=Course.objects.get(roll_number=fee.roll_number))
  File "C:\Users\manoj\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\Users\manoj\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\query.py", line 453, in create
    obj.save(force_insert=True, using=self.db)
  File "F:\Sonu\Projects\Practice\test1\account\models.py", line 51, in save
    self.id = self._get_next_id()
  File "F:\Sonu\Projects\Practice\test1\account\models.py", line 44, in _get_next_id
    last = self.objects.aggregate(max_id=models.Max('id'))['max_id']
  File "C:\Users\manoj\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\manager.py", line 179, in __get__
    raise AttributeError("Manager isn't accessible via %s instances" % cls.__name__)

Exception Type: AttributeError at /fee/
Exception Value: Manager isn't accessible via Report instances

编辑 2:

报告模型:

class Report(models.Model):
    id = models.CharField(max_length=7, primary_key=True)
    student = models.ForeignKey(Student, on_delete=models.CASCADE)
    course = models.ForeignKey(Course, on_delete=models.CASCADE)
    fee = models.ForeignKey(Fee, on_delete=models.CASCADE)

    def _get_next_id(self):
        last = Report.objects.aggregate(max_id=models.Max('id'))['max_id']
        if last is None:
            last = 1
        self.id = "{}{:04d}".format('HB', last)

    def save(self, *args, **kwargs):
        if not self.id:
            self.id = self._get_next_id()
        super().save(*args, **kwargs)

我用Report 替换了self,但我现在得到一个ValueError,Traceback 在这里:

Environment:


Request Method: POST
Request URL: http://127.0.0.1:8000/fee/

Django Version: 3.2.6
Python Version: 3.9.6
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'account']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback (most recent call last):
  File "C:\Users\manoj\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\Users\manoj\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "F:\Sonu\Projects\Practice\test1\account\views.py", line 50, in fee_view
    Report.objects.create(student=fee.roll_number, fee=fee, course=Course.objects.get(roll_number=fee.roll_number))
  File "C:\Users\manoj\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\Users\manoj\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\query.py", line 453, in create
    obj.save(force_insert=True, using=self.db)
  File "F:\Sonu\Projects\Practice\test1\account\models.py", line 51, in save
    self.id = self._get_next_id()
  File "F:\Sonu\Projects\Practice\test1\account\models.py", line 47, in _get_next_id
    self.id = "{}{:04d}".format('HB', last)

Exception Type: ValueError at /fee/
Exception Value: Unknown format code 'd' for object of type 'str'

【问题讨论】:

    标签: python python-3.x django django-models django-views


    【解决方案1】:

    当您执行fee=Fee.objects.all() 时,您将获得所有Fee 对象,因此您无法从fee 访问字段。

    如果您希望从保存的费用表单创建报告,您可能想要这样做;

           if fm_fee.is_valid():
                fee = fm_fee.save()
    
                Report.objects.create(
                    student=fee.roll_number,
                    fee=fee,
                    course=Course.objects.get(roll_number=fee.roll_number)
                )
                fm_fee=FeeForm()
    

    这假定FeeFormModelForm,因此保存它会创建一个Fee 实例。

    回到您的查询集fees = Fee.objects.all(),您可以通过执行fees.values_list('roll_number', flat=True) 之类的操作来访问表中的列。

    这将为您提供Fee 表中所有roll_number 值的列表。

    编辑

    看起来您的错误是由以下原因引起的:

    last = self.objects.aggregate(max_id=models.Max('id'))['max_id']

    上面写的;

    无法通过报表实例访问管理器

    我假设self 是报告的一个实例,所以它不能做.objects。你需要在这里做Report.objects.aggregate

    【讨论】:

    • 它现在在 /fee/ 处给了我另一个 AttributeError。我在我的问题中粘贴了编辑 1 中的代码。请看一下。
    • 感谢您的指出。我已在编辑 2 中粘贴了该特定代码。我还在那里用 Report 替换了 self,但现在我得到一个 ValueError。
    • ValueError 问题现已解决。你能告诉我为什么下面的代码没有返回预期的值吗?相反,id 只是默认的 1、2、3 等等。有什么建议吗?
    • @noob87 这很难说,但这是与该问题所解决的问题不同的问题。我会问另一个问题,包括您的模型,您的自定义 save()_get_next_id() 导致问题。
    猜你喜欢
    • 2021-09-15
    • 2018-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-30
    • 2011-05-10
    • 2016-06-27
    • 1970-01-01
    相关资源
    最近更新 更多