Python 3.x 如何将必填字段添加到我没有编写的模型中?
我正在使用Django 3、Python 3.7和Django地址模块-。我想指出局部性模型的State字段是必需的。因为我自己没有写模型,所以我不太确定该怎么做。我创建了下面的序列化程序Python 3.x 如何将必填字段添加到我没有编写的模型中?,python-3.x,django,django-models,django-rest-framework,django-validation,Python 3.x,Django,Django Models,Django Rest Framework,Django Validation,我正在使用Django 3、Python 3.7和Django地址模块-。我想指出局部性模型的State字段是必需的。因为我自己没有写模型,所以我不太确定该怎么做。我创建了下面的序列化程序 class AddressTypeField(serializers.PrimaryKeyRelatedField): queryset = Address.objects def to_internal_value(self, data): if type(data) =
class AddressTypeField(serializers.PrimaryKeyRelatedField):
queryset = Address.objects
def to_internal_value(self, data):
if type(data) == dict:
locality = data['locality']
state = None if not re.match(r"[0-9]+", str(locality['state'])) else State.objects.get(pk=locality['state'])
locality['state'] = state
locality, created = Locality.objects.get_or_create(**locality)
data['locality'] = locality
address = Address.objects.create(**data)
# Replace the dict with the ID of the newly obtained object
data = address.pk
return super().to_internal_value(data)
...
class CoopSerializer(serializers.ModelSerializer):
types = CoopTypeSerializer(many=True, allow_empty=False)
addresses = AddressTypeField(many=True)
phone = ContactMethodPhoneSerializer()
email = ContactMethodEmailSerializer()
class Meta:
model = Coop
fields = '__all__'
def to_representation(self, instance):
rep = super().to_representation(instance)
rep['types'] = CoopTypeSerializer(instance.types.all(), many=True).data
rep['addresses'] = AddressSerializer(instance.addresses.all(), many=True).data
return rep
def create(self, validated_data):
"""
Create and return a new `Snippet` instance, given the validated data.
"""
coop_types = validated_data.pop('types', {})
phone = validated_data.pop('phone', {})
email = validated_data.pop('email', {})
instance = super().create(validated_data)
for item in coop_types:
coop_type, _ = CoopType.objects.get_or_create(name=item['name'])
instance.types.add(coop_type)
instance.phone = ContactMethod.objects.create(type=ContactMethod.ContactTypes.PHONE, **phone)
instance.email = ContactMethod.objects.create(type=ContactMethod.ContactTypes.EMAIL, **email)
instance.save()
return instance
def update(self, instance, validated_data):
"""
Update and return an existing `Coop` instance, given the validated data.
"""
instance.name = validated_data.get('name', instance.name)
try:
coop_types = validated_data['types']
instance.types.clear() # Disassociates all CoopTypes from instance.
for item in coop_types:
coop_type, _ = CoopType.objects.get_or_create(**item)
instance.types.add(coop_type)
except KeyError:
pass
instance.addresses = validated_data.get('addresses', instance.addresses)
instance.enabled = validated_data.get('enabled', instance.enabled)
phone = validated_data.pop('phone', {})
email = validated_data.pop('email', {})
instance.phone = ContactMethod.objects.create(type=ContactMethod.ContactTypes.PHONE, **phone)
instance.email = ContactMethod.objects.create(type=ContactMethod.ContactTypes.EMAIL, **email)
instance.web_site = validated_data.get('web_site', instance.web_site)
instance.web_site = validated_data.get('web_site', instance.web_site)
instance.save()
return instance
但当我通过下面的序列化程序运行测试时
@pytest.mark.django_db
def test_coop_create_with_no_state(self):
""" Test coop serizlizer model """
name = "Test 8899"
coop_type_name = "Library"
street = "222 W. Merchandise Mart Plaza, Suite 1212"
city = "Chicago"
postal_code = "60654"
enabled = True
postal_code = "60654"
email = "test@example.com"
phone = "7739441422"
web_site = "http://www.1871.com"
serializer_data = {
"name": name,
"types": [
{"name": coop_type_name}
],
"addresses": [{
"formatted": street,
"locality": {
"name": city,
"postal_code": postal_code,
"state": ''
}
}],
"enabled": enabled,
"phone": {
"phone": phone
},
"email": {
"email": email
},
"web_site": web_site
}
serializer = CoopSerializer(data=serializer_data)
assert not serializer.is_valid()
assert len(serializer.errors.keys()) == 1
assert serializer.errors['phone']['phone'][0].code == "invalid_phone_number"
它会导致错误,而不是创建验证错误
Traceback (most recent call last):
File "/Users/davea/Documents/workspace/chicommons/maps/web/tests/test_serializers.py", line 142, in test_coop_create_with_no_state
assert not serializer.is_valid()
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/rest_framework/serializers.py", line 234, in is_valid
self._validated_data = self.run_validation(self.initial_data)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/rest_framework/serializers.py", line 433, in run_validation
value = self.to_internal_value(data)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/rest_framework/serializers.py", line 490, in to_internal_value
validated_value = field.run_validation(primitive_value)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/rest_framework/fields.py", line 565, in run_validation
value = self.to_internal_value(data)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/rest_framework/relations.py", line 519, in to_internal_value
return [
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/rest_framework/relations.py", line 520, in <listcomp>
self.child_relation.to_internal_value(item)
File "/Users/davea/Documents/workspace/chicommons/maps/web/directory/serializers.py", line 33, in to_internal_value
locality, created = Locality.objects.get_or_create(**locality)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/db/models/manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/db/models/query.py", line 562, in get_or_create
return self._create_object_from_params(kwargs, params)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/db/models/query.py", line 604, in _create_object_from_params
raise e
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/db/models/query.py", line 596, in _create_object_from_params
obj = self.create(**params)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/db/models/query.py", line 433, in create
obj.save(force_insert=True, using=self.db)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/db/models/base.py", line 745, in save
self.save_base(using=using, force_insert=force_insert,
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/db/models/base.py", line 782, in save_base
updated = self._save_table(
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/db/models/base.py", line 886, in _save_table
results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/db/models/base.py", line 923, in _do_insert
return manager._insert(
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/db/models/manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/db/models/query.py", line 1204, in _insert
return query.get_compiler(using=using).execute_sql(returning_fields)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1377, in execute_sql
cursor.execute(sql, params)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/db/backends/utils.py", line 68, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/db/backends/utils.py", line 77, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/db/backends/utils.py", line 86, in _execute
return self.cursor.execute(sql, params)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/db/utils.py", line 90, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/db/backends/utils.py", line 86, in _execute
return self.cursor.execute(sql, params)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/db/backends/mysql/base.py", line 74, in execute
return self.cursor.execute(query, args)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pymysql/cursors.py", line 170, in execute
result = self._query(query)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pymysql/cursors.py", line 328, in _query
conn.query(q)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pymysql/connections.py", line 517, in query
self._affected_rows = self._read_query_result(unbuffered=unbuffered)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pymysql/connections.py", line 732, in _read_query_result
result.read()
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pymysql/connections.py", line 1075, in read
first_packet = self.connection._read_packet()
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pymysql/connections.py", line 684, in _read_packet
packet.check_error()
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pymysql/protocol.py", line 220, in check_error
err.raise_mysql_exception(self._data)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pymysql/err.py", line 109, in raise_mysql_exception
raise errorclass(errno, errval)
django.db.utils.IntegrityError: (1048, "Column 'state_id' cannot be null")
如果我无法控制模型代码,如何向模型中添加必填字段?检查AddressTypeField字段中的状态emptynes,如下所示:
class AddressTypeField(serializers.PrimaryKeyRelatedField):
queryset = Address.objects
def to_internal_value(self, data):
if type(data) == dict:
locality = data['locality']
state = None if not re.match(r"[0-9]+", str(locality['state'])) else State.objects.get(pk=locality['state'])
if not state:
raise serializers.ValidationError({'state': 'This field is required.'})
locality['state'] = state
locality, created = Locality.objects.get_or_create(**locality)
data['locality'] = locality
address = Address.objects.create(**data)
# Replace the dict with the ID of the newly obtained object
data = address.pk
return super().to_internal_value(data)
默认情况下,django提供了一个用户字段,其中包含email not required,如果您想将其设置为required,或者您想更改未编写的模型,您可以这样做 将此放置在任何型号的.py中
from django.contrib.auth.models import User
User._meta.get_field('email').blank = False
Then run makemigrations. Then run migrate.
完成了 我想指出局部模型的State字段是必需的,错误列State_id不能为null;默认情况下,它是必需的,并且在序列化程序_数据中,状态中的数据丢失,这就是为什么它提供IntegrityError。您是否希望将其设置为可选?如果需要状态字段,验证是否应该返回错误,而不是尝试将实体保存到数据库中?是的,将assert not serializer.is_valid更改为assert serializer.is_valid将给出AssertionError。现在它让它执行下一行;assert not False为assert True。如果您坚持在try And except AssertionError中使用assert-fit-it,那么这种方法将更简单、更可读。出于某种原因,验证似乎调用了AddressTypeField的to_internal_value方法,这最终会产生错误。我认为我需要保持该方法的原样,以便成功创建与序列化程序的协作,但它似乎干扰了验证。您应该将内容保存在save而不是in to_internal_value中。如果后面的字段拒绝验证,那么重影位置在数据库中做什么?看看如何做得更好。谢谢。是否有一个更现成的解决方案,我可以利用?似乎我应该能够在某个地方指定一个blank=False或empty=False之类的值。如果没有重写to\u internal\u值,这是可能的。。。方法如果我们看看你的代码库,状态是由一些神奇的逻辑决定的,我不认为有更好的方法来替换逻辑,因为我不理解逻辑:P