57

models.pyrequest.userのメソッドで現在ログインしているユーザー()を取得したい。saveユーザーの役割を確認し、ユーザーの役割に基づいていくつかの操作を実行できるかどうかを確認したいと思います。

models.py

class TimeSheet(models.Model):
    check_in_time = models.TimeField()
    check_out_time = models.TimeField()

class Tasks(models.Model):
    time_sheet = models.ForeignKey(TimeSheet)
    project = models.ForeignKey(Project)
    start_time = models.TimeField()
    end_time = models.TimeField()

    def save(self, *args,**kwargs):
        project = SpentTime.objects.get(project__project__id = self.project.id)
        start = datetime.datetime.strptime(str(self.start_time), '%H:%M:%S')
        end = datetime.datetime.strptime(str(self.end_time), '%H:%M:%S')
        time = float("{0:.2f}".format((end - start).seconds/3600.0))

        if common.isDesigner(request.user):
            SpentTime.objects.filter(project__project__id = self.project.id).update(design = float(project.design) + time)

        if common.isDeveloper(request.user):
            SpentTime.objects.filter(project__project__id = self.project.id).update(develop = float(project.develop) + time)

        super(Tasks, self).save(*args, **kwargs)

ここでは、Tasksモデルはモデルのインラインとして使用されていTimesheetます。現在ログインしているユーザーの役割を確認し、ユーザーの役割に基づいて別のモデルを更新したいと思います。ここrequest.userで、現在のユーザーの役割を確認する必要があります。私はフォームやテンプレートを使用しておらず、Djangoadminを完全に利用しています。メソッドを取得したり、admin.pyの別のモデルの値を確認および更新したりする方法はありrequest.userますsaveか?

4

6 に答える 6

41

この問題には別の角度から取り組むことができます。モデルのsaveメソッドを変更する代わりに、AdminSitessave_modelメソッドをオーバーライドする必要があります。そこにリクエストオブジェクトがあり、すでに指摘したようにログインしたユーザーデータにアクセスできます。

ドキュメントのこの章をご覧ください:DjangoModelAdminドキュメントsave_model

于 2012-06-12T09:34:15.457 に答える
26

それを行う方法を見つけましたが、ミドルウェアを宣言する必要があります。get_username.py次のコンテンツを使用して、アプリ内で呼び出されるファイルを作成します。

from threading import current_thread

_requests = {}

def get_username():
    t = current_thread()
    if t not in _requests:
         return None
    return _requests[t]

class RequestMiddleware(object):
    def process_request(self, request):
        _requests[current_thread()] = request

を編集して、 :settings.pyに追加します。MIDDLEWARE_CLASSES

MIDDLEWARE_CLASSES = (
    ...
    'yourapp.get_username.RequestMiddleware',
)

これで、save()メソッドで、次のように現在のユーザー名を取得できます。

from get_username import get_username

...

def save(self, *args, **kwargs):
    req = get_username()
    print "Your username is: %s" % (req.user)
于 2016-03-31T08:53:03.917 に答える
11

@nKnによって提案されたソリューションは良い出発点ですが、今日実装しようとしたときに、2つの問題に直面しました。

  1. 現在のDjangoバージョンでは、プレーンオブジェクトとして作成されたミドルウェアは機能しません。
  2. 単体テストは失敗しています(通常はシングルスレッドで実行されるため、最初のテストにHTTPリクエストがあり、2番目のテストにHTTPリクエストがない場合、2つの結果のテストの間に「リクエスト」がスタックする可能性があります)。

これが私の更新されたミドルウェアコードです。これはDjango1.10で動作し、単体テストを壊しません。

from threading import current_thread

from django.utils.deprecation import MiddlewareMixin


_requests = {}


def current_request():
    return _requests.get(current_thread().ident, None)


class RequestMiddleware(MiddlewareMixin):

    def process_request(self, request):
        _requests[current_thread().ident] = request

    def process_response(self, request, response):
        # when response is ready, request should be flushed
        _requests.pop(current_thread().ident, None)
        return response

    def process_exception(self, request, exception):
        # if an exception has happened, request should be flushed too
         _requests.pop(current_thread().ident, None)
于 2017-02-27T16:43:30.933 に答える
8

正しい方法はthreading.local、で辞書を使用する代わりに、を使用するthreading.current_threadことです。これは、メモリリークが発生するためです。これは、アプリケーションが実行されている間、古い値がそこにとどまるためです。

import threading

request_local = threading.local()

def get_request():
    return getattr(request_local, 'request', None)

class RequestMiddleware():
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        request_local.request = request
        return self.get_response(request)

    def process_exception(self, request, exception):
        request_local.request = None

    def process_template_response(self, request, response):
        request_local.request = None
        return response

リクエストの代わりにユーザーにアクセスしたい場合は、リクエストのget_request().user代わりにユーザーを保存するか、__call__

于 2019-01-07T23:08:01.760 に答える
7

save_modelメソッドのオーバーライドが最良のオプションだとは思いません。たとえば、ユーザー情報を保存したり、ユーザー情報に基づいてモデルを検証したりする場合で、save()がビューまたは管理サイト自体からのものではないとします。

人々が求めているのは、次のような構造です。

def save(..)
    self.user = current_user()

また

def save(..)
    user = current_user()
    if user.group == 'XPTO':
        error('This user cannot edit this record')

私がこれまでに見つけた最善のアプローチは次のとおりです。

https://bitbucket.org/q/django-current-user/overview

于 2012-11-03T01:45:21.047 に答える
4

次のライブラリを使用してみましたか。

https://pypi.org/project/django-currentuser/

ウェブサイトからの使用方法の抜粋:

from django_currentuser.middleware import (get_current_user, get_current_authenticated_user)
# As model field:
from django_currentuser.db.models import CurrentUserField
class Foo(models.Model):
    created_by = CurrentUserField()
于 2019-10-02T15:49:20.400 に答える