Làm thế nào để đổi tên các mục trong giá trị () trong Django?


101

Tôi muốn làm tương tự như trong vé này tại djangoproject.com , nhưng với một số định dạng bổ sung. Từ truy vấn này

>>> MyModel.objects.values('cryptic_value_name')
[{'cryptic_value_name': 1}, {'cryptic_value_name': 2}]

Tôi muốn nhận được một cái gì đó như thế:

>>> MyModel.objects.values(renamed_value='cryptic_value_name')
[{'renamed_value': 1}, {'renamed_value': 2}]

Có cách nào khác, nhiều nội dung hơn hay tôi phải thực hiện việc này theo cách thủ công?

Câu trả lời:


72

Nó hơi khó hiểu, nhưng bạn có thể sử dụng extraphương pháp:

MyModel.objects.extra(
  select={
    'renamed_value': 'cryptic_value_name'
  }
).values(
  'renamed_value'
)

Điều này về cơ bản thực hiện SELECT cryptic_value_name AS renamed_valuetrong SQL.

Một tùy chọn khác, nếu bạn luôn muốn phiên bản được đổi tên nhưng db có tên khó hiểu, là đặt tên trường của bạn bằng tên mới nhưng sử dụng db_columnđể tham chiếu đến tên gốc trong db.


6
Rõ ràng trong 1.7. * Bạn sẽ có thể viết thẳng các tên bí danh dưới dạng các đối số được đặt tên cho values(). Nguồn: code.djangoproject.com/ticket/16735
gregoltsov

19
-1 bởi vì .values(supports__through_tables)và hack này không (tình cờ có lẽ là trường hợp sử dụng rõ ràng nhất để muốn đổi tên các ValuesQuerySetkhóa dict)
wim

1
Có ai đã tìm ra cách để thực hiện việc này thông qua các bảng (.values ​​(supports__through_tables)) không?
François Constant

12
Rất tiếc, giải pháp này không hỗ trợ các tên liên quan như in .values('foreignkeymodel__id', 'foreignkeymodel__name').
Risadinha

13
Model.objects.annotate (my_alias = F ('some__long__name__to__alias')). Giá trị ('my_alias') từ vé 16735.
eugene

188

Từ django>=1.8bạn có thể sử dụng chú thích và đối tượng F

from django.db.models import F

MyModel.objects.annotate(renamed_value=F('cryptic_value_name')).values('renamed_value')

Cũng extra()sẽ không được dùng nữa, từ tài liệu django:

Đây là một API cũ mà chúng tôi muốn ngừng sử dụng vào một thời điểm nào đó trong tương lai. Chỉ sử dụng nó nếu bạn không thể diễn đạt truy vấn của mình bằng các phương thức bộ truy vấn khác. Nếu bạn cần sử dụng nó, vui lòng gửi một vé bằng từ khóa QuerySet.extra với trường hợp sử dụng của bạn (vui lòng kiểm tra danh sách các vé hiện có trước) để chúng tôi có thể nâng cao API QuerySet để cho phép xóa thêm (). Chúng tôi không còn cải tiến hoặc sửa lỗi cho phương pháp này.


3
Câu trả lời này chỉ hoạt động trên django>=1.8. Biểu thức truy vấn được bật annotateđể chấp nhận các biểu thức không phải là tổng hợp. Tham khảo: docs.djangoproject.com/en/1.9/releases/1.8/…
Yeo

3
Nó hoạt động, nhưng không phải cú pháp được đề xuất trong câu hỏi ban đầu đẹp hơn nhiều sao? MyModel.objects.values(renamed_value='cryptic_value_name')
wim

11
MyModel.objects.values(renamed_value=models.F('cryptic_value_name'))công trình
jarcoal

1
Câu trả lời này hoạt động nhưng là thừa. Các đối số từ khóa được chuyển đến values()sẽ được chuyển annotate()thay mặt bạn (xem docs.djangoproject.com/en/2.2/ref/models/querysets/… ). Câu trả lời MyModel.objects.values(renamed_value=F('cryptic_value_name'))là đơn giản và rõ ràng hơn, IMO.
tobias.mcnulty

76

Không sử dụng bất kỳ phương pháp quản lý nào khác (đã thử nghiệm trên v3.0.4):

from django.db.models import F

MyModel.objects.values(renamed_value=F('cryptic_value_name'))

Trích từ tài liệu Django :

Một F () đối tượng đại diện cho giá trị của một lĩnh vực mô hình hoặc cột được chú thích. Nó làm cho nó có thể tham chiếu đến các giá trị trường mô hình và thực hiện các hoạt động cơ sở dữ liệu bằng cách sử dụng chúng mà không thực sự phải kéo chúng ra khỏi cơ sở dữ liệu vào bộ nhớ Python.


5
Đối với nhiều hơn một giá trị mà bạn có thể sử dụng:MyModel.objects.values(renamed_value=F('cryptic_value_name'),renamed_value2=F('cryptic_value_name2'))
alpere

1
nhưng nếu bạn muốn thay đổi một giá trị và giữ giá trị kia thì sao? Với chú thích thì có thể: inv.annotate(name=F('stock__name')).values('name', "price")nhưng tôi không thấy phương pháp này sẽ hoạt động như thế nào trong trường hợp đó. inv.values(name=F("stock__name"), price=F("price"))-> Chú thích 'giá' xung đột với một trường trên mô hình
Malte

1
@Malte Tôi nghĩ không cần thiết phải làm phức tạp điều này. Chỉ cần cố gắng inv.values('price', name=F("stock__name")). Trong python, bạn chỉ có thể đặt các đối số được đặt tên sau các đối số không được đặt tên.
Arpit Singh

0

Tôi đang làm việc với django 1.11.6

(Và chìa khóa: cặp giá trị đối lập với cặp giá trị được chấp nhận)

Đây là cách tôi đang làm cho nó hoạt động cho dự án của tôi

def json(university):
    address = UniversityAddress.objects.filter(university=university)
    address = address.extra(select={'city__state__country__name': 'country', 'city__state__name': 'state', 'city__name': 'city'})
    address = address.values('country', 'state', "city", 'street', "postal_code").get()
    return address

Lưu ý rằng việc thêm simultanous objects.filter (). Extra (). Values ​​() giống như trên.


bạn có thể thấy rằng .extra(select={cryptic_value:ranamed_value})có chìa khóa ngược lại: giá trị so với câu trả lời được chấp nhận
Sudip Bhattarai

-6

Nó không đơn giản hơn nếu bạn muốn đổi tên một vài trường của chế độ.

Thử

projects = Project.objects.filter()
projects = [{'id': p.id, 'name': '%s (ID:%s)' % (p.department, p.id)} for p in projects]

Ở đây tôi không có nametrường trong bảng, nhưng tôi có thể nhận được trường đó sau khi điều chỉnh một chút.


10
–1 nó đánh giá bộ truy vấn, là bộ ngắt giao dịch
wim
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.