Created
May 12, 2026 09:40
-
-
Save sunmeat/47ecd378c1033f767d6c7fff7a2f2e03 to your computer and use it in GitHub Desktop.
django.forms.ModelForm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| models.py: | |
| import os | |
| from django.db import models | |
| from django.core.validators import MinLengthValidator | |
| from datetime import datetime | |
| def resume_upload_path(instance, filename): | |
| """Генерує шлях для резюме""" | |
| ext = os.path.splitext(filename)[1].lower() | |
| new_name = f"resume_{datetime.now().strftime('%Y%m%d_%H%M%S')}{ext}" | |
| return f'resumes/{new_name}' | |
| def avatar_upload_path(instance, filename): | |
| """Генерує шлях для аватарки""" | |
| ext = os.path.splitext(filename)[1].lower() | |
| new_name = f"avatar_{datetime.now().strftime('%Y%m%d_%H%M%S')}{ext}" | |
| return f'avatars/{new_name}' | |
| class ResumeApplication(models.Model): | |
| """Модель для зберігання відправлених резюме""" | |
| full_name = models.CharField("ПІБ", max_length=150, validators=[MinLengthValidator(3)]) | |
| email = models.EmailField("Email") | |
| phone = models.CharField("Телефон", max_length=20) | |
| resume_file = models.FileField("Резюме", upload_to=resume_upload_path, blank=False) | |
| avatar = models.ImageField("Фото", upload_to=avatar_upload_path, blank=True, null=True) | |
| created_at = models.DateTimeField("Дата відправки", auto_now_add=True) | |
| class Meta: # для налаштування відображення в адмінці та сортування | |
| verbose_name = "Резюме" | |
| verbose_name_plural = "Резюме" | |
| ordering = ['-created_at'] | |
| def __str__(self): | |
| return f"{self.full_name} — {self.created_at.strftime('%d.%m.%Y %H:%M')}" | |
| ======================================================================================================= | |
| forms.py: | |
| from django import forms | |
| from django.core.validators import MinLengthValidator | |
| import os | |
| from .models import ResumeApplication | |
| def validate_phone(value): | |
| import re | |
| if value: | |
| cleaned = value.replace(' ', '').replace('(', '').replace(')', '').replace('-', '') | |
| if not re.match(r'^\+?380\d{9}$', cleaned): | |
| raise forms.ValidationError("Введіть коректний номер у форматі +380XXXXXXXXX") | |
| class ContactForm(forms.ModelForm): | |
| """ModelForm для відправки резюме""" | |
| class Meta: | |
| model = ResumeApplication | |
| fields = ['full_name', 'email', 'phone', 'resume_file', 'avatar'] | |
| labels = { | |
| 'full_name': "ПІБ", | |
| 'email': "Email адреса", | |
| 'phone': "Номер телефону", | |
| 'resume_file': "Файл з резюме", | |
| 'avatar': "Фото (аватар)", | |
| } | |
| widgets = { | |
| 'full_name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Шевченко Тарас Григорович'}), | |
| 'email': forms.EmailInput(attrs={'class': 'form-control', 'placeholder': 'taras.shevchenko@gmail.com'}), | |
| 'phone': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '+380 XX XXX XX XX', 'type': 'tel'}), | |
| 'resume_file': forms.ClearableFileInput(attrs={'class': 'form-control'}), | |
| 'avatar': forms.ClearableFileInput(attrs={'class': 'form-control'}), | |
| } | |
| help_texts = { | |
| 'resume_file': "Дозволено: PDF, DOC, DOCX (максимум 10 МБ)", | |
| 'avatar': "Дозволено: JPG, JPEG, PNG (максимум 5 МБ)", | |
| } | |
| def clean_resume_file(self): | |
| resume = self.cleaned_data.get('resume_file') | |
| if resume and resume.size > 10 * 1024 * 1024: | |
| raise forms.ValidationError("Файл резюме занадто великий. Максимальний розмір — 10 МБ.") | |
| return resume | |
| def clean_avatar(self): | |
| avatar = self.cleaned_data.get('avatar') | |
| if avatar and avatar.size > 5 * 1024 * 1024: | |
| raise forms.ValidationError("Фото занадто велике. Максимальний розмір — 5 МБ.") | |
| return avatar | |
| ======================================================================================================= | |
| views.py: | |
| from datetime import datetime | |
| from django.shortcuts import render, redirect | |
| from django.contrib import messages | |
| from .forms import ContactForm | |
| # !!! зробити міграції після оновлення трьох файлів !!! | |
| # python manage.py makemigrations | |
| # python manage.py migrate | |
| def contact(request): | |
| if request.method == 'POST': | |
| form = ContactForm(request.POST, request.FILES) | |
| if form.is_valid(): | |
| application = form.save() # зберігає і в БД, і файли | |
| print("\n" + "="*80) | |
| print("НОВЕ РЕЗЮМЕ ЗБЕРЕЖЕНО В БАЗУ!") | |
| print("="*80) | |
| print(f"ID запису: {application.id}") | |
| print(f"ПІБ: {application.full_name}") | |
| print(f"Email: {application.email}") | |
| print(f"Телефон: {application.phone}") | |
| print(f"Резюме: {application.resume_file}") | |
| if application.avatar: | |
| print(f"Аватар: {application.avatar}") | |
| print("="*80 + "\n") | |
| messages.success(request, 'Резюме успішно надіслано та збережено!') | |
| return redirect('contact') | |
| else: | |
| messages.error(request, 'Будь ласка, виправте помилки у формі.') | |
| else: | |
| form = ContactForm() | |
| return render(request, 'app/contact.html', { | |
| 'form': form, | |
| 'title': 'Відправка резюме', | |
| 'year': datetime.now().year, | |
| }) | |
| def home(request): | |
| return render(request, 'app/index.html', { | |
| 'title': 'Home Page', | |
| 'year': datetime.now().year, | |
| }) | |
| def about(request): | |
| return render(request, 'app/about.html', { | |
| 'title': 'About', | |
| 'message': 'Your application description page.', | |
| 'year': datetime.now().year, | |
| }) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment