জাঙ্গো ক্লাস-ভিত্তিক দর্শনগুলিতে অনুমতি_ প্রয়োজনীয় সজ্জিতগুলি কীভাবে ব্যবহার করবেন


161

নতুন সিবিভিগুলি কীভাবে কাজ করে তা বুঝতে আমার কিছুটা সমস্যা হচ্ছে। আমার প্রশ্নটি হ'ল, আমার সমস্ত দর্শন এবং তার মধ্যে কয়েকটিতে সুনির্দিষ্ট অনুমতিতে লগইন হওয়া দরকার। ফাংশন-ভিত্তিক ভিউগুলিতে আমি এটি @ পারমিশন_প্রযুক্তি () এবং ভিউ-এ লগইন_প্রযুক্তিযুক্ত বৈশিষ্ট্য দিয়ে করি তবে নতুন ভিউগুলিতে এটি কীভাবে করা যায় তা আমি জানি না। জ্যাঙ্গো ডক্সে এর কোন ব্যাখ্যা রয়েছে? আমি কিছুই পাইনি। আমার কোডে কী ভুল?

আমি @ স্মার্ট_ডেকোরেটরটি ব্যবহার করার চেষ্টা করেছি তবে এটির জবাব দেয় " টাইপ এয়ারার এট / স্পেসস / প্রয়েবা / _ র্যাপড ভিউ () কমপক্ষে 1 টি আর্গুমেন্ট নেয় (0 দেওয়া) "

এখানে কোড (জিপিএল) দেওয়া হল:

from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required, permission_required

class ViewSpaceIndex(DetailView):

    """
    Show the index page of a space. Get various extra contexts to get the
    information for that space.

    The get_object method searches in the user 'spaces' field if the current
    space is allowed, if not, he is redirected to a 'nor allowed' page. 
    """
    context_object_name = 'get_place'
    template_name = 'spaces/space_index.html'

    @method_decorator(login_required)
    def get_object(self):
        space_name = self.kwargs['space_name']

        for i in self.request.user.profile.spaces.all():
            if i.url == space_name:
                return get_object_or_404(Space, url = space_name)

        self.template_name = 'not_allowed.html'
        return get_object_or_404(Space, url = space_name)

    # Get extra context data
    def get_context_data(self, **kwargs):
        context = super(ViewSpaceIndex, self).get_context_data(**kwargs)
        place = get_object_or_404(Space, url=self.kwargs['space_name'])
        context['entities'] = Entity.objects.filter(space=place.id)
        context['documents'] = Document.objects.filter(space=place.id)
        context['proposals'] = Proposal.objects.filter(space=place.id).order_by('-pub_date')
        context['publication'] = Post.objects.filter(post_space=place.id).order_by('-post_pubdate')
        return context

উত্তর:


211

সিবিভি ডক্সে কয়েকটি কৌশল তালিকাভুক্ত রয়েছে :

urls.pyআপনি যখন নিজের দৃষ্টিভঙ্গিটি ( দস্তাবেজগুলি ) ইনস্ট্যান্ট করবেন তখন প্রতি-উদাহরণ ভিত্তিতে দর্শনটি সাজান

