Kategori arşivi: Django

Django Framework hakkında Türkçe bilgiler, ipuçları, kod örnekleri, örnek projeler, sorunlar ve çözümler, fikir alışverişi, düşünceler ve daha fazlası

Django’da Migrationlar Nasıl Sıfırlanır?

Uygulamanızda çokça migration dosyası olabilir, bu konuda korkmanıza veya gerilmenize gerek yok hiç bir sıkıntı çıkmaksızın kullanmaya devam edebilirsiniz. Testlerinizi çalıştırırken sadece süreyi uzatacaktır. ci/cd süreçlerinde bunu biraz iyileştirmek isterseniz kullanabilirsiniz ancak bence gerek yok.

Git kullanıyorsanız bu işlemi yaparken öyle fazla korkmanıza da gerek yok, sadece Migration ve gerekli dosyaları kaldıracağız sonrasında ise sıfırlayıp temiz bir sayfa açacağız.

Dosyaları kaldıralım hızlıca

find . -path "*/migrations/*.py" -not -name "__init__.py" -delete
find . -path "*/migrations/*.pyc"  -delete
Python

Sonrasında gidip veri tabanından kayıtlarını da sileceğiz, veri tabanı üzerinde bir oturum açmayın direk uygulama üzerinden python manage.py shell komutunu girerek bir python kabuk oturumu başlatın. ve aşağıdaki komutu çalıştırın.

from django.db.migrations.recorder import MigrationRecorder
MigrationRecorder.Migration.objects.all().delete()
Python

Şimdi her şey tamamlandığına göre temiz bir sayfa için migration oluşturma komutunu verelim.

python manage.py makemigrations
ShellScript

Şimdi oluşturduğunuz bu dosyalar üzerinde tekrar migrate işlemi yaparsanız hoş olmaz çünkü zaten bu değişiklikler veritabanında yer alıyor. O sebeple --fake komutu ile geçmiş gibi yapmamız gerekiyor ki temiz bir sayfa açmış olalım.

python manage.py migrate --fake-initial
ShellScript

Evet başarılı bir şekilde işlemimizi tamamladık, çok ama çok gerekmedikçe asla migration dosyalarında sıfırlama işlemi yapmayın. Nasıl yapılacağını bilmenizde bir sakınca yok.

Django Pagination with Bulma CSS

We needed django pagination in a small project, I edited a piece of code that was visually compatible for bulma css you may need to make some changes to the code (design, structural or general)

Follow the steps below to add to the template, First, let’s create our file that we are going to add.

{% include "include/__pagination.html" %}

then replace the contents of the file with the below

{% if list.has_other_pages %}
    <div class="column">
        <nav class="pagination is-centered" role="navigation" aria-label="pagination">
            <ul class="pagination-list">
                {% if list.has_previous %}
                    <li><a class="pagination-link" aria-label="page"
                           href="?page={{ list.previous_page_number }}">&laquo;</a></li>
                {% else %}
                    <li class="disabled"><span>&laquo;</span></li>
                {% endif %}
                {% for i in list.paginator.page_range %}
                    {% if list.number == i %}
                        <li><a class="pagination-link is-current" aria-label="Page {{ i }}"
                               aria-current="page">{{ i }}</a></li>
                    {% else %}
                        <li><a class="pagination-link" aria-label="Goto page {{ i }}" href="?page={{ i }}">{{ i }}</a>
                        </li>
                    {% endif %}
                {% endfor %}
                {% if list.has_next %}
                    <li><a class="pagination-link" aria-label="Goto page {{ list.next_page_number }}"
                           href="?page={{ list.next_page_number }}">&raquo;</a></li>
                {% else %}
                    <li class="disabled"><span>&raquo;</span></li>
                {% endif %}
            </ul>
        </nav>
    </div>
{% endif %}

Finally, add to the templates you need pagination, now you have a proper pagination template. If you want, you can make minor improvements.

Django’da Kullanıcıları Tek Oturuma Nasıl Zorlarız?

Kullanıcıların birden fazla yerde oturum açmalarını engellemek isterseniz aşağıdaki gibi bir yapı kullanarak engelleme yapabilirsiniz. Oturumlarda kullanılan session_id kontrol edilecek ve tekilleştirilme uygulanacak birden fazla sessin olursa bir önceki session otomatik kapatılacak.

from django.contrib.sessions.models import Session

# utils.py
def get_client_ip(request):
    x_forwarded_for = request.META.get("HTTP_X_FORWARDED_FOR")
    if x_forwarded_for:
        ip = x_forwarded_for.split(",")[0]
    elif len(request.META.get("REMOTE_ADDR")) > 6:
        ip = request.META.get("REMOTE_ADDR")
    elif len(request.META.get("CF-Connecting-IP")) > 6:
        ip = request.META.get("CF-Connecting-IP")
    return ip

# models.py
class LoggedInUser(models.Model):
    user = models.OneToOneField(
        Users, on_delete=models.CASCADE, related_name="logged_in_user"
    )
    session_key = models.CharField(max_length=32, null=True, blank=True)
    ipAddress = models.GenericIPAddressField()

    class Meta:
        app_label = "account"

    def __str__(self):
        return self.user.email

# middleware.py
class OneSessionPerUserMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        if request.user.is_anonymous is False and customer_multiple_session:
            pass
        else:
            if request.user.is_authenticated:
                session_key = request.session.session_key
                client_ip = get_client_ip(request)
                try:
                    stored_session_key = (
                        request.user.logged_in_user.session_key
                    )

                    if stored_session_key != session_key:
                        Session.objects.filter(
                            session_key=stored_session_key
                        ).delete()

                    request.user.logged_in_user.session_key = session_key
                    request.user.logged_in_user.save()
                except LoggedInUser.DoesNotExist:
                    LoggedInUser.objects.create(
                        user=request.user,
                        session_key=session_key,
                        ipAddress=client_ip,
                    )

        response = self.get_response(request)
        return response

Django MongoDB Paginator

Mongodb kullananlar django’nun kendi paginatorunu kullandıklarında performans sorunları yaşıyor olabilirler, bu kod ile bu sorunu ortadan kaldırabilirsiniz. Kullanmayı bıraktığımız bu güzel kodumuz sizlerle.

Kendinize göre uyarlamayı ihmal etmeyin, kodumuzda sayfa kaldığı yerden devam etsin diye ufak tefek değişiklikler yapılmıştır.

def mongo_paginator(request, data, paginate_by):
    page = int(request.GET.get("page", 1))
    if len(request.GET) > 0:
        get_value = dict(request.GET)
        if get_value.get("page"):
            del get_value["page"]
        url = "?" + str(urlencode(get_value, doseq=True)) + "&page="
    else:
        url = "?page="
    row_count = int(data.count())
    page_count = int(row_count / paginate_by) + \
        1 if row_count > paginate_by else 1
    pagi = {
        "page_range": range(1, page_count+1),
        "has_other_pages": page_count > 1,
        "number": page,
        "has_previous": page > 1,
        "previous_page_number": page - 1,
        "has_next": page < page_count,
        "next_page_number": page + 1,
        "url": url,
    }

    if request.GET.get("page"):
        if page > 1:
            first = paginate_by * (page - 1)
            last = first + paginate_by
            data = data[first:last]
        elif page == 1:
            data = data[:paginate_by]
    else:
        data = data[:paginate_by]
    return {"data": data, "pagi": pagi}

BONUS

def paginate(queryset, request, paginate_by):
    paginator = Paginator(queryset, paginate_by)
    try:
        datum = paginator.page(request.GET.get("page"))
    except PageNotAnInteger:
        datum = paginator.page(1)
    except EmptyPage:
        datum = paginator.page(paginator.num_pages)
    return datum


def get_page_url(request):
    if len(request.GET) > 1:
        get_value = dict(request.GET)
        if get_value.get("page"):
            del get_value["page"]
        url = "?" + str(urlencode(get_value, doseq=True)) + "&page="
    else:
        url = "?page="
    return url

Django’da Parolasız Oturum Açma(Passwordless Authentication) Mekanizması Nasıl Uygulanır?

Sızdırılan parolaların durumları ortada hal böyle olunca alternatif oturum açma mekanizmaları gündeme gelmeye başladı, bunlardan bizimde zamanında kullandığımız yöntemi artık açıklama zamanı geldi. Bu sistemi hali hazırda kullanmayı bıraktık, elimde kalan halini sizlerle paylaşıyorum.

Öncelikli olarak bu sistemde uygulanan yapıda girişler suistimal edilmemesi amacıyla hem tek kullanımlık URL hemde giriş sırasında mail gatewaylerin linkin geçerliliğini devre dışı bırakmaması için hCaptcha ekledik. Tabii bu durum kullanıcıların canını biraz sıktı diyebiliriz, ama güvenlikten ödün vermedik.

Önce kullanıcının sisteme girebilmesi amacıyla bizim belirli bir link oluşturmamız gerekiyor, daha sonra oluşturulan bu link mail aracılığı ile kullanıcıya gidecek oluşturacağımız bu linkin ise belirli bir geçerlilik süresi olacak aynı zamanda link tıklandığında geçerliliğini güvenlik için yitirecek.

class IsLogin(FormView):
    http_method_names = ["get", "post"]
    template_name = "account/login.html"
    email_template_name = "account/mails/login_email.html"
    form_class = UserForm
    success_url = settings.LOGIN_REDIRECT_URL

    def form_valid(self, form):
        try:
            user = Users.objects.get(email=form.cleaned_data["email"], customer__is_active=True)
        except Users.DoesNotExist:
            messages.success(self.request, _("If an account matches the username %s, you should receive an email with magic link." % form.cleaned_data["email"]))
        else:
            current_site = get_current_site(self.request)
            mail_subject = _("Login your account.")
            mail_message = render_to_string(
                self.email_template_name,
                {
                    "user": user,
                    "domain": current_site.domain,
                    "uid": urlsafe_base64_encode(force_bytes(user.pk)),
                    "token": account_activation_token.make_token(user),
                },
            )
            email = EmailMessage(from_email='noreply@mertcangokgoz.com', to=[user.email], subject=mail_subject, body=mail_message)
            email.content_subtype = "html"
            email.send()
            messages.success(self.request, _("If an account matches the username %s, you should receive an email with magic link." % form.cleaned_data["email"]))
        return render(self.request, self.template_name, {"form":self.get_form()})

    def form_invalid(self, form):
        return render(
            self.request, self.template_name, {'form':self.get_form()}
        )

Sisteme giriş yapmış bir kullanıcı tekrar bir şekilde istekte bulunmasın diyede ayrıca kontrol ediyoruz giriş yapmışsa tekrar ilgili alana yönlendiriyoruz.

    def get(self, request, *args, **kwargs):
        if self.request.user.is_authenticated:
            return HttpResponseRedirect(resolve_url(self.success_url))
        return super().get(request, *args, **kwargs)

Eposta oluşturduğumuz ve gerekli bilgileri girdiğimiz noktada ise kullanıcıya özel bir token oluşturuyoruz. Ve bu tokenle birlikte bağlantılı olan verileri ekliyoruz.

mail_message = render_to_string(
self.email_template_name,
 {
    "user": user,
    "domain": current_site.domain,
    "uid": urlsafe_base64_encode(force_bytes(user.pk)),
    "token": account_activation_token.make_token(user),
 },
)

Tokeni ise kullanıcıya göre aşağıdaki şekilde oluşturuyoruz. Burada önemli olan magic_link_secret_key değerinin giriş yapıldıktan sonra otomatik olarak değişmesi olacak.

from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.utils import six


class TokenGenerator(PasswordResetTokenGenerator):
    def _make_hash_value(self, user, timestamp):

        return (
            six.text_type(user.pk)
            + six.text_type(timestamp)
            + six.text_type(user.magic_link_secret_key)
        )


account_activation_token = TokenGenerator()

Hem OTP hemde Captcha için kullanacağımız sayfamızın ise kodları şu şekilde olacak.

class OTPView(View):
    template_name = "account/otp_login.html"

    def get(self, *args, **kwargs):
        try:
            uid = force_text(urlsafe_base64_decode(self.kwargs.get("uidb64")))
            user = Users.objects.get(pk=uid)
        except:
            messages.error(self.request, _("Link is invalid!"))
            return redirect("/")

        form = OtpCodeForm()
        otp = False

        if not account_activation_token.check_token(user, self.kwargs.get("token")):
            messages.error(self.request, _("Link is invalid!"))
            return redirect("login")

        if not user.otp_active and settings.OTP_IS_ACTIVE and user.is_2fa:
            if account_activation_token.check_token(user, self.kwargs.get("token")):
                return redirect("otp_activation", uidb64 = self.kwargs.get("uidb64"), token = self.kwargs.get("token"))
            else:
                return HttpResponse(_("Link is invalid!"))

        if user.is_2fa:
            if account_activation_token.check_token(user, self.kwargs.get("token")):
                otp = True

        return render(
            self.request, self.template_name, {"form": form, "hcaptcha_sitekey":settings.HCAPTCHA_SITEKEY, "otp":otp}
        )


    def post(self, *args, **kwargs):
        try:
            uid = force_text(urlsafe_base64_decode(self.kwargs.get("uidb64")))
            user = Users.objects.get(pk=uid)
        except:
            messages.error(self.request, _("Link is invalid!"))
            return redirect("/")
        form = OtpCodeForm(data=self.request.POST)
        if not self.request.POST.get("h-captcha-response"):
            messages.warning(self.request, _("Please enter captcha!"))
            return redirect("activate", uidb64 = self.kwargs.get("uidb64"), token = self.kwargs.get("token"))
        payload = { 'secret': settings.HCAPTCHA_SECRET, 'response': self.request.POST["h-captcha-response"] }
        r = requests.post("https://hcaptcha.com/siteverify", data=payload)
        result = json.loads(r.text)
        if not result['success']:
            messages.error(self.request, _("Incorrect Captcha"))
            return redirect("activate", uidb64 = self.kwargs.get("uidb64"), token = self.kwargs.get("token"))

        if user.is_2fa:
            if account_activation_token.check_token(user, self.kwargs.get("token")):
                if form.is_valid():
                    code = form.cleaned_data["code"]
                    totp = TOTP(user.secret_key)
                    if totp.verify(code) and user.customer.is_active:
                        if account_activation_token.check_token(user, self.kwargs.get("token")):
                            login(self.request, user)
                            user.magic_link_secret_key = random_base32()
                            user.save()
                            return redirect("/")
                        else:
                            return redirect("login")
                    else:
                        return HttpResponse(status=401)
                else:
                    messages.error(self.request, _("Incorrect code!"))
            else:
                messages.error(self.request, _("Link is invalid!"))
            return redirect("activate", uidb64 = self.kwargs.get("uidb64"), token = self.kwargs.get("token"))
        elif result['success']:
            if account_activation_token.check_token(user, self.kwargs.get("token")) and user.customer.is_active:
                login(self.request, user)
                user.magic_link_secret_key = random_base32()
                user.save()
                return redirect("/")
            else:
                return redirect("login")
        else:
            messages.error(self.request, str(result))
            return redirect("activate", uidb64 = self.kwargs.get("uidb64"), token = self.kwargs.get("token"))

Kodumuzun tamamı ise şu şekilde oluyor haliyle

from django.conf import settings
from django.contrib import messages
from django.contrib.auth import login, logout
from django.contrib.sites.shortcuts import get_current_site
from django.core.mail import EmailMessage
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import redirect, render, resolve_url
from django.template.loader import render_to_string
from django.utils.encoding import force_bytes, force_text
from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode
from django.utils.translation import gettext_lazy as _
from django.views.generic import FormView, View

from pyotp import TOTP, random_base32
from .utils.token import account_activation_token

