2011-01-17 26 views
19

Tôi đã thực hiện tín hiệu post_save bên dưới trong dự án của mình.Truy cập yêu cầu của người dùng trong tín hiệu post_save

from django.db.models.signals import post_save 
from django.contrib.auth.models import User 

# CORE - SIGNALS 
# Core Signals will operate based on post 

def after_save_handler_attr_audit_obj(sender, **kwargs): 
    print User.get_profile() 

    if hasattr(kwargs['instance'], 'audit_obj'): 
     if kwargs['created']: 
      kwargs['instance'].audit_obj.create(operation="INSERT", operation_by=**USER.ID**).save() 
     else: 
      kwargs['instance'].audit_obj.create(operation="UPDATE").save() 


# Connect the handler with the post save signal - Django 1.2 
post_save.connect(after_save_handler_attr_audit_obj, dispatch_uid="core.models.audit.new") 

Cột operation_by, tôi muốn lấy user_id và lưu trữ. Bất kỳ ý tưởng làm thế nào có thể làm điều đó?

Trả lời

12

Không thể hoàn thành. Người dùng hiện tại chỉ có sẵn thông qua yêu cầu, không có sẵn khi sử dụng hoàn toàn chức năng mô hình. Truy cập người dùng trong chế độ xem bằng cách nào đó.

+0

hmm Nó có ý nghĩa, tôi chỉ định dạng lại câu hỏi của tôi để tìm ra một cách để làm công việc sử dụng phương pháp thay thế –

+0

http://stackoverflow.com/questions/4725685/django-auto-filling-some-data-based-on-model-attribute –

+0

Bạn có thể thực hiện khi tải chế độ xem của mình. Trong bài đăng của bạn, hãy lưu trạng thái bạn muốn gắn cờ trong mô hình. Khi tải mô hình trong giao diện, hãy kiểm tra cờ trạng thái và thực hiện những gì bạn sẽ làm với nó trước khi trả lời. Tôi thực hiện trạng thái đăng cuộc gọi api, sau đó đặt trường mô hình có tên là api_status bằng mã trạng thái thích hợp. Tôi kiểm tra mã trong nhận của tôi và sử dụng khung thông điệp để thông báo cho người dùng về trạng thái nhận được từ cuộc gọi. – radtek

5

Ignacio là đúng. Tín hiệu mô hình của Django nhằm mục đích thông báo cho các thành phần hệ thống khác về các sự kiện liên quan đến các cá thể và dữ liệu được kính trọng của chúng, vì vậy tôi đoán rằng dữ liệu yêu cầu truy cập từ tín hiệu post_save là không hợp lệ, trừ khi dữ liệu yêu cầu đó được lưu trữ hoặc liên kết với ví dụ.

Tôi đoán có rất nhiều cách để xử lý, từ xấu đến tốt hơn, nhưng tôi muốn nói đây là ví dụ chính để tạo chế độ xem chung dựa trên lớp/chức năng sẽ tự động xử lý việc này cho bạn.

Có chế độ xem của bạn được kế thừa từ CreateView, UpdateView hoặc DeleteView bổ sung kế thừa từ lớp AuditMixin nếu chúng xử lý các động từ hoạt động trên các mô hình cần được kiểm tra. Các AuditMixin sau đó có thể móc vào các khung nhìn tạo thành công các đối tượng \ update \ delete và tạo một mục trong cơ sở dữ liệu.

Làm cho cảm giác hoàn hảo, rất sạch sẽ, dễ cắm và sinh con ngựa hạnh phúc. Lật mặt? Bạn sẽ phải có bản phát hành Django 1.3 sắp phát hành hoặc bạn sẽ phải dành một chút thời gian để làm nổi bật các khung nhìn chung dựa trên chức năng và cung cấp những cái mới cho mỗi hoạt động kiểm toán.

0

Tôi tưởng tượng bạn sẽ có figured này ra, nhưng tôi đã có cùng một vấn đề và tôi nhận ra rằng tất cả các trường hợp tôi có thể tạo đã có một tài liệu tham khảo cho người sử dụng tạo ra chúng (đó là những gì bạn đang tìm kiếm)

+0

Bạn có thể xây dựng? Làm thế nào đến: "tất cả các trường hợp tôi tạo có tham chiếu đến người dùng tạo chúng"? – dmitri

+0

Điều tôi ngụ ý là tất cả các tín hiệu tôi sử dụng đều có tham chiếu đến một cá thể (trong kwargs) có một trường 'created_by' hoặc một cái gì đó tương tự, có nghĩa là người dùng. – kiril

2
context_processors.py 

from django.core.cache import cache 

def global_variables(request): 
    cache.set('user', request.user) 

