前提・実現したいこと
python,djangoで出退勤時間を管理するアプリを作りたいと思っています。
%H:%M:%Sの形で入力して、それを反映し管理アプリです。
以下のソースでウェブページから更新ボタンを押下するとTypeErrorが出ましたので、
それを解消したいです。
データの型の問題だと考えているのですが、
①form.pyに問題があるのでしょうか。
②model.pyに問題があるのでしょうか。
③あるいは他に原因があるのでしょうか
お分かりの方がおりましたら、ご教示いただきたいです。
発生している問題・エラーメッセージ
match = datetime_re.match(value)
TypeError: expected string or bytes-like object
該当のソースコード
model
from django.db import models from django.contrib.auth import get_user_model from django.contrib.auth.models import User #import datetime as dt from django.utils import timezone # Create your models here. class SubmitAppsite(models.Model): class Meta: db_table = 'appsite' STATE = ( (1, '正常'), (2, '遅刻'), (3, '欠勤'), (4, '早退'), (5, '休日'), (6, 'そのほか'), ) IN_OUT = ( (1, '出勤'), (0, '退勤'), ) staff = models.ForeignKey(get_user_model(), verbose_name="社員", on_delete=models.CASCADE, default=None) in_outtime = models.TimeField(verbose_name="出退勤時間", default=None) state = models.IntegerField(verbose_name='状態', choices=STATE, default=None) in_out = models.IntegerField(verbose_name='IN/OUT', choices=IN_OUT, default=None) time = models.DateTimeField(verbose_name="更新時間") date = models.DateField(verbose_name='更新日')
view
from django.shortcuts import render, redirect from django.views import View from django.contrib.auth.mixins import LoginRequiredMixin from .models import SubmitAppsite from .forms import SubmitAppsiteForm from datetime import datetime from django.utils import timezone # Create your views here. class IndexView(LoginRequiredMixin, View): def get(self, request): form = SubmitAppsiteForm context = { 'form': form, "user": request.user, } return render(request, 'appsite/index.html', context) index = IndexView.as_view() class ResultView(View): def post(self, request): form = SubmitAppsiteForm(request.POST) now = datetime.now() month = now.month day = now.day hour = now.hour minute = now.minute obj = form.save(commit=False) obj.in_outtime = request.POST["in_outtime"] obj.state = request.POST["state"] obj.in_out = request.POST["in_out"] obj.staff = request.user obj.date = datetime.now().date() obj.time = datetime.now().time() obj.save() if request.POST["in_out"] == '1': comment = str(month) + "月" + str(day) +"日" + str(hour) + "時" + str(minute) + "分" + "出勤確認しました。今日も頑張りましょう!" else: comment = str(month) + "月" + str(day) +"日" + str(hour) + "時" + str(minute) + "分" + "退勤確認しました。お疲れ様でした(^-^)!" context = { 'state': SubmitAppsite.STATE[int(obj.state)-1][1], 'comment': comment, } return render(request, 'appsite/result.html', context) result = ResultView.as_view()
form
class SubmitAppsiteForm(forms.ModelForm): class Meta: model = SubmitAppsite fields = ('in_outtime') widgets = { 'in_outtime': datetimepicker.DatePickerInput( format='%H:%M:%S', ), }
html
{{ form.media }} <p>出退勤時間:<input type="hidden" name="in_outtime">{{ form.in_outtime }}</p> <p><input class="btn btn-primary" type="submit" value="更新"></p>
試したこと
1.model.pyの in_outtime = models.TimeFieldの
TimeFieldをDateTimeFieldに変えて更新するとValueErrorとなりました。
2.form.pyを以下のように変更してみましたが、やはりTypeErrorとなりました。
form
format='%Y-%m-%d %H:%M:%S',
補足情報(FW/ツールのバージョンなど)
**DBはsqlite。**bootstrap-datetimepickerを使用しています。ソースは抜粋。
調べてみますとSQLiteでは日付・時刻・日付時刻は単なる文字列として扱われるとあったので、
form.pyかview.pyで入力した情報を文字列として扱えれば解決できるのかと考え、
調べましたが分かりませんでした。
###追記(エラーの行が、提示されているコードの中に無い)
エラーは下記ようになっていました。
File "D:\01_勉強用\03_python\work\webapp\myvenv\lib\site-packages\django\utils\dateparse.py", line 106, in parse_datetime
match = datetime_re.match(value)
TypeError: expected string or bytes-like object
dateparse
def parse_datetime(value): match = datetime_re.match(value) if match: kw = match.groupdict() kw['microsecond'] = kw['microsecond'] and kw['microsecond'].ljust(6, '0') tzinfo = kw.pop('tzinfo') if tzinfo == 'Z': tzinfo = utc elif tzinfo is not None: offset_mins = int(tzinfo[-2:]) if len(tzinfo) > 3 else 0 offset = 60 * int(tzinfo[1:3]) + offset_mins if tzinfo[0] == '-': offset = -offset tzinfo = get_fixed_timezone(offset) kw = {k: int(v) for k, v in kw.items() if v is not None} kw['tzinfo'] = tzinfo return datetime.datetime(**kw)
###追記(このvalueという変数はいったいナニモノ)
エラーをすべて下記に追記しました。
ただ大変申し訳ありません。
valueがいったい何者なのか、私には分かりませんでした。
またparse_datetime関数の呼び元のソースがどれに当たるのか、分かりませんでした。
もっと勉強してから質問しようと思います。
コメントありがとうございました。
File "D:\01_勉強用\03_python\work\webapp\appsite\views.py", line 39, in post
obj.save()
File "D:\01_勉強用\03_python\work\webapp\myvenv\lib\site-packages\django\db\models\base.py", line 741, in save
force_update=force_update, update_fields=update_fields)
File "D:\01_勉強用\03_python\work\webapp\myvenv\lib\site-packages\django\db\models\base.py", line 779, in save_base
force_update, using, update_fields,
File "D:\01_勉強用\03_python\work\webapp\myvenv\lib\site-packages\django\db\models\base.py", line 870, in save_table
result = self.do_insert(cls.base_manager, using, fields, update_pk, raw)
File "D:\01_勉強用\03_python\work\webapp\myvenv\lib\site-packages\django\db\models\base.py", line 908, in do_insert
using=using, raw=raw)
File "D:\01_勉強用\03_python\work\webapp\myvenv\lib\site-packages\django\db\models\manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "D:\01_勉強用\03_python\work\webapp\myvenv\lib\site-packages\django\db\models\query.py", line 1186, in insert
return query.get_compiler(using=using).execute_sql(return_id)
File "D:\01_勉強用\03_python\work\webapp\myvenv\lib\site-packages\django\db\models\sql\compiler.py", line 1334, in execute_sql
for sql, params in self.as_sql():
File "D:\01_勉強用\03_python\work\webapp\myvenv\lib\site-packages\django\db\models\sql\compiler.py", line 1278, in as_sql
for obj in self.query.objs
File "D:\01_勉強用\03_python\work\webapp\myvenv\lib\site-packages\django\db\models\sql\compiler.py", line 1278, in <listcomp>
for obj in self.query.objs
File "D:\01_勉強用\03_python\work\webapp\myvenv\lib\site-packages\django\db\models\sql\compiler.py", line 1277, in <listcomp>
[self.prepare_value(field, self.pre_save_val(field, obj)) for field in fields]
File "D:\01_勉強用\03_python\work\webapp\myvenv\lib\site-packages\django\db\models\sql\compiler.py", line 1218, in prepare_value
value = field.get_db_prep_save(value, connection=self.connection)
File "D:\01_勉強用\03_python\work\webapp\myvenv\lib\site-packages\django\db\models\fields_init.py", line 789, in get_db_prep_save
return self.get_db_prep_value(value, connection=connection, prepared=False)
File "D:\01_勉強用\03_python\work\webapp\myvenv\lib\site-packages\django\db\models\fields_init.py", line 1431, in get_db_prep_value
value = self.get_prep_value(value)
File "D:\01_勉強用\03_python\work\webapp\myvenv\lib\site-packages\django\db\models\fields_init.py", line 1410, in get_prep_value
value = super().get_prep_value(value)
File "D:\01_勉強用\03_python\work\webapp\myvenv\lib\site-packages\django\db\models\fields_init.py", line 1270, in get_prep_value
return self.to_python(value)
File "D:\01_勉強用\03_python\work\webapp\myvenv\lib\site-packages\django\db\models\fields_init.py", line 1371, in to_python
parsed = parse_datetime(value)
File "D:\01_勉強用\03_python\work\webapp\myvenv\lib\site-packages\django\utils\dateparse.py", line 106, in parse_datetime
match = datetime_re.match(value)
TypeError: expected string or bytes-like object
###追記(views.pyについて)
上記のveiwをすべて記載しました。(そのため以前までのものは消えています)
またmodelもすべて記載しています、
このファイルはnonono333さんが編集したものでまちがいないでしょうか。
はい。こちら(リンク)を参考に作成し、自身で時刻を入力する機能を追加するのために編集しました。
入力者によって時刻の入力がバラバラになるのを嫌い、またフォーマットを制限しないとVauleErrorが出たため
こちらで入力方法を制限したく、bootstrap-datetimepickerを使用しました。
その際はこちらを参考リンクに時刻を入力する形にしました。
###追記(日時のフォーマットに従っていないこと)
日時のフォーマットに従っていないことが原因であると考えられます。
上記指摘をいただき、日次が入る個所を一つ一つコメントアウトして実行してみましたところ、下記の個所をコメントアウトするとエラーが起こらず、無事に更新されました。
veiw
#obj.time = datetime.now().time()
model
#time = models.DateTimeField(verbose_name="更新時間")
また下記のように修正し実行すると問題なく更新されました。
veiw
obj.time = datetime.now().time()
model
time = models.TimeField(verbose_name="更新時間") #Dateを削除
上記の結果から考えますと
Datetime型が入るべきところにtime型が入ろうとしていてためTypwerrorとり、
time型に修正したらエラーが起きなくなったと考えています。
最初に挙げていた抜粋のソースがエラーの原因ではなく、違う箇所が原因のようでした。
回答のために読んでいただいたのに見当違いの個所を記載してしまい、申し訳ありません。
まだ回答がついていません
会員登録して回答してみよう