class IsLogin(FormView):
    http_method_names = ["get", "post"]
    template_name = "account/login.html"
    email_template_name = "account/mails/login_email.html"
    form_class = UserForm
    success_url = settings.LOGIN_REDIRECT_URL

    def get(self, request, *args, **kwargs):
        if self.request.user.is_authenticated:
            return HttpResponseRedirect(resolve_url(self.success_url))
        return super().get(request, *args, **kwargs)

    def form_valid(self, form):
        try:
            user = Users.objects.get(email=form.cleaned_data["email"], customer__is_active=True)
        except Users.DoesNotExist:
            messages.success(self.request, _("If an account matches the username %s, you should receive an email with magic link." % form.cleaned_data["email"]))
        else:
            current_site = get_current_site(self.request)
            mail_subject = _("Login your account.")
            mail_message = render_to_string(
                self.email_template_name,
                {
                    "user": user,
                    "domain": current_site.domain,
                    "uid": urlsafe_base64_encode(force_bytes(user.pk)),
                    "token": account_activation_token.make_token(user),
                },
            )
            email = EmailMessage(from_email='noreply@mertcangokgoz.com', to=[user.email], subject=mail_subject, body=mail_message)
            email.content_subtype = "html"
            email.send()
            messages.success(self.request, _("If an account matches the username %s, you should receive an email with magic link." % form.cleaned_data["email"]))
        return render(self.request, self.template_name, {"form":self.get_form()})

    def form_invalid(self, form):
        return render(
            self.request, self.template_name, {'form':self.get_form()}
        )

class OTPView(View):
    template_name = "account/otp_login.html"

    def get(self, *args, **kwargs):
        try:
            uid = force_text(urlsafe_base64_decode(self.kwargs.get("uidb64")))
            user = Users.objects.get(pk=uid)
        except:
            messages.error(self.request, _("Link is invalid!"))
            return redirect("/")

        form = OtpCodeForm()
        otp = False

        if not account_activation_token.check_token(user, self.kwargs.get("token")):
            messages.error(self.request, _("Link is invalid!"))
            return redirect("login")

        if not user.otp_active and settings.OTP_IS_ACTIVE and user.is_2fa:
            if account_activation_token.check_token(user, self.kwargs.get("token")):
                return redirect("otp_activation", uidb64 = self.kwargs.get("uidb64"), token = self.kwargs.get("token"))
            else:
                return HttpResponse(_("Link is invalid!"))

        if user.is_2fa:
            if account_activation_token.check_token(user, self.kwargs.get("token")):
                otp = True

        return render(
            self.request, self.template_name, {"form": form, "hcaptcha_sitekey":settings.HCAPTCHA_SITEKEY, "otp":otp}
        )


    def post(self, *args, **kwargs):
        try:
            uid = force_text(urlsafe_base64_decode(self.kwargs.get("uidb64")))
            user = Users.objects.get(pk=uid)
        except:
            messages.error(self.request, _("Link is invalid!"))
            return redirect("/")
        form = OtpCodeForm(data=self.request.POST)
        if not self.request.POST.get("h-captcha-response"):
            messages.warning(self.request, _("Please enter captcha!"))
            return redirect("activate", uidb64 = self.kwargs.get("uidb64"), token = self.kwargs.get("token"))
        payload = { 'secret': settings.HCAPTCHA_SECRET, 'response': self.request.POST["h-captcha-response"] }
        r = requests.post("https://hcaptcha.com/siteverify", data=payload)
        result = json.loads(r.text)
        if not result['success']:
            messages.error(self.request, _("Incorrect Captcha"))
            return redirect("activate", uidb64 = self.kwargs.get("uidb64"), token = self.kwargs.get("token"))

        if user.is_2fa:
            if account_activation_token.check_token(user, self.kwargs.get("token")):
                if form.is_valid():
                    code = form.cleaned_data["code"]
                    totp = TOTP(user.secret_key)
                    if totp.verify(code) and user.customer.is_active:
                        if account_activation_token.check_token(user, self.kwargs.get("token")):
                            login(self.request, user)
                            user.magic_link_secret_key = random_base32()
                            user.save()
                            return redirect("/")
                        else:
                            return redirect("login")
                    else:
                        return HttpResponse(status=401)
                else:
                    messages.error(self.request, _("Incorrect code!"))
            else:
                messages.error(self.request, _("Link is invalid!"))
            return redirect("activate", uidb64 = self.kwargs.get("uidb64"), token = self.kwargs.get("token"))
        elif result['success']:
            if account_activation_token.check_token(user, self.kwargs.get("token")) and user.customer.is_active:
                login(self.request, user)
                user.magic_link_secret_key = random_base32()
                user.save()
                return redirect("/")
            else:
                return redirect("login")
        else:
            messages.error(self.request, str(result))
            return redirect("activate", uidb64 = self.kwargs.get("uidb64"), token = self.kwargs.get("token"))