---------------------------------- 
in you model 

from django.db.models.signals import pre_delete 
from django.dispatch import receiver 
from django.core.cache import cache 
from news.models import News 

@receiver(pre_delete, sender=News) 
def news_delete(sender, instance, **kwargs): 
    user = cache.get('user') 

in settings.py 

TEMPLATE_CONTEXT_PROCESSORS = (
    'web.context_processors.global_variables', 
) 
+4

Mô tả về những gì bạn đã làm ở đó sẽ hữu ích. – JoelC

+1

Đây là một ý tưởng rất tồi tệ, không bao giờ làm theo cách này. Với hầu hết các cấu hình bộ nhớ cache, điều này sẽ dẫn đến tình trạng đua. – marxin

+1

Điều này hoàn toàn là WRONG. bộ nhớ cache không yêu cầu cụ thể – sha256

5

Tôi có thể thực hiện điều đó bằng cách kiểm tra ngăn xếp và tìm kiếm chế độ xem, sau đó xem xét biến cục bộ cho chế độ xem để nhận yêu cầu. Nó cảm thấy như một chút của một hack, nhưng nó đã làm việc.

import inspect, os 

@receiver(post_save, sender=MyModel) 
def get_user_in_signal(sender, **kwargs): 
    for entry in reversed(inspect.stack()): 
     if os.path.dirname(__file__) + '/views.py' == entry[1]: 
      try: 
       user = entry[0].f_locals['request'].user 
      except: 
       user = None 
      break 
    if user: 
     # do stuff with the user variable 
+0

làm việc tuyệt vời cho tôi, tôi không biết những gì xem sẽ được như vậy tôi loại bỏ kiểm tra và nó vẫn hoạt động tốt. –

3

Đối với truy xuất nguồn gốc thêm hai thuộc tính để mô hình của bạn (created_byupdated_by), trong "updated_by" tiết kiệm cho người sử dụng cuối cùng người sửa đổi hồ sơ. Sau đó, trong tín hiệu của bạn, bạn có người sử dụng:

models.py:

class Question(models.Model): 
    question_text = models.CharField(max_length=200) 
    pub_date = models.DateTimeField('date published') 
    created_by = models. (max_length=100) 
    updated_by = models. (max_length=100) 

views.py

p = Question.objects.get(pk=1) 
    p.question_text = 'some new text' 
    p.updated_by = request.user 
    p.save() 

tín hiệu.py

@receiver(pre_save, sender=Question) 
def do_something(sender, instance, **kwargs): 
    try: 
     obj = Question.objects.get(pk=instance.pk) 
    except sender.DoesNotExist: 
     pass 
    else: 
     if not obj.user == instance.user: # Field has changed 
      # do something 
      print('change: user, old=%s new=%s' % (obj.user, instance.user)) 
+0

Điều này là khủng khiếp dễ bị điều kiện chủng tộc. Mà có thể là ok cho rất nhiều trường hợp sử dụng, nhưng nó nên được đề cập. – Julien

3

Tại sao không thêm một middleware với một cái gì đó như thế này:

class RequestMiddleware(object): 

    thread_local = threading.local() 

    def process_request(self, request): 
     RequestMiddleware.thread_local.current_user = request.user 

và sau đó trong mã của bạn (đặc biệt trong một tín hiệu trong chủ đề đó):

thread_local = RequestMiddleware.thread_local 
if hasattr(thread_local, 'current_user'): 
    user = thread_local.current_user 
else: 
    user = None 
+0

Âm thanh tiếp cận rõ ràng. Tôi muốn tìm ra cái này đắt thế nào. – electropoet

+0

Tôi khuyên bạn không nên sử dụng luồng cho việc này. Điều này là rất khó khăn, và không phải là mã cấp ứng dụng, vì bạn không có nhiều quyền kiểm soát của các chủ đề đó. Tôi sẽ sử dụng bộ nhớ cache làm phụ trợ truyền thông ở đây bằng cách sử dụng một ID duy nhất. –

+0

@electropoet bạn đã tìm ra nó đắt bao nhiêu? Tôi đang nghĩ đến việc triển khai nó, và cho đến nay tôi không thể nghĩ ra bất kỳ tác dụng phụ nào. – Agey

2

Bạn cũng có thể sử dụng django-reversion cho mục đích này, ví dụ

from reversion.signals import post_revision_commit 
import reversion 

@receiver(post_save) 
def post_revision_commit(sender, **kwargs): 
    if reversion.is_active(): 
     print(reversion.get_user()) 

Tìm hiểu thêm về API của họ https://django-reversion.readthedocs.io/en/stable/api.html#revision-api

Các vấn đề liên quan