urlpatterns = [
    path('view/',login_required(ViewSpaceIndex.as_view(..)),
    ...
]

সাজসজ্জাটি প্রতি-প্রতি ভিত্তিতে প্রয়োগ করা হয়, যাতে আপনি এটি যুক্ত করতে পারেন বা urls.pyপ্রয়োজন হিসাবে এটি বিভিন্ন রুটে মুছে ফেলতে পারেন ।

আপনার শ্রেণিটি সাজান যাতে আপনার দৃষ্টির প্রতিটি উদাহরণ সাজসজ্জার দ্বারা আবৃত হবে ( ডক্স )

এটি করার জন্য দুটি উপায় রয়েছে:

  1. method_decoratorআপনার সিবিভি প্রেরণ পদ্ধতিতে একটি প্রয়োগ করা যেমন,

    from django.utils.decorators import method_decorator
    
    @method_decorator(login_required, name='dispatch')
    class ViewSpaceIndex(TemplateView):
        template_name = 'secret.html'

আপনি যদি জ্যাঙ্গো <1.9 ব্যবহার করছেন (যা আপনার উচিত নয়, এটি আর সমর্থিত নয়) আপনি method_decoratorক্লাসে ব্যবহার করতে পারবেন না , সুতরাং আপনাকে dispatchপদ্ধতিটি ওভাররাইড করতে হবে :

    class ViewSpaceIndex(TemplateView):

        @method_decorator(login_required)
        def dispatch(self, *args, **kwargs):
            return super(ViewSpaceIndex, self).dispatch(*args, **kwargs)
  1. আধুনিক জ্যাঙ্গো (২.২+) এ একটি সাধারণ অনুশীলন হ'ল জাজানো কন্ট্রিবি.আউথ.মিক্সিনস। লোগিনের প্রয়োজনযুক্ত মিক্সিন যেমন জাঙ্গো ১.৯+ এ উপলব্ধ এবং অন্য উত্তরগুলিতে এখানে ভালভাবে বর্ণনা করা হয়েছে:

    from django.contrib.auth.mixins import LoginRequiredMixin
    
    class MyView(LoginRequiredMixin, View):
    
        login_url = '/login/'
        redirect_field_name = 'redirect_to'

আপনি উত্তরাধিকার তালিকায় মিক্সিনকে প্রথমে রেখেছেন তা নিশ্চিত করুন (সুতরাং পদ্ধতি সমাধানের আদেশটি সঠিক বিষয়টিকে বেছে নিয়েছে)।

আপনি যে কারণে পাচ্ছেন তার কারণ TypeErrorডক্সে ব্যাখ্যা করা হয়েছে:

দ্রষ্টব্য: মেথড_ডেকোরেটর ক্লাসে সজ্জিত পদ্ধতির পরামিতি হিসাবে * আরগস এবং ** কাওয়ার্গগুলি পাস করে। যদি আপনার পদ্ধতিটি প্যারামিটারগুলির একটি সামঞ্জস্যপূর্ণ সেট গ্রহণ না করে তবে এটি টাইপরর ব্যতিক্রম বাড়িয়ে তুলবে।


3
সর্বশেষ ডক্সে এখানে উল্লেখ করেছে docs.djangoproject.com/en/dev/topics/class-based-views/intro
Bharathwaaj

messageএটা কিভাবে যুক্ত করা যায়?
andilabs

যারা বুঝতে পারেন নি তাদের জন্য (যেমন আমি প্রথমে করেছি) - 'প্রেরণ' পদ্ধতিটি ভিউস্পেসআইডেক্স শ্রেণিতে যুক্ত করা উচিত
o_c

এই পদ্ধতির মধ্যে অন্যটির তুলনায় কোনও কারণকে সমর্থন করার কোনও কারণ আছে কি?
অ্যালিস্টায়ার

@ অ্যালিস্টায়ার আমি মনে করি এটি আপনার দল / সংস্থার মধ্যে ব্যক্তিগত পছন্দ এবং কোডবেস ধারাবাহিকতা বজায় রাখার জন্য উত্সাহিত হয়। যদিও আমি শ্রেণিভিত্তিক দৃষ্টিভঙ্গি তৈরি করছি তবে আমি ব্যক্তিগতভাবে মেশিন পদ্ধতির দিকে ঝোঁক।
এ লি

118

এখানে আমার দৃষ্টিভঙ্গিটি রয়েছে, আমি সুরক্ষিত একটি মিক্সিন তৈরি করি (এটি আমার মিক্সিন লাইব্রেরিতে রাখা হয়):

from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator

class LoginRequiredMixin(object):
    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)

যখনই আপনি কোনও দৃশ্য সুরক্ষিত রাখতে চান আপনি কেবল উপযুক্ত মিক্সিন যুক্ত করুন:

class SomeProtectedViewView(LoginRequiredMixin, TemplateView):
    template_name = 'index.html'

আপনার মিক্সিনটি প্রথমে রয়েছে তা নিশ্চিত করুন।

আপডেট: আমি এটিকে ২০১১ সালে ফিরে পোস্ট করেছি, সংস্করণ ১.৯ দিয়ে শুরু করে জ্যাঙ্গোতে এখন এই এবং অন্যান্য দরকারী মিশ্রণগুলি (অ্যাক্সেসমিক্সিন, PermissionRequiredMixin, ইউজারপ্যাসেসটেষ্টমিক্সিন) স্ট্যান্ডার্ড হিসাবে অন্তর্ভুক্ত রয়েছে!


এই জাতীয় মিশ্রণের একাধিক পাওয়া কি সম্ভব? এটি আমার পক্ষে কার্যকর হয়নি এবং আমি মনে করি না যে এটির অর্থ হবে এটি sense
পাইকলার

হ্যাঁ এটি প্রতিটি মিশ্রণ সুপারকে একটি কল দেয় যা এমআরও অনুসারে পরবর্তী ক্লাসটি বেছে নেয়
একাধিক

আমি মনে করি এটি একটি মার্জিত সমাধান; আমি আমার ইউআরএল.পি.এতে সজ্জকারের মিশ্রণ এবং ভিউ.পাইতে মিশ্রণ পছন্দ করি না। এটি সাজানোর মোড়কের এমন একটি উপায় যা সেই যুক্তিগুলির সমস্ত দৃশ্যে নিয়ে যায়।
haাকনার


আমার মতো পুরো রিয়ার্ড মোডে থাকা লোকদের জন্য কেবল একটি নোট: লগইন_প্রয়োজনীয় কার্যকারিতা পরীক্ষা করার সময় আপনি লগইন না করে তা নিশ্চিত করুন ...
ভিজিয়ান স্কেলোরু

46

শ্রেণিভিত্তিক সাজসজ্জার ব্যবহার করে এখানে একটি বিকল্প রয়েছে:

from django.utils.decorators import method_decorator

def class_view_decorator(function_decorator):
    """Convert a function based decorator into a class based decorator usable
    on class based Views.

    Can't subclass the `View` as it breaks inheritance (super in particular),
    so we monkey-patch instead.
    """

    def simple_decorator(View):
        View.dispatch = method_decorator(function_decorator)(View.dispatch)
        return View

    return simple_decorator

এরপরে এটি সহজভাবে ব্যবহার করা যেতে পারে:

@class_view_decorator(login_required)
class MyView(View):
    # this view now decorated

3
আপনি এটিকে সুন্দরভাবে সাজানোর জন্য চেইন ভিউতে ব্যবহার করতে পারেন! +1
পাইকলার

9
এটি এত দুর্দান্ত যে এটি প্রবাহের আইএমও অন্তর্ভুক্তির জন্য বিবেচনা করা উচিত।
কোনিয়িক

আমি এটা ভালোবাসি! আমি ভাবছি কি ক্লাস_ভিউ_ডেকোরেটর থেকে ফাংশন_দেকরেটর থেকে অর্গ / কাওয়ার্গগুলি পাস করা আদৌ সম্ভব? এটি দুর্দান্ত হবে যদি লগইন_দেকার শর্তসাপেক্ষে অনুরোধটির সাথে মিল রাখতে পারে E এমএইচডিএড তাই এটি কেবল পোস্ট পোস্টের জন্য প্রয়োগ হয়?
মাইক ওয়েটস

1
আরগস / কাওয়ার্গগুলি ব্যবহার করে সহজেই অর্জনযোগ্য হওয়া উচিত class_view_decorator(my_decorator(*args, **kwargs))। শর্তসাপেক্ষ পদ্ধতিটি মিলে যাওয়ার ক্ষেত্রে - আপনি নিজের পরিবর্তে View.getবা View.postপরিবর্তে ক্লাস_ভিউ_ডেকোরেটরটি সংশোধন করতে পারেন View.dispatch
mjtamlyn

14

আমি বুঝতে পারি এই থ্রেডটি কিছুটা তারিখযুক্ত, তবে যাইহোক এখানে আমার দুটি সেন্ট।

নিম্নলিখিত কোড সহ:

from django.utils.decorators import method_decorator
from inspect import isfunction

class _cbv_decorate(object):
    def __init__(self, dec):
        self.dec = method_decorator(dec)

    def __call__(self, obj):
        obj.dispatch = self.dec(obj.dispatch)
        return obj

def patch_view_decorator(dec):
    def _conditional(view):
        if isfunction(view):
            return dec(view)

        return _cbv_decorate(dec)(view)

    return _conditional

আমাদের কাছে এখন ডেকরেটরকে প্যাচ করার একটি উপায় রয়েছে, সুতরাং এটি বহুগুণে পরিণত হবে। এর কার্যকরভাবে অর্থ হ'ল নিয়মিত দৃশ্যের ডেকোরিটারে যখন প্রয়োগ করা হয়, তেমন:

login_required = patch_view_decorator(login_required)

এই সাজসজ্জাটি এখনও এটির কাজ করবে যখন এটির উদ্দেশ্য ছিল:

@login_required
def foo(request):
    return HttpResponse('bar')

তবে এটির মতো ব্যবহারের সময় সঠিকভাবে কাজ করবে:

@login_required
class FooView(DetailView):
    model = Foo

এই বাস্তব-দুনিয়ার উদাহরণ সহ আমি বেশ কয়েকটি ক্ষেত্রে সাম্প্রতিক সময়ে এসেছিলে এটি কাজ করে বলে মনে হচ্ছে:

@patch_view_decorator
def ajax_view(view):
    def _inner(request, *args, **kwargs):
        if request.is_ajax():
            return view(request, *args, **kwargs)
        else:
            raise Http404

    return _inner

অজ্যাক্স_ভিউ ফাংশনটি একটি (ফাংশন ভিত্তিক) ভিউ সংশোধন করার জন্য রচনা করা হয়েছে, যাতে যখনই এই ভিউটি অজেক্স কল দ্বারা পরিদর্শন করা হয় এটি 404 ত্রুটি উত্থাপন করে। সজ্জা হিসাবে প্যাচ ফাংশনটি কেবল প্রয়োগ করে, এই ডেকরেটরটি বর্গ ভিত্তিক দেখুনগুলিতেও কাজ করতে প্রস্তুত


14

আপনাদের মধ্যে যারা ব্যবহার জন্য জ্যাঙ্গো> = 1.9 , এটি আগে থেকেই মধ্যে অন্তর্ভুক্ত django.contrib.auth.mixinsহিসাবে AccessMixin, LoginRequiredMixin, PermissionRequiredMixinএবং UserPassesTestMixin

সুতরাং সিবিভিতে লগইনআর প্রয়োজন (যেমন DetailView):

from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.detail import DetailView


class ViewSpaceIndex(LoginRequiredMixin, DetailView):
    model = Space
    template_name = 'spaces/space_index.html'
    login_url = '/login/'
    redirect_field_name = 'redirect_to'

জিসিবিভি মিক্সিন অর্ডারটি মাথায় রাখাও ভাল: মিক্সিনগুলি অবশ্যই বাম দিকে যেতে হবে এবং বেস ভিউ ক্লাসটি অবশ্যই ডানদিকে যেতে হবে । অর্ডার পৃথক হলে আপনি ভাঙ্গা এবং অনির্দেশ্য ফলাফল পেতে পারেন।