Django Dil Çerezleri İçin Arakatman

Projeleri geliştirirken çoklu dil için çalışma yapıyor olabilirsiniz globalleşen dünyada tek dil tek millet gibi kavramlar yok, bunun yerine çoklu dil ve herkese hizmet etmek var. Bu bağlamda kişinin dil ayarlarını tarayıcısına kayıt etmek için aşağıdaki yolu kullanabilirsiniz.

  • 10 yıl geçerli olacak şekilde kayıt edilir.
  • Session’a ayrıca eklenir.
import datetime

from django.utils.translation import LANGUAGE_SESSION_KEY, get_language
from django.conf import settings


class LanguageCookieMiddleware:
    def __call__(self, request, response):
        language = get_language()
        if hasattr(request, 'session'):
            session_language = request.session.get(LANGUAGE_SESSION_KEY, None)
            if session_language and not session_language == language:
                request.session[LANGUAGE_SESSION_KEY] = language
                request.session.save()
        if settings.LANGUAGE_COOKIE_NAME in request.COOKIES and \
                        request.COOKIES[settings.LANGUAGE_COOKIE_NAME] == language:
            return response
        max_age = 365 * 24 * 60 * 60  # 10 yıl
        expires = datetime.datetime.utcnow() + datetime.timedelta(seconds=max_age)
        response.set_cookie(settings.LANGUAGE_COOKIE_NAME, language, expires=expires)
        return response

Django’da Ip Adresinden Timezone Ataması Yapmak

Django üzerinde kullanıcıların IP adreslerine göre zaman dilimlerini değiştirmek kullanıcının bölgesine göre doğru düzgün zamanları göstermek isteyenler aşağıdaki kod parçasını kullanabilirler.

import ipaddress
from django.contrib.gis.geoip2 import GeoIP2
from django.utils.deprecation import MiddlewareMixin

def get_client_ip(request):
    x_forwarded_for = request.META.get("HTTP_X_FORWARDED_FOR")
    if x_forwarded_for:
        ip = x_forwarded_for.split(",")[0]
    elif len(request.META.get("REMOTE_ADDR")) > 6:
        ip = request.META.get("REMOTE_ADDR")
    elif len(request.META.get("CF-Connecting-IP")) > 6:
        ip = request.META.get("CF-Connecting-IP")
    return ip

def is_valid_ip(ip_address):
    try:
        ip = ipaddress.ip_address(ip_address)
        return True
    except ValueError as e:
        return False

def is_local_ip(ip_address):
    try:
        ip = ipaddress.ip_address(ip_address)
        return ip.is_loopback
    except ValueError as e:
        return None

class IPtoTimezoneMiddleware(MiddlewareMixin):
    def process_request(self, request):
        tz = request.session.get('django_timezone')
        if not tz:
            tz = timezone.get_default_timezone()
            client_ip = get_client_ip(request)
            ip_addrs = client_ip.split(',')
            for ip in ip_addrs:
                if is_valid_ip(ip) and not is_local_ip(ip):
                    if ip:
                        tz = GeoIP2().city(str(ip))['time_zone']
                        break
        if tz:
            timezone.activate(tz)
            Users.objects.filter(id=request.user.id).update(timezone=str(tz))
            request.session['django_timezone'] = str(tz)
        else:
            timezone.deactivate()

Amazon S3 + Django Versiyonlu Statik Dosya Barındırma

Django üzerinde tutulan statik dosyaları versiyonlu bir şekilde tutmak ve Amazon S3 üzerinde barındırmak isteyen arkadaşlarımız bu kodu kullanabilirler. Normalde Django versiyonlanmış Asset desteklemekte ancak direk S3 desteği bulunmamaktadır, bu iş için böyle bir kod işinizi çokça görecektir.

import hashlib
import threading

from django import template
from django.conf import settings
from django.contrib.staticfiles.storage import staticfiles_storage

