Метод ViewSet create никогда не проверяет вложенную модель
Я изучаю WebSockets [django channels], чтобы использовать их вместе с DRF. Я создал простую HTML-форму для создания Comment
. Форма содержит некоторые User
данные, чтобы каждый мог оставить свой комментарий, и введенные данные используются для создания нового User
(публикация комментария не требует никакой аутентификации).
Все работает нормально при отправке POST-запроса из DRF Browsable API. Однако не работает при отправке данных из HTML-формы: возвращается ошибка "user": ["This field is required."]
Модели:
class Comment(MPTTModel):
""" The base model represents comment object in db. """
user = models.ForeignKey(CustomUser, related_name="comments", on_delete=models.CASCADE)
date_created = models.DateTimeField(
verbose_name="Created at",
auto_now_add=True,
blank=True,
null=True
)
text = models.TextField(max_length=500)
class CustomUser(AbstractBaseUser, PermissionsMixin):
"""Custom User model extends a pre-defined django AbstractUser model."""
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
email = models.EmailField(verbose_name="email address", max_length=255, unique=True)
username = models.CharField(max_length=64, unique=True)
avatar = ResizedImageField(
force_format="WEBP",
crop=["middle", "center"],
upload_to=profile_avatar_path,
blank=True,
null=True,
max_length=500,
storage=OverwriteStorage()
)
homepage = models.URLField(max_length=255, null=True, blank=True)
enter code here
ViewSet:
class CommentViewSet(ModelViewSet):
""" Comment Viewset to handle base model operations. """
queryset = Comment.objects.filter(level=0)
serializer_class = CommentSerializer
def create(self, request, *args, **kwargs):
user_data = {}
for field, value in request.data.items():
if field.startswith("user"):
user_data.update({field.split("-")[1]: value})
request.data._mutable = True
request.data["user"] = user_data
request.data._mutable = False
print(request.data)
return super().create(request, *args, **kwargs)
Однако request.data
никогда не переходит к методу perform_create()
, так как застрял (похоже) на serializer.is_valid(rise_exception=True)
и не переходит к сериализатору create()
.
Serializers.py
class CommentSerializer(serializers.ModelSerializer):
""" Serializes Comment model data. """
user = BaseCustomUserSerializer()
rate = serializers.SerializerMethodField(read_only=True)
class Meta:
model = Comment
exclude = ('level', 'lft', 'rght', 'tree_id')
read_only_fields = ('date_created', )
def create(self, validated_data):
"""
Modified create method handle additional user creation
while creating new Comment by anonymous user.
"""
user_data = validated_data.pop('user')
try:
user = CustomUser.objects.get(pk=user_data.get('uuid'))
except ObjectDoesNotExist:
# performing atomic transaction to insure both instances created
with transaction.atomic():
new_user = CustomUser.objects.create(**user_data)
comment = Comment.objects.create(user=new_user, **validated_data)
return comment
else:
comment = Comment.objects.create(user=user, **validated_data)
return comment
Наконец, FORM:
<form action="http://127.0.0.1:8000/api/v1/comments/" method="post" id="newCommentForm" enctype="multipart/form-data"> {% csrf_token %}
<div class="field">
<label for="username">Username:</label>
<input type="text" name="user-username" id="username" required />
</div>
<div class="field">
<label for="user-email">Email: </label>
<input type="email" name="user-email" id="user-email" required />
</div>
<div class="field">
<label for="homepage">Homepage: </label>
<input type="url" name="user-homepage" id="homepage"/>
</div>
<div class="field">
<label for="text">Text</label>
<input type="text" name="text" id="text" required/>
</div>
<div class="g-recaptcha" data-sitekey="6LfA6NcpAAAAALR-d4hJGFOVZNb3bF6N1Ib-nIPt"></div>
<button data-action='submit'>Submit</button>
</form>