2
এটি 2019 সালের সেরা উত্তর Also এছাড়াও, মিক্সিন অর্ডার সম্পর্কে দুর্দান্ত পয়েন্ট।
ক্রিশ্চিয়ান লং

5

জ্যাঙ্গো ধনুর্বন্ধনী ব্যবহার করুন। এটি সহজেই উপলভ্য প্রচুর দরকারী মিক্সিন সরবরাহ করে। এটিতে সুন্দর ডক্স রয়েছে। চেষ্টা কর.

এমনকি আপনার কাস্টম মিশ্রণগুলি তৈরি করতে পারেন।

http://django-braces.readthedocs.org/en/v1.4.0/

উদাহরণ কোড:

from django.views.generic import TemplateView

from braces.views import LoginRequiredMixin


class SomeSecretView(LoginRequiredMixin, TemplateView):
    template_name = "path/to/template.html"

    #optional
    login_url = "/signup/"
    redirect_field_name = "hollaback"
    raise_exception = True

    def get(self, request):
        return self.render_to_response({})

4

যদি এটি এমন কোনও সাইট হয় যেখানে বেশিরভাগ পৃষ্ঠাগুলির ব্যবহারকারীর লগ ইন করার প্রয়োজন হয় তবে আপনি বিশেষত চিহ্নিত হওয়া ব্যতীত সকল দর্শনে লগইন করার জন্য মিডলওয়্যার ব্যবহার করতে পারেন ।

প্রাক জাজানো 1.10 মিডলওয়্যার.পি:

from django.contrib.auth.decorators import login_required
from django.conf import settings

EXEMPT_URL_PREFIXES = getattr(settings, 'LOGIN_EXEMPT_URL_PREFIXES', ())

class LoginRequiredMiddleware(object):
    def process_view(self, request, view_func, view_args, view_kwargs):
        path = request.path
        for exempt_url_prefix in EXEMPT_URL_PREFIXES:
            if path.startswith(exempt_url_prefix):
                return None
        is_login_required = getattr(view_func, 'login_required', True)
        if not is_login_required:
            return None
        return login_required(view_func)(request, *view_args, **view_kwargs) 

views.py:

def public(request, *args, **kwargs):
    ...
public.login_required = False

class PublicView(View):
    ...
public_view = PublicView.as_view()
public_view.login_required = False

আপনি মোড়তে চান না এমন তৃতীয় পক্ষের দর্শনগুলি সেটিংসে ছাড় দেওয়া যেতে পারে:

settings.py:

LOGIN_EXEMPT_URL_PREFIXES = ('/login/', '/reset_password/')

3

আমার কোডে আমি এই অ্যাডাপ্টারটি সদস্যবিহীন ফাংশনটিকে একটি সদস্যবিহীন ফাংশনে অভিযোজিত করতে লিখেছি:

from functools import wraps


def method_decorator_adaptor(adapt_to, *decorator_args, **decorator_kwargs):
    def decorator_outer(func):
        @wraps(func)
        def decorator(self, *args, **kwargs):
            @adapt_to(*decorator_args, **decorator_kwargs)
            def adaptor(*args, **kwargs):
                return func(self, *args, **kwargs)
            return adaptor(*args, **kwargs)
        return decorator
    return decorator_outer

আপনি এটি সহজভাবে এটি ব্যবহার করতে পারেন:

from django.http import HttpResponse
from django.views.generic import View
from django.contrib.auth.decorators import permission_required
from some.where import method_decorator_adaptor


class MyView(View):
    @method_decorator_adaptor(permission_required, 'someapp.somepermission')
    def get(self, request):
        # <view logic>
        return HttpResponse('result')

এটি চমৎকার হবে যে এটি জঙ্গোতে অন্তর্নির্মিত ছিল (ঠিক ঠিক method_decoratorতেমন)। এটি অর্জনের এটি একটি দুর্দান্ত এবং পঠনযোগ্য উপায় বলে মনে হচ্ছে।
মারিউসুইরাম