class UrlCache(object):
    _md5_sum = {}
    _lock = threading.Lock()

    @classmethod
    def get_md5(cls, file):
        try:
            return cls._md5_sum[file]
        except KeyError:
            with cls._lock:
                try:
                    md5 = cls.calc_md5(file)[:8]
                    value = '%s%s?v=%s' % (settings.STATIC_URL, file, md5)
                except OSError:
                    value = settings.STATIC_URL + file
                cls._md5_sum[file] = value
                return value

    @classmethod
    def calc_md5(cls, file_path):
        with staticfiles_storage.open(file_path, 'rb') as fh:
            m = hashlib.md5()
            while True:
                data = fh.read(8192)
                if not data:
                    break
                m.update(data)
            return m.hexdigest()


@register.simple_tag
def md5url(value):
    return UrlCache.get_md5(value)

Kullanabilmek amacıyla STATIC_ROOT tanımlaması yapmayı unutmayınız.

Django’da Amazon S3 Üzerinde Tutulan Private Dosyaların Sunulması

Herkesten sakladığınız ve sadece erişim isteği isteyen kullanıcıların dosyalara erişmesini sağlamak istiyorsanız ve bu isteğinizi Amazon üzerinde bulunan S3 bucketınızda yapacaksanız derdinizin çözümü burada,

  • AWS S3 de tutulan dosyalar private olarak geçmelidir.
  • Amazon S3 API anahtarınızda s3:GetObject yetkisi mutlaka bulunmalıdır.
  • django-storages Kullanılıyorsa ve dosyalar onun üzerinden sisteme yükleniyorsa, imza hatası alınmaması için mutlaka AWS_S3_SIGNATURE_VERSION = 's3v4' ve AWS_S3_ADDRESSING_STYLE = 'path' parametreleri settings.py dosyasına eklenmelidir.
import boto3
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import View
from django.http import HttpResponseRedirect

class AwsS3UrlGenerator(LoginRequiredMixin, View):
    def get(self, *args, **kwargs):
        s3_client = boto3.client(
            "s3",
            aws_access_key_id="",
            aws_secret_access_key="",
            region_name="eu-west-1",
            config=Config(
                s3={"addressing_style": "path"}, signature_version="s3v4"
            ),
        )
        try:
            presigned_url = s3_client.generate_presigned_url(
                "get_object",
                Params={
                    "Bucket": "bucket-name",
                    "Key": str(self.request.GET["p"]),
                },
                ExpiresIn=300,
                HttpMethod="GET",
            )
        except ClientError as e:
            return None

        return HttpResponseRedirect(presigned_url)

Django’da Uzak Sunucuda Barınan Görselin Rapora Eklenmesi

Özellikle PDF rapor oluşturma noktasında, HTML’den dönüştürüyorsanız ve görseller amazon s3 gibi uzak sunucularda yer alıyorsa, rapor içerisine gömmek bazen çileye dönebilir, bu noktada şöyle bir kullanım ile rapor içerisine görselleri basitçe ekleyebilirsiniz.

@register.filter
def read_image_as_base64(image_url):
    """
    Usage: <img src="{{ user.user_avatar.url|read_image_as_base64 }}">
    """
    if not image_url:
        return image_url

    try:
        response = requests.get(image_url, headers={"user-agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0"})
        if response.status_code == 200:
            image_data = response.content
            image_format = os.path.splitext(image_url)[-1].replace('.', '').lower()
            encoded_string = base64.b64encode(image_data).decode('utf-8')

            if image_format in ['jpg', 'jpeg', 'png', 'gif']:
                return 'data:image/%s;base64,%s' % (image_format, encoded_string)

    except Exception as e:
        logging.error('ERROR: %s' % e)
        pass

    return image_url

Windows’da Django Locale Yapılandırma

Django uygulamaları geliştiriyor ve çok dilli bir yapıyı da beraberinde kullanıyorsanız, geliştirme ortamınızda Windows ise bir takım hatalar ile karşılaşabilirsiniz. Özellikle gettext ile dil dosyalarının oluşmaması gibi büyük bir problem bulunuyor.

Hata şu şekilde

CommandError: Can't find xgettext. Make sure you have GNU gettext tools 0.15 or newer installed.

Bu sorunun çözmek için gettextin windows sürümünü sisteme dahil edin. Ardından hiç bir şey olmamış gibi dil dosyası oluşacak

python manage.py makemessages -l tr