Django ViewSet Perform_create 无法识别我的数据

问题描述 投票:0回答:1

我有一个 Django (python) 项目。问题在于尝试对我的视图集使用创建函数,但无法识别过去的数据。 (它声称未满足 NullConstraint。)

我的views.py 包括(注意 print() 语句):

class MyModelInstModelViewSet(ABC, MyModelrModelViewSet):
   dfn_class = None

   def _create(self, request, *args, **kwargs):
      print(request.data)
      # Check if 'dfn_id' is provided in request.data
      dfn_id = request.data.get('dfn_id')
      if dfn_id is None:
         return Response({'error': 'dfn_id is required'}, status=status.HTTP_400_BAD_REQUEST)

      # Retrieve the Def instance
      try:
         dfn = self.dfn_class.objects.get(id=dfn_id)
      except self.dfn_class.DoesNotExist:
         return Response({'error': 'Invalid dfn_id'}, status=status.HTTP_400_BAD_REQUEST)

      # Get default values from Def instance
      data = {}

      # Dynamically copy each/all fields from the Def instance
      for field in dfn._meta.fields:
         data[field.name] = getattr(dfn, field.name)

      # Update default values with request data
      for key, value in request.data.items():
         # If the value is a dict/JSONField, perform a deep copy
         if isinstance(value, dict):
            data[key] = copy.deepcopy(value)
         else:
            data[key] = value

      del data['id']
      del data['updated_at']

      data['created_at'] = timezone.now()

      if data['dfn_id'] is None:
         raise 'DFN ID IS NONE!'
      print(data)

      # Create a serializer instance with the updated data
      serializer = self.serializer_class(data=data)
      print('about to validate')
      serializer.is_valid(raise_exception=True)
      print('after validate')

      # Perform creation
      self.perform_create(serializer)
      print('after perform_create')

      return serializer

  def create(self, request, *args, **kwargs):
     res = self._create(request, *args, **kwargs)

     if isinstance(res, Response):
        return res

     return Response(res.data, status=status.HTTP_201_CREATED)

class MyModelModelViewSet(MyModelInstViewSet):
   ...

我的 models.py 包含(注意 mymodel 模型类将 dfn 定义为 null=False):

    # models.py

    from enum import Enum

    from django.db import models
    from django.conf import settings
    from django.core.exceptions import ValidationError

    from django.utils.translation import gettext as _

    from secure.models import User as mymodelrUser

    CHARFIELD_MAX_LENGTH = settings.CHARFIELD_MAX_LENGTH

    # Create your models here.

    class AbstractModel(models.Model):
        created_at  = models.DateTimeField(auto_now_add=True, null=False, blank=False,)
        updated_at  = models.DateTimeField(auto_now_add=False, null=True, blank=False,)
        barcode     = models.CharField(max_length=CHARFIELD_MAX_LENGTH, null=False, blank=False,)

        def clean_fields(self, fields):
            if fields is None:
                fields = self._meta.fields

            for field in fields:
                # Generate method name for field
                method_name = f"clean_{field.name}"
                # Check if method exists and call it
                if hasattr(self, method_name):
                    getattr(self, method_name)()

        def save(self, *args, **kwargs):
            self.clean_fields(None)
            super().save(*args, **kwargs)

        def __str__(self):
            if self.pk:  # Check if the object has been saved to the database
                id = self.pk
            else:
                id = '<None>'

            if self.barcode:
                barcode = f"\"{self.barcode}\""
            else:
                barcode = '<None>'

            return f"[{self.__module__}.{self.__class__.__name__}(id={id}, code={barcode})]"

        class Meta:
            abstract = True
            ordering = ['updated_at', 'created_at',]

    # Base Model class for all Def models
    class AbstractDefModel(AbstractModel):
        class Meta:
            abstract = True

    # Base Model class for all instance models
    class AbstractInstModel(AbstractModel):
        class Meta:
            abstract = True


    # mymodel Models

    class mymodelFields(models.Model):
        ...
        class Meta:
            abstract = True

    class mymodelDef(AbstractDefModel, mymodelFields):
        parent      = models.ForeignKey('self', on_delete=models.CASCADE, related_name='children', null=True, blank=False,)

        class Meta(AbstractDefModel.Meta):
            abstract = False
            constraints = [
                models.UniqueConstraint(fields=['barcode'], name='constraint_unique_mymodelrdef_barcode')
            ]
            verbose_name = 'mymodeldef'
            verbose_name_plural = 'mymodeldefs'

    class mymodel(AbstractInstModel, mymodelFields):
        parent      = models.ForeignKey('self', on_delete=models.CASCADE, related_name='children', null=True, blank=False,)
        dfn         = models.ForeignKey('mymodelDef', on_delete=models.CASCADE, related_name='instances', null=False, blank=False,)

        address     = models.CharField(max_length=CHARFIELD_MAX_LENGTH, null=False, blank=False,)

        class Meta(AbstractInstModel.Meta):
            abstract = False
            verbose_name = 'mymodel'
            verbose_name_plural = 'mymodels'

