views.py
def hello_world(request):
if request.user.is_authenticated:
if request.method == "POST":
temp = request.POST.get('hello_world_input')
new_hello_world = HelloWorld()
new_hello_world.text = temp
new_hello_world.save()
return HttpResponseRedirect(reverse('accountapp:hello_world'))
else:
hello_world_list = HelloWorld.objects.all()
return render(request, 'accountapp/hello_world.html', context={'hello_world_list': hello_world_list})
else:
return HttpResponseRedirect(reverse('accountapp:login'))
from datetime import datetime
def decorator(func):
def decorated():
print(datetime.now())
func()
print(datetime.now())
return
@decorater
함수를 받아 함수의 앞, 뒤, 앞뒤를 꾸며준다. 함수 내부에 직접적인 영향은 없다.
from django.contrib.auth.models import User
from django.http import HttpResponseForbidden
def account_ownership_required(func):
def decorated(request, *args, **kwargs):
user = User.objects.get(pk=kwargs['pk'])
if not user == request.user:
return HttpResponseForbidden()
return func(request, *args, **kwargs)
return decorated
has_ownership = [account_ownership_required, login_required]
@method_decorator(has_ownership, 'get')
@method_decorator(has_ownership, 'post')
python manage.py createsuperuser
settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
터미널
pip install pillow
python manage.py startapp profileapp
setting.py에서 profile app 명시
urls.py에서 경로 연결
profileapp/models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
연결되어 있는 user객체가 delete될 때 그와 연결되어 있는 profile 객체가 어떤 행동을 결정할지 정책 부분을 담당한다.
class ProfileCreationForm(ModelForm):
class Meta:
model = Profile
fields = ['image', 'nickname', 'message']
ModelForm을 상속받은 후에 어떤 모델을 사용할 것인지, 어떤 필드를 입력할 수 있게 만들 것인지 설정만 하면 model이 form으로 변화한다.
필요한 뷰를 만들고 form_vaild라는 함수를 적용했다.
def form_valid(self, form): #form_vaild 함수를 통해서 로직을 수행하고 성공적으로 마치면 알아서 success_url에 정의한 페이지로 이동한다.
temp_profile = form.save(commit=False) # 임시저장
temp_profile.user = self.request.user
temp_profile.save()
return super().form_valid(form) #슈퍼클래스, 즉 부모인 CreateView를 상속
detail.html
{% if target_user.profile %}
<h2 style="font-family: 'NanumSquareB' ">
{{ target_user.profile.nickname }}
</h2>
{% else %}
<a href="{% url 'profileapp:create' %}">
<h2 style="font-family: 'NanumSquareB'">
Create Profile
</h2>
</a>
{% endif %}
타겟 유저의 프로필이라면 프로필앱에서 닉네임을 보여준다. 그게 아니면 프로필을 만들도록 Create Profile을 띄운다.
urls.py 경로, static 설정
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('accountapp.urls')),
path('profiles/', include('profileapp.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
detail.py
<a href="{% url 'profileapp:update' pk=target_user.profile.pk %}">
edit
</a>
프로필 닉네임을 변경할 수 있도록 edit 추가
<img src="{{ target_user.profile.image.url }}" style="height: 12rem; width: 12rem; border-radius: 20rem; margin-bottom: 2rem;">
프로필 사진의 경로와 css 추가
decorators.py
from django.http import HttpResponseForbidden
from profileapp.models import Profile
def profile_ownership_required(func):
def decorated(request, *args, **kwargs):
profile = Profile.objects.get(pk=kwargs['pk'])
if not profile.user == request.user:
return HttpResponseForbidden()
return func(request, *args, **kwargs)
return decorated
유저의 프로필이 요청한 유저와 같지 않다면 forbidden 반환
views.py
@method_decorator(profile_ownership_required, 'get')
@method_decorator(profile_ownership_required, 'post')
def form_valid(self, form): #form_vaild 함수를 통해서 로직을 수행하고 성공적으로 마치면 알아서 success_url에 정의한 페이지로 이동한다.
temp_profile = form.save(commit=False) # 임시저장
temp_profile.user = self.request.user
temp_profile.save()
return super().form_valid(form) #슈퍼클래스, 즉 부모인 CreateView를 상속
이 부분을 이해하고 싶어 나름 주석까지 달아보며 열심히 노력했지만 확실하게 아는 느낌이 없다.
임시저장의 개념이 와닿지 않는다. 뭘 임시저장 하는걸까?
(주석을 달며 참고한 티스토리: https://iamthejiheee.tistory.com/69)