...
from .models import Profile
class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput)
class UserEditForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email')
class ProfileEditForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('date_of_birth', 'photo')
class UserRegistrationForm(forms.ModelForm):
password = forms.CharField(label='Password', widget=forms.PasswordInput)
password_confirm = forms.CharField(
label='Repeat password',
widget=forms.PasswordInput
)
class Meta:
model = User
fields = ('username', 'first_name', 'email')
def clean_password_confirm(self):
cd = self.cleaned_data
if cd['password'] != cd['password_confirm']:
raise forms.ValidationError("Passwords don't match.")
return cd['password_confirm']
...
from .services.utils import get_random_default_profile_photo
class Profile(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
date_of_birth = models.DateField(blank=True, null=True)
photo = models.ImageField(
upload_to='media/users/%Y/%m/%d',
default=get_random_default_profile_photo,
blank=True,
storage=FileSystemStorage(location=str(settings.BASE_DIR), base_url='/'),
)
def __str__(self):
return f'Profile for user {self.user.username}'
...
from . import views
urlpatterns = [
path('', views.dashboard, name='dashboard'),
path('', include('django.contrib.auth.urls')),
path('register/', views.register, name='register'),
path('edit/', views.edit, name='edit'),
]
...
from .forms import UserRegistrationForm, UserEditForm, ProfileEditForm
from .models import Profile
@login_required
def edit(request):
if request.method == 'POST':
user_form = UserEditForm(instance=request.user, data=request.POST)
profile_form = ProfileEditForm(
instance=request.user.profile,
data=request.POST,
files=request.FILES
)
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
messages.success(request, 'Profile updated successfully')
else:
messages.error(request, 'Error updating your profile')
else:
user_form = UserEditForm(instance=request.user)
profile_form = ProfileEditForm(instance=request.user.profile)
return render(
request,
'account/edit.html',
{'user_form': user_form, 'profile_form': profile_form}
)
def register(request):
if request.method == 'POST':
user_form = UserRegistrationForm(request.POST)
if user_form.is_valid():
new_user = user_form.save(commit=False)
new_user.set_password(user_form.cleaned_data['password'])
new_user.save()
Profile.objects.create(user=new_user)
return render(
request,
'account/register_done.html',
{'new_user': new_user}
)
else:
user_form = UserRegistrationForm()
return render(request, 'account/register.html', {'user_form': user_form})
...
from .models import Image
class ImageCreateForm(forms.ModelForm):
class Meta:
model = Image
fields = ['title', 'url', 'description']
widgets = {'url': forms.HiddenInput}
def clean_url(self):
url = self.cleaned_data['url']
valid_suffixes = ('.jpg', '.jpeg', '.png', '.gif')
image_suffix = Path(url).suffix
if image_suffix not in valid_suffixes:
raise forms.ValidationError(
f'The given URL({url}) does not match valid image extensions!'
)
return url
def save(self, force_insert=False, force_update=False, commit=True):
url = self.cleaned_data['url']
# Get an image object.
response = requests.get(url)
image = super().save(commit=False)
image_slug = slugify(image.title)
filename_with_extension = image_slug + Path(url).suffix
image.image.save(
filename_with_extension,
ContentFile(response.content),
save=False
)
if commit:
image.save()
return image
...
class Image(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
related_name='images_created',
on_delete=models.CASCADE
)
users_liked = models.ManyToManyField(
settings.AUTH_USER_MODEL,
through='Like',
related_name='images_liked',
blank=True
)
image = models.ImageField(upload_to='images/%Y/%m/%d/')
title = models.CharField(max_length=200)
description = models.TextField(blank=True)
url = models.URLField(max_length=2048)
slug = models.SlugField(max_length=200, blank=True)
created = models.DateField(auto_now_add=True, db_index=True)
def __str__(self):
return self.title
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super().save(*args, **kwargs)
def get_absolute_url(self):
return reverse('images:detail', args=(self.id, self.slug))
def last_liked(self):
return self.users_liked.order_by('like__liked_at')
class Like(models.Model):
image = models.ForeignKey(Image, on_delete=models.CASCADE)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
liked_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('liked_at',)
...
urlpatterns = [
path('create/', views.image_create, name='create'),
path('detail/<int:id>/<slug:slug>/', views.image_detail, name='detail'),
path('like/', views.image_like, name='like'),
path('', views.images_list, name='list'),
]
...
from .forms import ImageCreateForm
from .models import Image
from bookmarks.services.decorators import ajax_required
@login_required
def image_create(request):
if request.method == 'POST':
form = ImageCreateForm(request.POST)
if form.is_valid():
new_image = form.save(commit=False)
new_image.user = request.user
new_image.save()
messages.success(request, 'Image added successfully')
return redirect(new_image.get_absolute_url())
else:
form = ImageCreateForm(request.GET)
return render(
request,
'images/image/create.html',
{
'section': 'images',
'form': form,
}
)
def image_detail(request, id, slug):
image = get_object_or_404(Image, id=id, slug=slug)
return render(
request,
'images/image/detail.html',
{
'section': 'images',
'image': image,
}
)
@ajax_required
@login_required
@require_POST
def image_like(request):
image_id = request.POST.get('image-id')
action = request.POST.get('action')
if image_id and action:
try:
image = Image.objects.get(id=image_id)
except Model.DoesNotExist:
return JsonResponse({'status': 'ImageDoesNotExist'})
if action == 'like':
image.users_liked.add(request.user)
elif action == 'unlike':
image.users_liked.remove(request.user)
return JsonResponse({'status': 'ok'})
return JsonResponse({'status': 'Bad request'})
@login_required
def images_list(request):
page = request.GET.get('page')
all_images = Image.objects.all()
paginator_object = paginator.Paginator(all_images, settings.IMAGES_ON_PAGE)
try:
images = paginator_object.page(page)
except paginator.PageNotAnInteger:
images = paginator_object.page(1)
except paginator.EmptyPage:
if request.is_ajax():
return HttpResponse('')
images = paginator_object.page(paginator_object.num_pages)
if request.is_ajax():
template_name = 'images/image/list_ajax.html'
else:
template_name = 'images/image/list.html'
return render(
request,
template_name,
{
'section': 'images',
'images': images,
}
)
if POST:
сериализуем объект
рендерим страницу с сообщением об успехе
else:
рендерим страницу с формой