2010-06-09 24 views
16

Tôi có cùng một câu hỏi hóc búa như presented in this question, nhưng được áp dụng cho auth.User của Django.Cách chuyển đổi request.user thành proxy auth.User class?

tôi có mô hình proxy này:

class OrderedUser(User): 
    def __unicode__(self): 
     return self.get_full_name() 

    class Meta: 
     proxy=True 
     ordering=["first_name", "last_name"] 

Và một số mô hình khác của tôi sử dụng một OrderedUser thay vì một django.contrib.auth.models.User như kiểu trường.

Trong quan điểm của tôi sau đó tôi sử dụng request.user để cư trú một trường và - như mong đợi - nhận được một lỗi:

'Cannot assign "<User...>": <field> must be a "OrderedUser" instance' 

Tôi chỉ có thể làm OrderedUser.objects.get(request.user.id), nhưng đó là một hit bổ sung cho các cơ sở dữ liệu.

Vì vậy, làm thế nào để chuyển đổi một lớp mô hình cơ sở thành lớp được ủy quyền của nó?

Trả lời

14

Đó là một cơ sở dữ liệu hit, nhưng điều này sẽ làm việc:

OrderedUser.objects.get(pk=request.user.pk) 

Sửa Bạn có thể thử:

o = OrderedUser() 
o.__dict__ = request.user.__dict__ 
+0

Đúng vậy. Có cơ chế nào không liên quan đến cú đánh của DB không? – cethegeek

+2

Vâng, sao chép dict đã làm các trick. Cảm ơn Daniel. – cethegeek

+3

Cảm ơn lời khuyên này. Một điều tôi đã tìm thấy mặc dù, khi sử dụng điều này trong một context_processor để vượt qua một đối tượng người dùng đến các mẫu ... bạn cần phải làm điều đó một cách khác nhau nếu người dùng không đăng nhập. Như bạn có nó, o luôn luôn kết thúc bằng một đối tượng OrderedUser (hậu duệ của User), nhưng nếu người dùng không đăng nhập, nó phải là kiểu AnonymousUser. Vì vậy, tôi sẽ kiểm tra nếu 'request.user.is_authenticated()' và nếu như vậy, chỉ sau đó làm điều trên. Khác, làm 'o = request.user'. –

10

tôi không thể có được phương pháp sao chép dict để làm việc trên Python 2.7 .4 và Django 1.6. Tôi đã không theo dõi nó tất cả các con đường xuống, nhưng tôi nghĩ rằng nó có cái gì để làm với nó là một đối tượng lười biếng.

gì làm việc cho tôi:

request.user.__class__ = OrderedUser 

Nó tránh được cuộc gọi cơ sở dữ liệu và cho phép truy cập đến auth thứ cơ sở và tất cả các hành vi mở rộng của tôi.

Để thực hiện các hành động request.user như lớp proxy mọi khi, tôi đặt nhiệm vụ trong middleware sau các middleware xác thực và trước bất kỳ ứng dụng của tôi có thể tham khảo nó. Vì phần mềm trung gian được gọi trên mọi yêu cầu, hãy đảm bảo rằng người dùng được xác thực trước khi thiết lập lớp. Sử dụng ví dụ của bạn, đây là cách mã middleware có thể trông:

from yourapp.models import OrderedUser 

class OrderedUserMiddleware(): 
    def process_request(self, request): 
     if hasattr(request, 'user') and request.user.is_authenticated(): 
      request.user.__class__ = OrderedUser 

Và hãy nhớ để đăng ký middleware sau khi xác thực:

MIDDLEWARE_CLASSES = [ 
    # ...middleware from the guts of Django, none of your middle wares yet... 
    'django.contrib.auth.middleware.AuthenticationMiddleware', 
    # ...more middleware from the guts of Django, none of your middlewares yet... 
    'yourapp.middleware.OrderedUserMiddleware', 
    # ...more middleware from you other middlewares... 
] 
+0

Điều tôi đang tìm kiếm. – Charlesliam

+0

Điều này làm việc tuyệt vời, ngoại trừ tôi không thể có được middleware làm việc với xác thực django-rest-framework và đã phải nghỉ mát để thiết lập __class__. – MrDBA

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