我的网址.py:

    # urls.py

    from django.urls import path, include
    from . import views
    from rest_framework import routers

    router = routers.DefaultRouter()

    router.register(prefix=r'mymodels',    viewset=views.MyModelViewSet,    basename='mymodel')

    urlpatterns = [
        path('api/', include(router.urls)),
        path('', views.home_view, name='home'),
    ]

当我使用有效负载发布 /api/mymodel/ 时:

{
  "dfn_id": 11,
  "barcode": "Test DFNID POST CREATE!",
  "address": "This is a test"
}

我的运行服务器抛出此错误:

    (venv) D:\projects\mymodeler>python manage.py runserver
    Watching for file changes with StatReloader
    [2024-03-03 21:00:09] [INFO]: Watching for file changes with StatReloader
        [Path]: D:\projects\mymodeler\venv\lib\site-packages\django\utils\autoreload.py:668
    Performing system checks...

    System check identified no issues (0 silenced).
    March 03, 2024 - 21:00:10
    Django version 5.0.1, using settings 'mymodeler.settings'
    Starting development server at http://127.0.0.1:8000/
    Quit the server with CTRL-BREAK.

    {'dfn_id': 11, 'barcode': 'Test DFNID POST CREATE!', 'address': 'This is a test'}
    {'external_id': None, 'created_at': datetime.datetime(2024, 3, 3, 10, 0, 12, 33136, tzinfo=datetime.timezone.utc), 'options': None, 'status': 1, 'barcode': 'Test DFNID POST CREATE!', 'is_virtual': False, 'is_storage': False, 'is_mobile': False, 'max_weight': None, 'max_height': None, 'max_width': None, 'max_length': None, 'parent': None, 'dfn_id': 11, 'address': 'This is a test'}
    about to validate
    after validate
    Internal Server Error: /api/mymodels/
    Traceback (most recent call last):
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\backends\utils.py", line 105, in _execute
        return self.cursor.execute(sql, params)
    psycopg2.errors.NotNullViolation: null value in column "dfn_id" of relation "core_mymodel" violates not-null constraint
    DETAIL:  Failing row contains (63, null, null, 2024-03-03 10:00:12.035136+00, null, Test DFNID POST CREATE!, f, 1, f, f, null, null, null, null, This is a test, null, null, null, null, null, null).


    The above exception was the direct cause of the following exception:

    Traceback (most recent call last):
    File "D:\projects\mymodeler\venv\lib\site-packages\django\core\handlers\exception.py", line 55, in inner
        response = get_response(request)
    File "D:\projects\mymodeler\venv\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
        response = wrapped_callback(request, *callback_args, **callback_kwargs)
    File "D:\projects\mymodeler\venv\lib\site-packages\django\views\decorators\csrf.py", line 65, in _view_wrapper
        return view_func(request, *args, **kwargs)
    File "D:\projects\mymodeler\venv\lib\site-packages\rest_framework\viewsets.py", line 125, in view
        return self.dispatch(request, *args, **kwargs)
    File "D:\projects\mymodeler\venv\lib\site-packages\rest_framework\views.py", line 509, in dispatch
        response = self.handle_exception(exc)
    File "D:\projects\mymodeler\venv\lib\site-packages\rest_framework\views.py", line 469, in handle_exception
        self.raise_uncaught_exception(exc)
    File "D:\projects\mymodeler\venv\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception
        raise exc
    File "D:\projects\mymodeler\venv\lib\site-packages\rest_framework\views.py", line 506, in dispatch
        response = handler(request, *args, **kwargs)
    File "D:\projects\mymodeler\core\views.py", line 170, in create
        res = self._create(request, *args, **kwargs)
    File "D:\projects\mymodeler\core\views.py", line 164, in _create
        self.perform_create(serializer)
    File "D:\projects\mymodeler\venv\lib\site-packages\rest_framework\mixins.py", line 24, in perform_create
        serializer.save()
    File "D:\projects\mymodeler\venv\lib\site-packages\rest_framework\serializers.py", line 212, in save
        self.instance = self.create(validated_data)
    File "D:\projects\mymodeler\venv\lib\site-packages\rest_framework\serializers.py", line 962, in create
        instance = ModelClass._default_manager.create(**validated_data)
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\models\manager.py", line 87, in manager_method
        return getattr(self.get_queryset(), name)(*args, **kwargs)
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\models\query.py", line 677, in create
        obj.save(force_insert=True, using=self.db)
    File "D:\projects\mymodeler\core\models.py", line 39, in save
        super().save(*args, **kwargs)
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\models\base.py", line 822, in save
        self.save_base(
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\models\base.py", line 909, in save_base
        updated = self._save_table(
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\models\base.py", line 1067, in _save_table
        results = self._do_insert(
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\models\base.py", line 1108, in _do_insert
        return manager._insert(
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\models\manager.py", line 87, in manager_method
        return getattr(self.get_queryset(), name)(*args, **kwargs)
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\models\query.py", line 1845, in _insert
        return query.get_compiler(using=using).execute_sql(returning_fields)
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\models\sql\compiler.py", line 1823, in execute_sql
        cursor.execute(sql, params)
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\backends\utils.py", line 122, in execute
        return super().execute(sql, params)
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\backends\utils.py", line 79, in execute
        return self._execute_with_wrappers(
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\backends\utils.py", line 92, in _execute_with_wrappers
        return executor(sql, params, many, context)
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\backends\utils.py", line 100, in _execute
        with self.db.wrap_database_errors:
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\utils.py", line 91, in __exit__
        raise dj_exc_value.with_traceback(traceback) from exc_value
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\backends\utils.py", line 105, in _execute
        return self.cursor.execute(sql, params)
    django.db.utils.IntegrityError: null value in column "dfn_id" of relation "core_mymodel" violates not-null constraint
    DETAIL:  Failing row contains (63, null, null, 2024-03-03 10:00:12.035136+00, null, Test DFNID POST CREATE!, f, 1, f, f, null, null, null, null, This is a test, null, null, null, null, null, null).

    [2024-03-03 21:00:12] [ERROR]: Internal Server Error: /api/mymodels/
        [Path]: D:\projects\mymodeler\venv\lib\site-packages\django\utils\log.py:241
    Traceback (most recent call last):
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\backends\utils.py", line 105, in _execute
        return self.cursor.execute(sql, params)
    psycopg2.errors.NotNullViolation: null value in column "dfn_id" of relation "core_mymodel" violates not-null constraint
    DETAIL:  Failing row contains (63, null, null, 2024-03-03 10:00:12.035136+00, null, Test DFNID POST CREATE!, f, 1, f, f, null, null, null, null, This is a test, null, null, null, null, null, null).


    The above exception was the direct cause of the following exception:

    Traceback (most recent call last):
    File "D:\projects\mymodeler\venv\lib\site-packages\django\core\handlers\exception.py", line 55, in inner
        response = get_response(request)
    File "D:\projects\mymodeler\venv\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
        response = wrapped_callback(request, *callback_args, **callback_kwargs)
    File "D:\projects\mymodeler\venv\lib\site-packages\django\views\decorators\csrf.py", line 65, in _view_wrapper
        return view_func(request, *args, **kwargs)
    File "D:\projects\mymodeler\venv\lib\site-packages\rest_framework\viewsets.py", line 125, in view
        return self.dispatch(request, *args, **kwargs)
    File "D:\projects\mymodeler\venv\lib\site-packages\rest_framework\views.py", line 509, in dispatch
        response = self.handle_exception(exc)
    File "D:\projects\mymodeler\venv\lib\site-packages\rest_framework\views.py", line 469, in handle_exception
        self.raise_uncaught_exception(exc)
    File "D:\projects\mymodeler\venv\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception
        raise exc
    File "D:\projects\mymodeler\venv\lib\site-packages\rest_framework\views.py", line 506, in dispatch
        response = handler(request, *args, **kwargs)
    File "D:\projects\mymodeler\core\views.py", line 170, in create
        res = self._create(request, *args, **kwargs)
    File "D:\projects\mymodeler\core\views.py", line 164, in _create
        self.perform_create(serializer)
    File "D:\projects\mymodeler\venv\lib\site-packages\rest_framework\mixins.py", line 24, in perform_create
        serializer.save()
    File "D:\projects\mymodeler\venv\lib\site-packages\rest_framework\serializers.py", line 212, in save
        self.instance = self.create(validated_data)
    File "D:\projects\mymodeler\venv\lib\site-packages\rest_framework\serializers.py", line 962, in create
        instance = ModelClass._default_manager.create(**validated_data)
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\models\manager.py", line 87, in manager_method
        return getattr(self.get_queryset(), name)(*args, **kwargs)
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\models\query.py", line 677, in create
        obj.save(force_insert=True, using=self.db)
    File "D:\projects\mymodeler\core\models.py", line 39, in save
        super().save(*args, **kwargs)
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\models\base.py", line 822, in save
        self.save_base(
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\models\base.py", line 909, in save_base
        updated = self._save_table(
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\models\base.py", line 1067, in _save_table
        results = self._do_insert(
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\models\base.py", line 1108, in _do_insert
        return manager._insert(
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\models\manager.py", line 87, in manager_method
        return getattr(self.get_queryset(), name)(*args, **kwargs)
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\models\query.py", line 1845, in _insert
        return query.get_compiler(using=using).execute_sql(returning_fields)
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\models\sql\compiler.py", line 1823, in execute_sql
        cursor.execute(sql, params)
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\backends\utils.py", line 122, in execute
        return super().execute(sql, params)
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\backends\utils.py", line 79, in execute
        return self._execute_with_wrappers(
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\backends\utils.py", line 92, in _execute_with_wrappers
        return executor(sql, params, many, context)
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\backends\utils.py", line 100, in _execute
        with self.db.wrap_database_errors:
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\utils.py", line 91, in __exit__
        raise dj_exc_value.with_traceback(traceback) from exc_value
    File "D:\projects\mymodeler\venv\lib\site-packages\django\db\backends\utils.py", line 105, in _execute
        return self.cursor.execute(sql, params)
    django.db.utils.IntegrityError: null value in column "dfn_id" of relation "core_mymodel" violates not-null constraint
    DETAIL:  Failing row contains (63, null, null, 2024-03-03 10:00:12.035136+00, null, Test DFNID POST CREATE!, f, 1, f, f, null, null, null, null, This is a test, null, null, null, null, null, null).

    [03/Mar/2024 21:00:12] "POST /api/mymodels/ HTTP/1.1" 500 218095

打印语句正在打印,并清楚地表明传递给序列化器构造函数的数据字典具有“dfn_id”键(在本例中值为 11)。那么我如何让 'dfn_id' 为 None 呢?

提前非常感谢您的任何见解。

django django-views
1个回答
0
投票

我不是专家,但也许提供

dfn
而不是
dfn_id
就能完成工作。 如果您提供序列化器,它将有更多帮助。

© www.soinside.com 2019 - 2024. All rights reserved.