如何解决模型没有名为'True'的字段?

时间:2018-06-02 13:36:27

标签: django database django-models django-rest-framework serializer

我正在使用django-restframework。我遇到了一个非常奇怪的问题,无法解决问题。我在验证后尝试访问“http://127.0.0.1:8000/api/attendance/”时出现此问题:

Traceback:

File "C:\ProgramData\Anaconda3\lib\site-packages\django\db\models\options.py" in get_field
566.             return self.fields_map[field_name]

During handling of the above exception (True), another exception occurred:

File "C:\ProgramData\Anaconda3\lib\site-packages\django\core\handlers\exception.py" in inner
35.             response = get_response(request)

File "C:\ProgramData\Anaconda3\lib\site-packages\django\core\handlers\base.py" in _get_response
158.                 response = self.process_exception_by_middleware(e, request)

File "C:\ProgramData\Anaconda3\lib\site-packages\django\core\handlers\base.py" in _get_response
156.                 response = response.render()

File "C:\ProgramData\Anaconda3\lib\site-packages\django\template\response.py" in render
106.             self.content = self.rendered_content

File "C:\ProgramData\Anaconda3\lib\site-packages\rest_framework\response.py" in rendered_content
72.         ret = renderer.render(self.data, accepted_media_type, context)

File "C:\ProgramData\Anaconda3\lib\site-packages\rest_framework\renderers.py" in render
724.         context = self.get_context(data, accepted_media_type, renderer_context)

File "C:\ProgramData\Anaconda3\lib\site-packages\rest_framework\renderers.py" in get_context
656.         raw_data_post_form = self.get_raw_data_form(data, view, 'POST', request)

File "C:\ProgramData\Anaconda3\lib\site-packages\rest_framework\renderers.py" in get_raw_data_form
572.                 data = serializer.data.copy()

File "C:\ProgramData\Anaconda3\lib\site-packages\rest_framework\serializers.py" in data
560.         ret = super(Serializer, self).data

File "C:\ProgramData\Anaconda3\lib\site-packages\rest_framework\serializers.py" in data
266.                 self._data = self.get_initial()

File "C:\ProgramData\Anaconda3\lib\site-packages\rest_framework\serializers.py" in get_initial
413.             for field in self.fields.values()

File "C:\ProgramData\Anaconda3\lib\site-packages\rest_framework\serializers.py" in fields
363.             for key, value in self.get_fields().items():

File "C:\ProgramData\Anaconda3\lib\site-packages\rest_framework\serializers.py" in get_fields
1026.             field_names, declared_fields, extra_kwargs

File "C:\ProgramData\Anaconda3\lib\site-packages\rest_framework\serializers.py" in get_uniqueness_extra_kwargs
1403.             unique_constraint_field = model._meta.get_field(unique_constraint_name)

File "C:\ProgramData\Anaconda3\lib\site-packages\django\db\models\options.py" in get_field
568.             raise FieldDoesNotExist("%s has no field named '%s'" % (self.object_name, field_name))

Exception Type: FieldDoesNotExist at /api/attendance/
Exception Value: Attendance has no field named 'True'

说实话,我对这个'真实'字段感到困惑。我完全无法摆脱困境。我尝试重新生成我的数据库并将相关字段设置为可选.etc。但是,它们都没有奏效。

这是我的代码:

models.py
class Attendance(models.Model):
    A = 'a'
    B = 'b'
    C = 'c'
    WORKPLACE_CHOICES = (
        (A,'工作区 A'),
        (B, '工作区 B'),
        (C, '工作区 C')
    )
    work = models.TextField(blank=True,null=True)
    student = models.ForeignKey('Student', blank = True, null=True,on_delete=models.CASCADE, related_name='attendances')
    date = models.DateField(verbose_name='打卡日期',auto_now_add=True,unique_for_date=True)
    start_work = models.DateTimeField(verbose_name='上班时间',null=True,blank=True)
    off_work =  models.DateTimeField(verbose_name='下班时间',blank=True,null=True)
    is_late = models.BooleanField(verbose_name='是否迟到',default=False)
    work_place = models.CharField(verbose_name='工作区',max_length=1, choices=WORKPLACE_CHOICES,default=A)
    work_length = models.FloatField(verbose_name='工作时长',default=0,)
    ip = models.GenericIPAddressField(verbose_name='签到 IP',blank=True,null=True)
    def save(self, *args, **kwargs):
        self.is_late = self.compute_is_late()
        return super().save(*args,**kwargs)

    def compute_is_late(self):
        if not self.start_work:
            return False
        if self.start_work <= dt.datetime(
            self.start_work.year,
            self.start_work.month,
            self.start_work.day,
            self.student.start_work.hour,
            self.student.start_work.minute
        ):
            return False
        else:
            return True
    def compute_ip(self, request):
        if request.META.has_key('HTTP_X_FORWARDED_FOR'):  
            ip =  request.META['HTTP_X_FORWARDED_FOR']  
        else:  
            ip = request.META['REMOTE_ADDR']
        self.ip = ip
        return self.save()
    def compute_work_length(self):
        """这个方法需要手动调用"""
        assert self.off_work, '请在“下班”之后再调用此字段'
        hours = (self.off_work - self.start_work).total_seconds() / (60*60)
        self.work_length =hours
        return self.save()


    def __str__(self):
        return self.student.user.username + ' ' + str(self.date) + ' 考勤表'