1

এই জ্যাঙ্গো সঙ্গে সুপার সহজ> আছে 1.9 জন্য সমর্থন নিয়ে আসছে PermissionRequiredMixinএবংLoginRequiredMixin

কেবল লেখক থেকে আমদানি করুন

views.py

from django.contrib.auth.mixins import LoginRequiredMixin

class YourListView(LoginRequiredMixin, Views):
    pass

আরও তথ্যের জন্য জাঙ্গোতে অনুমোদন পড়ুন


1

এখন অনেকটা সময় হয়ে গেছে এবং এখন জ্যাঙ্গো এতটা বদলেছে।

শ্রেণিবদ্ধ ভিউটি কীভাবে সাজাতে হয় তা এখানে দেখুন।

https://docs.djangoproject.com/en/2.2/topics/class-based-views/intro/#decorating-the-class

ডকুমেন্টেশনে "সাজসজ্জার যে কোনও যুক্তি গ্রহণ করে" এর উদাহরণ অন্তর্ভুক্ত করা হয়নি। তবে সাজসজ্জা যারা যুক্তি গ্রহণ করে তারা এর মতো:

def mydec(arg1):
    def decorator(func):
         def decorated(*args, **kwargs):
             return func(*args, **kwargs) + arg1
         return decorated
    return deocrator

সুতরাং আমরা যদি যুক্তি ছাড়াই মাইডেককে একটি "সাধারণ" ডেকরেটার হিসাবে ব্যবহার করি, আমরা এটি করতে পারি:

mydecorator = mydec(10)

@mydecorator
def myfunc():
    return 5

একইভাবে, সাথে ব্যবহার permission_requiredকরতেmethod_decorator

আমরা করতে পারি:

@method_decorator(permission_required("polls.can_vote"), name="dispatch")
class MyView:
    def get(self, request):
        # ...

0

আপনি যদি এমন একটি প্রকল্প করছেন যার জন্য বিভিন্ন অনুমতি পরীক্ষার প্রয়োজন হয় তবে আপনি এই শ্রেণীর উত্তরাধিকারী হতে পারেন।

from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import user_passes_test
from django.views.generic import View
from django.utils.decorators import method_decorator



class UserPassesTest(View):

    '''
    Abstract base class for all views which require permission check.
    '''


    requires_login = True
    requires_superuser = False
    login_url = '/login/'

    permission_checker = None
    # Pass your custom decorator to the 'permission_checker'
    # If you have a custom permission test


    @method_decorator(self.get_permission())
    def dispatch(self, *args, **kwargs):
        return super(UserPassesTest, self).dispatch(*args, **kwargs)


    def get_permission(self):

        '''
        Returns the decorator for permission check
        '''

        if self.permission_checker:
            return self.permission_checker

        if requires_superuser and not self.requires_login:
            raise RuntimeError((
                'You have assigned requires_login as False'
                'and requires_superuser as True.'
                "  Don't do that!"
            ))

        elif requires_login and not requires_superuser:
            return login_required(login_url=self.login_url)

        elif requires_superuser:
            return user_passes_test(lambda u:u.is_superuser,
                                    login_url=self.login_url)

        else:
            return user_passes_test(lambda u:True)

0

আমি জোশের সমাধানের ভিত্তিতে এটি ঠিক করেছি

class LoginRequiredMixin(object):

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super(LoginRequiredMixin, self).dispatch(*args, **kwargs)

নমুনা ব্যবহার:

class EventsListView(LoginRequiredMixin, ListView):

    template_name = "events/list_events.html"
    model = Event

0

অনুমতি_ প্রয়োজনীয় সাজসজ্জার জন্য সমাধান এখানে:

class CustomerDetailView(generics.GenericAPIView):

@method_decorator(permission_required('app_name.permission_codename', raise_exception=True))
    def post(self, request):
        # code...
        return True
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.