Тест поля изображения в представлении
Я пытаюсь разместить изображение на url 'accounts/profile_edit' в одном из моих тестов. У меня есть модель Profile, которая изменяет размер изображений больше, чем (225, 255), и это та функциональность, которую я хочу протестировать. Я прочитал как юнит-тестировать загрузку файлов в django, но я не могу заставить client.post работать с изображением. В чем проблема?
class TestProfileEditView(TestCase):
# other tests...
def test_profile_picture_resize(self):
self.client.force_login(user=self.user)
image = Image.new('RGB', (500, 500), (255, 255, 255))
image_location = f'{settings.MEDIA_ROOT}/TestProfilePictureResize.png'
image.save(image_location)
with open(image_location ,'rb') as f:
response = self.client.post(reverse('profile-edit-view'), {'picture': f})
profile = Profile.objects.get(user=self.user.id)
picture_path = profile.picture # falsely returns default picture location
self.assertEqual(picture_path,
/media/profile_pictures/TestProfilePictureResize.png)
self.assertTemplateUsed(response, 'user/profile.html') # returns False
views.py :
@login_required
def profile_edit(request):
if request.method == 'POST':
user_form = UserEditForm(request.POST, instance=request.user)
profile_form = ProfileEditForm(
request.POST, request.FILES, instance=request.user.profile)
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
messages.success(request, f'Profile Edited Successfully.')
return redirect(reverse('profile-view'), request.user)
else:
user_form = UserEditForm(instance=request.user)
profile_form = ProfileEditForm(instance=request.user.profile)
context = {
'user_form': user_form,
'profile_form': profile_form
}
return render(request, 'user/profile_edit.html', context)
models.py :
class User(AbstractUser):
email = models.EmailField(unique=True, blank=False, null=False)
first_name = models.CharField(max_length=50, blank=False, null=False)
last_name = models.CharField(max_length=50, blank=False, null=False)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["first_name", "last_name"]
def __str__(self):
return f"{self.first_name} {self.last_name}"
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
picture = models.ImageField(
default=f"default_profile_picture.png",
upload_to="profile_pictures"
)
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
with Image.open(self.picture.path) as image:
if image.height > 225 or image.width > 225:
size = (225, 225)
image.resize(size, Image.ANTIALIAS).save(self.picture.path)
def __str__(self):
return f"{self.user.first_name} {self.user.last_name} Profile"
Я нашел ответ. Если у вас есть две ModelForms в представлении, поскольку они уже заполнены данными, вы должны следить за ними обеими. Вы не можете передавать данные в одну из них и не отправлять данные в другую, если у последней есть какое-либо поле, которое является обязательным. В моем случае, поскольку я не передал никаких данных в UserEditForm, метод is_valid() вернул False и, исходя из логики представлений, user_form.save() и profile_form.save() так и не выполнились. решение (передача валидных данных в user_form):
with open(test_image_location,'rb') as f:
response = self.client.post(reverse('profile-edit-view'), {
'email':'ProfileEditViewTest@google.com',
'first_name':'first',
'last_name':'last',
'picture': f }, follow=True)