2009-05-08 31 views
182

Tôi đang cố gắng tạo ra một SlugField ở Django.Làm cách nào để tạo một con sên ở Django?

Tôi tạo ra mô hình này rất đơn giản:

from django.db import models 

class Test(models.Model): 
    q = models.CharField(max_length=30) 
    s = models.SlugField() 

sau đó tôi làm điều này:

>>> from mysite.books.models import Test 
>>> t=Test(q="aa a a a", s="b b b b") 
>>> t.s 
'b b b b' 
>>> t.save() 
>>> t.s 
'b b b b' 
>>> 

tôi đã mong b-b-b-b

+15

tôi đến đây từ "tango with django";) – kmonsoor

Trả lời

351

Bạn sẽ cần phải sử dụng chức năng slugify.

>>> from django.template.defaultfilters import slugify 
>>> slugify("b b b b") 
u'b-b-b-b' 
>>> 

Bạn có thể gọi slugify tự động bằng cách ghi đè các phương pháp save:

class test(models.Model): 
    q = models.CharField(max_length=30) 
    s = models.SlugField() 

    def save(self, *args, **kwargs): 
     self.s = slugify(self.q) 
     super(test, self).save(*args, **kwargs) 

Hãy nhận biết rằng ở trên sẽ gây ra URL của bạn thay đổi khi các lĩnh vực q được chỉnh sửa, có can cause broken links. Nó có thể là một lợi thế để tạo ra sên một lần duy nhất khi bạn tạo một đối tượng mới:

class test(models.Model): 
    q = models.CharField(max_length=30) 
    s = models.SlugField() 

    def save(self, *args, **kwargs): 
     if not self.id: 
      # Newly created object, so set slug 
      self.s = slugify(self.q) 

     super(test, self).save(*args, **kwargs) 
+3

nhút nhát có loại mô hình đặc biệt? tại sao không chỉ slugify CharFields? – Johnd

+22

SlugFields đặt db_index = True theo mặc định và cũng sử dụng trường biểu mẫu theo mặc định có regex xác thực để yêu cầu các slugs hợp lệ (nếu được trình bày trong một ModelForm hoặc trong quản trị viên). Bạn có thể làm những điều đó bằng tay với CharField nếu bạn thích, nó chỉ làm cho ý định mã của bạn ít rõ ràng hơn. Ngoài ra, đừng quên cài đặt Prepopulate_fields ModelAdmin, nếu bạn muốn tự động điền sẵn dựa trên JS trong quản trị viên. –

+4

Như Dingle đã nói dưới đây trong câu trả lời của mình, bạn sẽ cần phải thay thế 'def save (self):' với 'def save (self, * args, ** kwargs):' để tránh các lỗi bị ném khi viết một cái gì đó như 'test.objects.create (q =" blah blah blah ")'. – Liam

27

Nếu bạn đang sử dụng giao diện quản trị để thêm các mục mới của mô hình, bạn có thể thiết lập một ModelAdmin trong admin.py của bạn và sử dụng để tự động hóa prepopulated_fields cách nhập của một sên:

class ClientAdmin(admin.ModelAdmin): 
    prepopulated_fields = {'slug': ('name',)} 

admin.site.register(Client, ClientAdmin) 

ở đây, khi người dùng nhập vào một giá trị trong các hình thức quản trị cho lĩnh vực name, các slug sẽ được tự động điền đúng slugified name.

+0

Các trường 'slug' và' name' của tôi có bản dịch. Làm thế nào tôi có thể làm điều đó với bản dịch? Bởi vì tôi đã cố gắng thêm ''slug_en' :('name_en',)' và nhận được lỗi rằng thuộc tính không tồn tại trong mô hình của tôi. – patricia

22

Trong hầu hết các trường hợp, sên không nên thay đổi, vì vậy bạn thực sự chỉ muốn tính toán nó trên đầu tiết kiệm:

class Test(models.Model): 
    q = models.CharField(max_length=30) 
    s = models.SlugField(editable=False) # hide from admin 

    def save(self): 
     if not self.id: 
      self.s = slugify(self.q) 

     super(Test, self).save() 
+8

nên chấp nhận * args và ** kwargs –

57

Một sự điều chỉnh nhỏ để Thepeer của câu trả lời: Để ghi đè save() chức năng trong các lớp mô hình, tốt hơn thêm đối số với nó:

from django.utils.text import slugify 

def save(self, *args, **kwargs): 
    if not self.id: 
     self.s = slugify(self.q) 

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

Nếu không, test.objects.create(q="blah blah blah") sẽ dẫn đến một force_insert lỗi (đối số bất thường).

+2

Một điều rất nhỏ nữa để thêm vào câu trả lời của người dùng: Tôi sẽ làm cho dòng cuối cùng đó trở lại siêu (tự kiểm tra, tự) .save (* args, ** kwargs) '. Tôi nghĩ phương thức này trả về 'None', và tôi không biết bất kỳ kế hoạch nào để thay đổi điều đó, nhưng không có hại gì khi trả về phương thức của lớp cha trong trường hợp nó thay đổi đôi chút trong tương lai. –

+0

Vui lòng thêm * từ django.utils.text import slugify * là bắt buộc cho giải pháp này. – Routhinator

+1

@Routhinator đã làm điều đó –

5

Nếu bạn không muốn đặt slugfield thành Không thể chỉnh sửa, thì tôi tin bạn sẽ muốn đặt thuộc tính Null và Blank thành False. Nếu không, bạn sẽ gặp lỗi khi cố gắng lưu trong Quản trị viên.

Vì vậy, một sửa đổi để ví dụ trên sẽ là ::

class test(models.Model): 
    q = models.CharField(max_length=30) 
    s = models.SlugField(null=True, blank=True) # Allow blank submission in admin. 

    def save(self): 
     if not self.id: 
      self.s = slugify(self.q) 

     super(test, self).save() 
+5

hoặc bạn có thể sử dụng có thể chỉnh sửa = False: P – bx2

+0

Tài liệu trên [có thể chỉnh sửa] (https://docs.djangoproject.com/en/1.11/ref/models/fields/#editable) – surfer190

101

Có trường hợp góc với một số utf-8 ký tự

Ví dụ:

>>> from django.template.defaultfilters import slugify 
>>> slugify(u"test ąęśćółń") 
u'test-aescon' # there is no "l" 

Điều này có thể được giải quyết với Unidecode

>>> from unidecode import unidecode 
>>> from django.template.defaultfilters import slugify 
>>> slugify(unidecode(u"test ąęśćółń")) 
u'test-aescoln' 
+4

Đây là một bổ sung rất quan trọng mà sẽ nhận được nhiều sự chú ý hơn (upvotes) để được chú ý! –

+6

utf-8 hiện được xử lý chính xác bởi slugify (trong django 1.8.5) –

+0

@ASz Làm theo hướng dẫn của bạn, tôi đã bỏ phiếu. : D – learner

2

Tôi đang sử dụng Django 1,7

Tạo một SlugField trong mô hình của bạn như thế này:

slug = models.SlugField() 

Sau đó, trong admin.py xác định prepopulated_fields;

class ArticleAdmin(admin.ModelAdmin): 
    prepopulated_fields = {"slug": ("title",)} 
Các vấn đề liên quan