class Student(models.Model):
    M = 'man'
    W = 'Wan'
    GENDER_CHOICES = (
        (M, '男'),
        (W, '女')
    )
    name = models.CharField(verbose_name='姓名',max_length=20,null=True,blank=True)
    email = models.EmailField(verbose_name='邮箱',blank=True,null=True)
    start_work = models.TimeField(verbose_name='上班时间',default=dt.time(9,0))
    gender = models.CharField(
        verbose_name='性别',
        max_length=3,
        choices=GENDER_CHOICES,
        blank=True,
        null=True,
        default=M
    )
    number = models.CharField(verbose_name='学号',max_length=30,blank=False,null=False)
    grade = models.CharField(verbose_name='年级',max_length=30,null=True,blank=True)
    college = models.CharField(
        verbose_name='学院',
        max_length=30,null=True,
        blank=True
    )
    connect = models.TextField(
        verbose_name='其它联系方式',
        null=True,blank=True
    )
    user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True, related_name='student')
    def __str__(self):
        return '学生 ' + self.user.username
    def save(self, *args, **kwargs):
        try:
            user_obj = User.objects.get(username=self.number)
        except User.DoesNotExist:
            user_obj = User.objects.create_user(username=self.number,
            password=self.number,
            email=self.email)
        self.user = user_obj
        return super().save(*args,**kwargs)

这是相对序列化器。

serializers.py
class AttendanceSerializer(serializers.ModelSerializer):
    class Meta:
        model = Attendance
        fields = ('start_work', 'off_work', 'work_place', 'work','ip','date')
        read_only_fields = ('start_work','ip','date','id')
        extra_kwargs = {
            'start_work': {'default': dt.datetime.now()}
        }

    def create(self, validated_data):
        request = self.context['request']
        user = request.user
        student = user.student
        validated_data['start_work'] = dt.datetime.now()
        validated_data['student'] = student
        attendance = Attendance.objects.create(**validated_data)
        attendance.compute_ip(request)
        return attendance
    def update(self, instance, validated_data):
        if instance.off_work:
            validated_data.pop('off_work')
            super().update(instance, validated_data)

然后是观点:

class AttendanceViewSet(viewsets.ModelViewSet):
    queryset = Attendance.objects.all()
    serializer_class = AttendanceSerializer   
    def update(self, request, *args, **kwargs):
        self.partial_update(request, *args, **kwargs)

最后是网址:

router = routers.SimpleRouter()
router.register('attendance', AttendanceViewSet,base_name='attendance')
urlpatterns = [
    path('',home, name='home'),
    path('admin/', admin.site.urls),
    path('login/', LoginView.as_view(),name='login'),
    path('api/',include(router.urls)),
    path('student/', StudentView.as_view(),name='student')
]
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

1 个答案:

答案 0 :(得分:1)

错误是由日期字段中的模型文件中的unique_for_date=True引起的。

将其更改为date = models.DateField(verbose_name='打卡日期',auto_now_add=True)可修复错误。

我猜你正在寻找的行为,但我认为你的意思是:

date = models.DateField(verbose_name='打卡日期',auto_now_add=True, unique=True)

在关于uniqueunique_for_date的Django引用中,它声明unique是一个布尔值“如果为True,则该字段在整个表中必须是唯一的。”

但是unique_for_date不是布尔值(因此当您将其设置为True时会出现错误),而是对不同字段的引用。

以下是DRF's tests中使用的示例:

class UniqueForDateModel(models.Model):
    slug = models.CharField(max_length=100, unique_for_date='published')
    published = models.DateField()

作为旁注,我调试错误的方法实际上与How to create a Minimal, Complete, and Verifiable example密切匹配。通过消除不会导致错误的事情,我能够确定原因是什么。