@property decorator in django models

In Django models, the @property decorator is used to define methods that behave like attributes, allowing you to create custom model properties. These properties can encapsulate logic and calculations, making them available as read-only attributes on model instances. Here’s how to use the @property decorator in a Django model:

Example

Let’s say you have a Book model with title and author_first_name, author_last_name fields, and you want to create a property called author_full_name that combines the author’s first and last names.

<span>from</span> <span>django.db</span> <span>import</span> <span>models</span>
<span>class</span> <span>Book</span><span>(</span><span>models</span><span>.</span><span>Model</span><span>):</span>
<span>title</span> <span>=</span> <span>models</span><span>.</span><span>CharField</span><span>(</span><span>max_length</span><span>=</span><span>100</span><span>)</span>
<span>author_first_name</span> <span>=</span> <span>models</span><span>.</span><span>CharField</span><span>(</span><span>max_length</span><span>=</span><span>50</span><span>)</span>
<span>author_last_name</span> <span>=</span> <span>models</span><span>.</span><span>CharField</span><span>(</span><span>max_length</span><span>=</span><span>50</span><span>)</span>
<span>@property</span>
<span>def</span> <span>author_full_name</span><span>(</span><span>self</span><span>):</span>
<span>return</span> <span>f</span><span>"</span><span>{</span><span>self</span><span>.</span><span>author_first_name</span><span>}</span><span> </span><span>{</span><span>self</span><span>.</span><span>author_last_name</span><span>}</span><span>"</span>
<span># Usage </span><span>book</span> <span>=</span> <span>Book</span><span>.</span><span>objects</span><span>.</span><span>get</span><span>(</span><span>pk</span><span>=</span><span>1</span><span>)</span>
<span>print</span><span>(</span><span>book</span><span>.</span><span>author_full_name</span><span>)</span> <span># Outputs: Firstname Lastname </span>
<span>from</span> <span>django.db</span> <span>import</span> <span>models</span>

<span>class</span> <span>Book</span><span>(</span><span>models</span><span>.</span><span>Model</span><span>):</span>
    <span>title</span> <span>=</span> <span>models</span><span>.</span><span>CharField</span><span>(</span><span>max_length</span><span>=</span><span>100</span><span>)</span>
    <span>author_first_name</span> <span>=</span> <span>models</span><span>.</span><span>CharField</span><span>(</span><span>max_length</span><span>=</span><span>50</span><span>)</span>
    <span>author_last_name</span> <span>=</span> <span>models</span><span>.</span><span>CharField</span><span>(</span><span>max_length</span><span>=</span><span>50</span><span>)</span>

    <span>@property</span>
    <span>def</span> <span>author_full_name</span><span>(</span><span>self</span><span>):</span>
        <span>return</span> <span>f</span><span>"</span><span>{</span><span>self</span><span>.</span><span>author_first_name</span><span>}</span><span> </span><span>{</span><span>self</span><span>.</span><span>author_last_name</span><span>}</span><span>"</span>

<span># Usage </span><span>book</span> <span>=</span> <span>Book</span><span>.</span><span>objects</span><span>.</span><span>get</span><span>(</span><span>pk</span><span>=</span><span>1</span><span>)</span>
<span>print</span><span>(</span><span>book</span><span>.</span><span>author_full_name</span><span>)</span>  <span># Outputs: Firstname Lastname </span>
from django.db import models class Book(models.Model): title = models.CharField(max_length=100) author_first_name = models.CharField(max_length=50) author_last_name = models.CharField(max_length=50) @property def author_full_name(self): return f"{self.author_first_name} {self.author_last_name}" # Usage book = Book.objects.get(pk=1) print(book.author_full_name) # Outputs: Firstname Lastname

Enter fullscreen mode Exit fullscreen mode

Key Points

  1. Read-Only: Properties created using @property are read-only. You cannot set them directly. If you need a writable property, you can define custom setter methods using the @property.setter decorator.

  2. Calculations and Logic: You can perform calculations or other logic inside the property method to dynamically generate the attribute value.

  3. Usage in Querysets: Since the property is calculated in Python and not stored in the database, you cannot directly use it in database queries. If you need to filter or sort based on such properties, you might need to use annotations or other query constructs.

Example with Setter

If you want to allow setting the author_full_name as well, you can define a setter for the property:

<span>class</span> <span>Book</span><span>(</span><span>models</span><span>.</span><span>Model</span><span>):</span>
<span>title</span> <span>=</span> <span>models</span><span>.</span><span>CharField</span><span>(</span><span>max_length</span><span>=</span><span>100</span><span>)</span>
<span>author_first_name</span> <span>=</span> <span>models</span><span>.</span><span>CharField</span><span>(</span><span>max_length</span><span>=</span><span>50</span><span>)</span>
<span>author_last_name</span> <span>=</span> <span>models</span><span>.</span><span>CharField</span><span>(</span><span>max_length</span><span>=</span><span>50</span><span>)</span>
<span>@property</span>
<span>def</span> <span>author_full_name</span><span>(</span><span>self</span><span>):</span>
<span>return</span> <span>f</span><span>"</span><span>{</span><span>self</span><span>.</span><span>author_first_name</span><span>}</span><span> </span><span>{</span><span>self</span><span>.</span><span>author_last_name</span><span>}</span><span>"</span>
<span>@author_full_name.setter</span>
<span>def</span> <span>author_full_name</span><span>(</span><span>self</span><span>,</span> <span>full_name</span><span>):</span>
<span>first_name</span><span>,</span> <span>last_name</span> <span>=</span> <span>full_name</span><span>.</span><span>split</span><span>(</span><span>'</span><span> </span><span>'</span><span>,</span> <span>1</span><span>)</span>
<span>self</span><span>.</span><span>author_first_name</span> <span>=</span> <span>first_name</span>
<span>self</span><span>.</span><span>author_last_name</span> <span>=</span> <span>last_name</span>
<span># Usage </span><span>book</span> <span>=</span> <span>Book</span><span>.</span><span>objects</span><span>.</span><span>get</span><span>(</span><span>pk</span><span>=</span><span>1</span><span>)</span>
<span>book</span><span>.</span><span>author_full_name</span> <span>=</span> <span>"</span><span>NewFirstname NewLastname</span><span>"</span>
<span>book</span><span>.</span><span>save</span><span>()</span>
<span>print</span><span>(</span><span>book</span><span>.</span><span>author_first_name</span><span>)</span> <span># Outputs: NewFirstname </span><span>print</span><span>(</span><span>book</span><span>.</span><span>author_last_name</span><span>)</span> <span># Outputs: NewLastname </span>
<span>class</span> <span>Book</span><span>(</span><span>models</span><span>.</span><span>Model</span><span>):</span>
    <span>title</span> <span>=</span> <span>models</span><span>.</span><span>CharField</span><span>(</span><span>max_length</span><span>=</span><span>100</span><span>)</span>
    <span>author_first_name</span> <span>=</span> <span>models</span><span>.</span><span>CharField</span><span>(</span><span>max_length</span><span>=</span><span>50</span><span>)</span>
    <span>author_last_name</span> <span>=</span> <span>models</span><span>.</span><span>CharField</span><span>(</span><span>max_length</span><span>=</span><span>50</span><span>)</span>

    <span>@property</span>
    <span>def</span> <span>author_full_name</span><span>(</span><span>self</span><span>):</span>
        <span>return</span> <span>f</span><span>"</span><span>{</span><span>self</span><span>.</span><span>author_first_name</span><span>}</span><span> </span><span>{</span><span>self</span><span>.</span><span>author_last_name</span><span>}</span><span>"</span>

    <span>@author_full_name.setter</span>
    <span>def</span> <span>author_full_name</span><span>(</span><span>self</span><span>,</span> <span>full_name</span><span>):</span>
        <span>first_name</span><span>,</span> <span>last_name</span> <span>=</span> <span>full_name</span><span>.</span><span>split</span><span>(</span><span>'</span><span> </span><span>'</span><span>,</span> <span>1</span><span>)</span>
        <span>self</span><span>.</span><span>author_first_name</span> <span>=</span> <span>first_name</span>
        <span>self</span><span>.</span><span>author_last_name</span> <span>=</span> <span>last_name</span>

<span># Usage </span><span>book</span> <span>=</span> <span>Book</span><span>.</span><span>objects</span><span>.</span><span>get</span><span>(</span><span>pk</span><span>=</span><span>1</span><span>)</span>
<span>book</span><span>.</span><span>author_full_name</span> <span>=</span> <span>"</span><span>NewFirstname NewLastname</span><span>"</span>
<span>book</span><span>.</span><span>save</span><span>()</span>
<span>print</span><span>(</span><span>book</span><span>.</span><span>author_first_name</span><span>)</span>  <span># Outputs: NewFirstname </span><span>print</span><span>(</span><span>book</span><span>.</span><span>author_last_name</span><span>)</span>   <span># Outputs: NewLastname </span>
class Book(models.Model): title = models.CharField(max_length=100) author_first_name = models.CharField(max_length=50) author_last_name = models.CharField(max_length=50) @property def author_full_name(self): return f"{self.author_first_name} {self.author_last_name}" @author_full_name.setter def author_full_name(self, full_name): first_name, last_name = full_name.split(' ', 1) self.author_first_name = first_name self.author_last_name = last_name # Usage book = Book.objects.get(pk=1) book.author_full_name = "NewFirstname NewLastname" book.save() print(book.author_first_name) # Outputs: NewFirstname print(book.author_last_name) # Outputs: NewLastname

Enter fullscreen mode Exit fullscreen mode

Limitations

  • Database Queries: Properties cannot be used in queryset filters or orderings. For example, you cannot do Book.objects.filter(author_full_name="John Doe").
  • Performance: Since properties are calculated in Python, they might introduce performance overhead if used extensively on large datasets.

Using properties in Django models helps keep your code clean and encapsulate logic within the model, promoting the principles of object-oriented programming.

原文链接:@property decorator in django models

© 版权声明
THE END
喜欢就支持一下吧
点赞9 分享
Life must be lived with love, happiness, and dreams.
人生一定要有爱,有快乐,有梦想
评论 抢沙发

请登录后发表评论

    暂无评论内容