django model 定义、统计、 高阶用法,form相关(字段加密、singal、customManager等),字段校验,电话正则表达式
pk使用uuid,字段校验
models.py import uuid from django.core.validators import RegexValidator from django.db import models class Customer(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) name = models.CharField(max_length=255) birthday = models.DateField() phone_no = models.CharField( max_length=11, validators=[RegexValidator(r"^[0-9]{11}$", "11桁の数字を入力してください。")], blank=True, ) class Meta: db_table = "Customer"
Django - Update model field based on another field
class Item(models.Model): name = models.CharField(max_length=40) default_price = models.DecimalField(max_digits=6, decimal_places=2, default=50) def __unicode__(self): return self.name class SaleDetail(models.Model): item = models.ForeignKey(Item) deposit = models.ForeignKey(Deposit) quantity = models.PositiveIntegerField() entered_unit_price = models.DecimalField(max_digits=6, decimal_places=2, default=None) sale = models.ForeignKey(Sale) @property def unit_price(self, value): if self.entered_unit_price is None: return self.item.default_price else: return self.entered_unit_price @unit_price.setter def unit_price(self, value): self.entered_unit_price = value
Then use it like so:
print(sd.unit_price)
sd.unit_price = 500
sd.save()
更好点的用法
check if there is a pk
. If the pk
is None, we know that the SaleDetail
is new. Then, we see if there is a unit_price
. If there is not a unit_price
, we set it to the Item.default_price
.
class Item(models.Model): name = models.CharField(max_length=40) default_price = models.DecimalField(max_digits=6, decimal_places=2, default=50) def __unicode__(self): return self.name class SaleDetail(models.Model): item = models.ForeignKey(Item) deposit = models.ForeignKey(Deposit) quantity = models.PositiveIntegerField() unit_price = models.DecimalField(max_digits=6, decimal_places=2) sale = models.ForeignKey(Sale) def save(self, *args, **kwargs): # Make sure this is the first save (pk should be None) and there is no unit_price set if self.pk is None and not self.unit_price: self.unit_price = self.item.default_price elif not self.unit_price: self.unit_price = self.item.default_price # Call the original save method super(SaleDetail, self).save(*args, **kwargs)
关于signal:
This calls post_save 信号会被调用
user = User.objects.get(id=1)
user.username='edited_username'
user.save()
This does not call post_save 这种写法,写好不会被调用
User.objects.filter(id=1).update(username='edited_username')
学习signal:https://simpleisbetterthancomplex.com/tutorial/2016/07/28/how-to-create-django-signals.html
深度定制django model:定制managerhttps://docs.djangoproject.com/en/3.1/topics/db/managers/
hidden隐藏字段
Change a Django form field to a hidden field
form里的内容用__dict__输出。
model.xxx 可以提取数据
从dict提取数据不能用 dict.xx 而是用 dict.get('xx')
print(form.instance.status) print(form.data.get('status','defaultvalue')) print(form.__dict__)
>2
>2
>{'instance': <KhPeriod: 临时考核112>, '_validate_unique': True, 'is_bound': True, 'data': <QueryDict: {'csrfmiddlewaretoken': ['US7oLRjAiTtBPCD3QEyVSjgTXd3j0cXSEvtJnK4P58sjtHEZ3Jqa6G9swTgjIgab'], 'kaohename': ['临时考核112'], 'status': ['2']}>, 'files': {}, 'auto_id': 'id_%s', 'initial': {'id': 20211, 'kaohename': '临时考核11', 'status': '2'}, 'error_class': <class 'django.forms.utils.ErrorList'>, 'label_suffix': ':', 'empty_permitted': False, '_errors': {}, 'fields': OrderedDict([('kaohename', <django.forms.fields.CharField object at 0x000002139692CA58>), ('status', <django.forms.fields.TypedChoiceField object at 0x000002139692CCC0>)]), '_bound_fields_cache': {'status': <django.forms.boundfield.BoundField object at 0x0000021396AC37B8>}, 'renderer': <django.forms.renderers.DjangoTemplates object at 0x0000021396AD43C8>, 'cleaned_data': {'kaohename': '临时考核112', 'status': '2'}}
一、限制数据的方式
data = list(Sale.objects.all())[:100] 最差用法
data = Sale.objects.all()[:100] 较好的用法
二、case when 的条件统计
from django.contrib.auth.models import User from django.db.models import Count, F User.objects.aggregate( total_users=Count('id'), total_active_users=Count('id', filter=F('is_active')), )
三、定义
# All 3 are equivalent! 三种定义字段方式相同
full_name = models.CharField(max_length=100)
full_name = models.CharField('full name', max_length=100)
full_name = models.CharField(verbose_name='full name', max_length=100)
四、关联foreign查询
class University(models.Model): full_name = models.CharField( max_length=100, ) class Student(models.Model): # new first_name = models.CharField('first name', max_length=30) last_name = models.CharField('last name', max_length=30) university = models.ForeignKey( University, on_delete=models.CASCADE, related_name='students', related_query_name='person', )
class Meta: # new
indexes = [models.Index(fields=['first_name'])]
ordering = ['-first_name']
verbose_name = 'Student'
以上的model,默认的查询方式:
dartmouth = University.objects.get(full_name='Dartmouth') dartmouth.student_set.all() # returns all students at Dartmouth University.objects.filter(student__first_name='william') # returns all University students named William
设定related_name和query_name后
yale = University.objects.get(full_name='Yale') yale.students.all() # returns all students at Yale University.objects.filter(person__first_name='ashley') # returns all University students named Ashley
以上,注意 Meta可以定义默认的order和indexes, 这个以前没注意过