Как решить модель не имеет поля с именем «True»? - PullRequest
0 голосов
/ 02 июня 2018

Я использую 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'

Честно говоря, я был смущен этим полем "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)

Наконец, URL:

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 голосов
/ 02 июня 2018

Ошибка вызвана unique_for_date=True в файле модели в поле даты.

Изменение его на date = models.DateField(verbose_name='打卡日期',auto_now_add=True) исправляет ошибку.

Я предполагаю поведение, которое вы ищете, но я думаю, что вы на самом деле имеете в виду просто:

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

В справочнике Django относительно unique и unique_for_date указывает, что unique - это логическое значение, что «Если True, это поле должно быть уникальным для всей таблицы.»

Однако unique_for_date не является логическим значением (следовательно, ошибка при установке значения True)а скорее ссылка на другое поле.

Вот пример его использования в тестах DRF :

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

В качестве примечания мой метод отладки ошибки фактически близко соответствует Каксоздать минимальный, полный и проверяемый пример .Устраняя вещи, которые не вызывали ошибку, я смог определить, что было.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...