TypeError: Field 'id' expected a number but got DeferredAttribute object at 0x000002B6ADE878D0

huangapple go评论125阅读模式
英文:

TypeError: Field 'id' expected a number but got DeferredAttribute object at 0x000002B6ADE878D0

问题

I am using a queryset in Django- whenever I run the server, it gives an error.

TypeError: Field 'id' expected a number but got <django.db.models.query_utils.DeferredAttribute object at 0x000002B6ADE878D0

It is something about the queryset of my form that causes the error.

我在Django中使用一个查询集,每当我运行服务器时,都会出现错误。

TypeError: 字段 'id' 期望一个数字,但得到了 <django.db.models.query_utils.DeferredAttribute 对象 at 0x000002B6ADE878D0>

这与我的表单的查询集有关,导致了错误。

英文:

I am using a queryset in Django- whenever I run the server, it gives an error.

TypeError: Field &#39;id&#39; expected a number but got &lt;django.db.models.query_utils.DeferredAttribute object at 0x000002B6ADE878D0

It is something about the queryset of my form that causes the error.

I don't know whether its an issue with my models.py or my forms.py
I tried looking up this DeferredAttribute object on Google, but I didn't really see any answer that works for me.

forms.py:

  1. from .models import Task, Categories
  2. from django import forms
  3. from django.forms import ModelForm
  4. from django.db.models import Q
  5. class TaskForm(ModelForm):
  6. task_title = forms.CharField(max_length=100)
  7. task_description = forms.CharField(widget=forms.Textarea)
  8. due_date = forms.DateTimeField()
  9. is_completed = forms.BooleanField()
  10. #categories = forms.ModelChoiceField(empty_label=&quot;---None---&quot;)
  11. class Meta:
  12. model = Task
  13. fields = [&#39;task_title&#39;, &#39;task_description&#39;, &#39;due_date&#39;, &#39;is_completed&#39;, &#39;categories&#39;, &#39;parent&#39;]
  14. def __init__(self, user, *args, **kwargs):
  15. # Get all the categories from the database for that specific user
  16. super(TaskForm, self).__init__(*args, **kwargs)
  17. # It is something about this line that causes the error
  18. self.fields[&#39;categories&#39;].queryset = Categories.objects.filter(Q(user_id__isnull=True) | Q(user_id=user.id))

models.py:

  1. from django.db import models
  2. from django.db.models import Q
  3. from users.models import CustomUser
  4. from django.urls import reverse
  5. from django.contrib.auth import get_user_model
  6. class Categories(models.Model):
  7. category_type = models.CharField(max_length=50)
  8. user = models.ForeignKey(CustomUser, null = True, on_delete=models.CASCADE)
  9. def __str__(self):
  10. return &#39;%s &#39; % (self.category_type)
  11. def get_absolute_url(self):
  12. return reverse(&#39;task_list&#39;)
  13. class Task(models.Model):
  14. task_title = models.CharField(max_length=100)
  15. task_description = models.TextField()
  16. date_added = models.DateTimeField(auto_now_add=True)
  17. due_date = models.DateTimeField()
  18. is_completed = models.BooleanField(default=False)
  19. user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
  20. categories = models.ForeignKey(&#39;Categories&#39;, on_delete=models.CASCADE)
  21. parent = models.ForeignKey(&quot;self&quot;, on_delete=models.CASCADE)
  22. class Meta:
  23. verbose_name = &quot;Task&quot;
  24. verbose_name_plural = &quot;Tasks&quot;
  25. def __str__(self):
  26. return &#39;%s ID: %s&#39; % (self.task_title, self.last_name)
  27. def get_absolute_url(self):
  28. return reverse(&#39;task_detail&#39;)

CustomUser model:

  1. from django.contrib.auth.models import AbstractUser
  2. from django.db import models
  3. class CustomUser(AbstractUser):
  4. nationality = models.CharField(null=True, blank=True, max_length=60)

views.py:

  1. from django.views.generic import TemplateView
  2. from django.views.generic.edit import UpdateView, DeleteView , CreateView
  3. from django.urls import reverse_lazy
  4. from .forms import TaskForm
  5. from django.contrib.auth import get_user_model
  6. from django.http import JsonResponse
  7. from django.template.loader import render_to_string
  8. class TaskListView(TemplateView):
  9. template_name = &quot;tasks.html&quot;
  10. # This is the actual create view I am for using now
  11. class TaskCreateView(CreateView):
  12. template_name = &#39;create.html&#39;
  13. form_class = TaskForm(get_user_model())
  14. success_url = reverse_lazy(&#39;task_list&#39;)
  15. # I am using this for a modal, but its not working so I fell back to the normal create view
  16. def task_create(request):
  17. form = TaskForm(get_user_model())
  18. context = {&#39;form&#39;: form}
  19. html_form = render_to_string(&#39;tasks/partial_task_create.html&#39;,
  20. context,
  21. request=request,
  22. )
  23. return JsonResponse({&#39;html_form&#39;: html_form})

答案1

得分: 2

A statement like:

  1. form = TaskForm(get_user_model())

does not make much sense. Indeed, get_user_model() returns a reference to the user class, not to a user object (like the logged in user). You can construct such a form with:

  1. from django.contrib.auth.decorators import login_required
  2. @login_required
  3. def task_create(request):
  4. form = TaskForm(request.user)
  5. context = {'form': form}
  6. html_form = render_to_string('tasks/partial_task_create.html',
  7. context,
  8. request=request,
  9. )
  10. return JsonResponse({'html_form': html_form})

Here we use the @login_required decorator to prevent users who are not logged in from accessing the view. This is useful, since in that case request.user is not a user object.

or in the CreateView, you can override the get_form_kwargs method to:

  1. from django.contrib.auth.mixins import LoginRequiredMixin
  2. class TaskCreateView(LoginRequiredMixin, CreateView):
  3. template_name = 'create.html'
  4. form_class = TaskForm
  5. success_url = reverse_lazy('task_list')
  6. def get_form_kwargs(self):
  7. kwargs = super().get_form_kwargs()
  8. kwargs.update(user=self.request.user)
  9. return kwargs

In order to enforce a user to be logged in, we then use a LoginRequiredMixin mixin.

英文:

A statement like:

<pre><code>form = TaskForm(<s>get_user_model()</s>)</code></pre>

does not make much sense. Indeed, get_user_model() returns a reference to the user class, not to a user object (like the logged in user). You can construct such a form with:

<pre><code>from django.contrib.auth.decorators import login_required

<b>@login_required</b>
def task_create(request):
form = TaskForm(<b>request.user</b>)
context = {'form': form}
html_form = render_to_string('tasks/partial_task_create.html',
context,
request=request,
)
return JsonResponse({'html_form': html_form})</code></pre>

Here we use the @login_required decorator [Django-doc] to prevent user that are not logged in to access the view. This is useful, since in that case request.user is not a user object.

or in the CreateView [Django-doc] you can override the get_form_kwargs method [Django-doc] to :

<pre><code>from django.contrib.auth.mixins import LoginRequiredMixin

class TaskCreateView(<b>LoginRequiredMixin</b>, CreateView):
template_name = 'create.html'
form_class = <b>TaskForm</b>
success_url = reverse_lazy('task_list')

  1. def get_form_kwargs(self):
  2. kwargs = super().get_form_kwargs()
  3. &lt;b&gt;kwargs.update(user=self.request.user)&lt;/b&gt;
  4. return kwargs&lt;/code&gt;&lt;/pre&gt;

In order to enforce a user to be logged in, we then use a LoginRequiredMixin mixin [Django-doc].

huangapple
  • 本文由 发表于 2020年1月7日 00:49:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/59615964.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定