[英]Django model with foreign key throws error on save
我有一個帶有外鍵的 model,當我嘗試創建新的 object 時會引發錯誤。 我相信外鍵字段(user_profile_id)是 NULL 出於某種原因(它不應該是),並且在嘗試創建時,會拋出錯誤(該字段永遠不應該為空)。 這是我得到的錯誤:
IntegrityError at /api/sensors/
NOT NULL constraint failed: sensors_api_sensor.user_profile_id
Request Method: POST
Request URL: http://127.0.0.1:8000/api/sensors/
Django Version: 2.2
Exception Type: IntegrityError
Exception Value:
NOT NULL constraint failed: sensors_api_sensor.user_profile_id
Exception Location: /home/vagrant/env/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py in execute, line 383
Python Executable: /home/vagrant/env/bin/python3
Python Version: 3.6.9
Python Path:
['/vagrant',
'/usr/lib/python36.zip',
'/usr/lib/python3.6',
'/usr/lib/python3.6/lib-dynload',
'/home/vagrant/env/lib/python3.6/site-packages']
Server time: Mon, 21 Dec 2020 08:29:01 +0000
模型.py:
class Sensor(models.Model):
"""Database model for users' sensors"""
user_profile = models.ForeignKey(
settings.AUTH_USER_MODEL, # first argument is the remote model for this foreign key
on_delete=models.CASCADE # if ForeignKey is deleted, delete all associations
)
name = models.CharField(max_length=255)
sensor_type = models.CharField(max_length=255)
surrounding = models.CharField(max_length=255)
latitude = models.FloatField()
longitude = models.FloatField()
created_at = models.DateTimeField(auto_now_add=True, null=False) # auto adds creation timestamp UTC for each object
updated_at = models.DateTimeField(auto_now=True, null=False)
# other fields required
REQUIRED_FIELDS = ['user_profile','name','type','surrounding']
# model to string conversion method
def __str__(self):
"""Return the model as a string"""
return self.name # returns the sensor name
序列化程序.py
class SensorSerializer(serializers.ModelSerializer):
"""Serializes a sensor object"""
class Meta:
# points serializer to WeatherSensor model
model = models.Sensor
# list fields you want to make accessible from WeatherSensor model in tuple
fields = ('id', 'user_profile', 'name', 'sensor_type', 'surrounding',
'latitude', 'longitude', 'created_at', 'updated_at')
# make foreign key read only by using extra keyword args variable
extra_kwargs = {'user_profile': {'read_only': True}}
視圖.py
class SensorListApiView(APIView):
"""Sensor List API View for list and create"""
serializer_class = serializers.SensorSerializer
def post(self, request):
"""Create a weather sensor"""
# self.serializer_class comes with APIView that retrieves serializer class for our review
serializer = self.serializer_class(data=request.data)
# validate input as per serializer class spec
if serializer.is_valid():
# can retrieve any field that is defined in our serializer
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
# use status library to pass human-readable error
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
設置.py
...
# Model Overrides
AUTH_USER_MODEL = 'profiles_api.UserProfile'
在測試一些奇怪的事情時,我觀察到:
user = models.UserProfile.objects.get(id=1)
ws = models.Sensor.objects.create(
user_profile=user, name='MoistureSensor1',
sensor_type='MoistureSensor', surrounding='greenhouse',
latitude=37.7749, longitude=122.4194,
created_at=timezone.now(), updated_at=timezone.now()
)
ws.save()
您想使用序列化程序創建與 request.user 相關的 object。
你需要在這里做的很簡單:
# serializers.py
class SensorSerializer(serializers.ModelSerializer):
"""Serializes a sensor object"""
class Meta:
# points serializer to WeatherSensor model
model = models.Sensor
# list fields you want to make accessible from WeatherSensor model in tuple
fields = ('id', 'user_profile', 'name', 'sensor_type', 'surrounding',
'latitude', 'longitude', 'created_at', 'updated_at')
# make foreign key read only by using extra keyword args variable
extra_kwargs = {'user_profile': {'read_only': True}}
def create(self, validated_data):
user = self.context["request"].user
sensor = models.Sensor.objects.create(user_profile=user, **validated_data)
return sensor
# views.py
class SensorListApiView(APIView):
"""Sensor List API View for list and create"""
serializer_class = serializers.SensorSerializer
def post(self, request):
"""Create a weather sensor"""
# self.serializer_class comes with APIView that retrieves serializer class for our review
serializer = self.serializer_class(data=request.data, context={"request":request})
# You need to pass the request in the context.
# etc...
請小心,因為我在您的代碼中沒有看到您檢查用戶是否實際登錄的任何地方。
嘗試從序列化程序中刪除user_profile
,然后:
if serializer.is_valid():
serializer.save(user_profile=request.user)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.