GVKun编程网logo

如何在mongodb中扩展django的默认用户?(mongodb django)

454

在这篇文章中,我们将带领您了解如何在mongodb中扩展django的默认用户?的全貌,包括mongodbdjango的相关情况。同时,我们还将为您介绍有关18_django的用户模型和扩展djang

在这篇文章中,我们将带领您了解如何在mongodb中扩展django的默认用户?的全貌,包括mongodb django的相关情况。同时,我们还将为您介绍有关18_django的用户模型和扩展django的用户模型、django from组件 ,model—from,django的缓存机制,dango的信号,django的序列号、Django如何在Django表单中自动保存用户?、Django:如何在model.py页面上获取用户ID并动态设置默认值的知识,以帮助您更好地理解这个主题。

本文目录一览:

如何在mongodb中扩展django的默认用户?(mongodb django)

如何在mongodb中扩展django的默认用户?(mongodb django)

使用EmbeddedField并不是一个好主意,因为它将复制数据库中的用户数据。您将在“用户”集合中有一些用户,并且相同的数据将嵌入到Profile集合元素中。

只需将用户ID保留在模型中并分别查询:

class Profile(models.Model):
    user_id = models.CharField() #or models.TextField()
    mobile = models.PositiveIntegerField()
    address = models.CharField(max_length=200)
    pincode = models.PositiveIntegerField()
,

它很简单,如文档中所定义。

所以,首先,使用 djongo 模型作为 model_container,我认为 User 模型是 Django 模型,而不是 djongo 模型。

第二件事,通过在下面给出的 Meta 类中定义,使您的 model_cotainer 模型抽象。

from djongo import models

class Blog(models.Model):
    name = models.CharField(max_length=100)

    class Meta:
        abstract = True

class Entry(models.Model):
    blog = models.EmbeddedField(
        model_container=Blog
    )    
    headline = models.CharField(max_length=255) 

参考:https://www.djongomapper.com/get-started/#embeddedfield

18_django的用户模型和扩展django的用户模型

18_django的用户模型和扩展django的用户模型

[TOC]

User 模型

User模型是这个框架的核心部分。他的完整的路径是在django.contrib.auth.models.User。以下对这个User模型做一个简单的了解:

字段:

内置的User模型拥有以下的字段: 1. username: 用户名。150个字符以内。可以包含数字和英文字符,以及_/@/+/.和-字符。不能为空,且必须唯一。 2. email: 邮箱。 可以为空。 3. password: 密码。经过哈希过后的密码. 4. groups: 分组。多对多的组。一个分组可以拥有多个用户,groups这个字段是跟Group的一种多对多的关系. 5. user_permissions: 权限。一个用户可以拥有多个权限,一个权限可以被多个用户所有用。和Permission属于一种多对多的关系。 6. is_staff: 是否可以进入到admin的站点。代表是否是员工。 7. is_active: 是否是可用的。对于一些想要删除账号的数据,我们设置值为False就可以了,而不是真正的从数据库中删除. 8. is_superuser: 是否是超级管理员。如果是超级管理员,那么拥有整个网站的所有权限. 9. last_login: 上次登录的时间 10. date_joined: 注册时间,即账号创建的时间

User模型的基本用法

创建用户:

通过 create_user方法可以快速的创建用户。这个方法必须传递 username, password和email可传可不传 示例代码如下。

from django.contrib.auth.models import User
user = User.objects.create_user(username=''long'', email=''1987719593@qq.com'', password=''111111'')
# 创建完成后,还可以进行修改某个字段, 如
user.password = ''yanyan_love''
user.save()

创建超级用户:

创建超级用户有两种方式。第一种是使用代码的方式。用代码创建超级用户跟创建普通用户非常的类似,只不过是使用 create_superuser, 并且必须要传递username, password, email。示例代码如下:

from django.contrib.auth.models import User
user = User.objects.create_superuser(username=''long'', email=''1987719593@qq.com'', password=''111111'')

也可以通过命令行的方式。命令为: python manage.py create_superuser, 然后根据提示输入用户名和邮箱和密码

我的创建用户代码
# User 模型的基本用法
# 1. 创建用户
from django.contrib.auth.models import User
class CreateUser(View):
    def get(self, request):
        return render(request, ''blog/create_user.html'')

    def post(self, request):
        username = request.POST.get(''username'')
        password = request.POST.get(''password'')
        email = request.POST.get(''email'')
        print(username, password, email)
        if username:
            # 1. 创建普通用户
            user = User.objects.create_user(username=username)
            # 创建完成后,还可以对某个字段进行修改
            user.password = ''5201314''  # 这样子修改的密码是不加密的
            user.email = ''haolong@163.com''
            user.save()

        # if username and email and password:
            # 2. 创建超级用户,代码实现
            # super_user = User.objects.create_superuser(username=username, email=email, password=password)
            return HttpResponse(''success'')
        return HttpResponse(''fail'')

修改密码:

因为密码是需要经过加密后才能存储进去的,所以如果想要修改密码,不能直接修改 password 字段。而需要调用 set_password 来达到修改密码的目的。 示例代码如下:

# 修改密码
from django.contrib.auth.models import User
def set_password_user(request):
    user = User.objects.get(pk=1)
    user.set_password(''new_password'')  # 把新的密码放在括号中
    user.save()  # 记得保存
    return HttpResponse(''success'')

登录验证

Django的验证系统已经帮我们实现了登录验证的功能。通过 django.contrib.auth.authenticate即可实现。这个方法只能通过 usernamepassword 来进行验证。示例代码如下:

# 登录验证
from django.contrib.auth import authenticate
def login(request):
    # user = authenticate(username=''yan'', password=''adminadmin'')
    user = authenticate(request, username=''yan'', password=''adminadmin'')
    print(user)
    # 如果验证通过了,就会返回一个 user 对象
    if user:
        # 验证通过后的代码
        print(''登录成功: %s'' % user.username)
    else:
        # 验证失败后的代码
        print(''登录失败 用户名或密码错误'')
    return HttpResponse(''login'')

扩展用户模型:

Django 内置的 User 模型虽然已经足够强大了,但是有时候还是不能满足我们的需求。比如在验证用户登录的时候,他用的是用户名作为验证,而我们有时候需要通过手机号码或者邮箱来进行验证。还有比如我们想要增加一些新的的字段。那么这时候我们就需要扩展用户模型了。扩展用户模型有多种方式。这里我们一一讨论下。

1. 设置Proxy模型

如果你对 Django提供的字段,以及验证的方法都比较满意,没有什么需要修改的,只是需要在他原有的基础之上增加一些操作的方法,那么建议使用这种方式。示例代码如下:

from django.db import models
from django.contrib.auth.models import User
class Person(User):
    class Meta:
        proxy = True
    def get_blacklist(self):
        return self.objects.filter(is_active=False) # is_active 是否激活,判断该用户是否可用,=False即不可用
# models.py
from django.contrib.auth.models import User
# User  的代理模型
class Person(User):
    # 这种Field字段不可以有,有的话,数据库映射的时候会报错, 需要注意
    # telephone = models.CharField(max_length=11)
    class Meta:
        proxy = True
    @classmethod
    def get_blacklist(cls):
        """获取所有的黑名单"""
        return cls.objects.filter(is_active=False)
    # 不止可以定义这些,还可以定义一些其它的

# 使用 views.py
# 扩展用户模型
from .models import Person
def proxy_view(request):
    blacklist = Person.get_blacklist()  # 获取所有没有激活的用户, 即黑名单用户
    for person in blacklist:
        print(person.username)
    return HttpResponse(''proxy 扩展用户模型'')

# 如果没有未激活的用户, 可以设置用户为未激活
def set_active(reqeust):
    """设置黑名单用户"""
    user = User.objects.get(pk=1)
    user.is_active = 0
    user.save()
    return HttpResponse(''设置黑名单成功: %s'' % user.username)

在以上,我们定义了一个Person 对象,让他继承自 User, 并且在 Meta元类中设置了 proxy=True,说明这个Person 只是 User 的一个代理模型。他并不会影响原来 User模型在数据库中表的结构,以后如果你想方便的获取所有黑名单的人,那么你就可以通过 Person.get_blacklist() 就可以获取到。并且 User.objects.all()Person.objects.all其实是等价的,加为他们都是从User这个模型中获取所有的数据 (注意: 如果一个模型是代理模型, 那么就不能在这个模型中添加新的Field)

2. 一对一外键

如果你对用户验证方法 authenticate 没有其他要求,就是使用 usernamepassword 即可完成。但是想要在原来模型的基础上添加新的字段,那么可以使用 一对一外键 的方式。示例代码如下:

# models.py
# 一对一外键 扩展用户模型
from django.contrib.auth.models import User
from django.db import models
from django.dispatch import receiver
from django.db.models.signals import post_save

class UserExtension(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name=''extension'')
    telephone = models.CharField(max_length=11, verbose_name=''电话号码'')
    birthday = models.DateField(null=True, blank=True, verbose_name=''出生日期'')
    school = models.CharField(max_length=20, verbose_name=''学校'')

@receiver(post_save, sender=User)
def create_user_extension(sender, instance, created, **kwargs):
    if created:
        UserExtension.objects.create(user=instance)
    else:
        instance.extension.save()

# 使用 views.py
# 一对一扩展 User 模型
def one_to_one_user(request):
    user = User.objects.create_superuser(username=''yy'', password=''5021314yanyan'', email=''1599962587@qq.com'')
    user.extension.telephone = ''13037200197''
    user.extension.school = ''明瑞''
    user.save()
    return HttpResponse(''一对一扩展User用户模型'')

# 自定义字段验证登录
# 自定义验证登录
def my_authenticate(telephone, password):
    user = User.objects.filter(extension__telephone=telephone).first()
    print(user)
    if user:
        is_correct = user.check_password(password)
        print(is_correct)
        if is_correct:
            return user
        else:
            return None
    else:
        return None

def one_login(request):
    """使用自定义的验证 my_authenticate 来进行登录验证"""
    telephone = request.GET.get(''telephone'')
    password = request.GET.get(''password'')
    user = my_authenticate(telephone, password)
    print(user)
    if user:
        print(''验证成功: %s'' % user.username)
    else:
        print(''验证失败'')
    return HttpResponse(''自定义验证字段登录'')

以上定义了一个 UserExtension的模型,并且让他和 User 模型进行了一对一的绑定,以后我们新增的字段,就添加到 UserExtension 上。 并且还写了一个接受保存模型的信号处理方法,只要是 User调用了save() 方法,那么就会创建一个UserExtensionUser 进行绑定。

3. 继承自 AbstractUser:

对于 authenticate 不满意,并且不想要修改原来的 User对象上的一些字段,但是想要增加一些字段,那么这时候可以直接继承自django.contrib.auth.models.AbstractUser,其实这个类也是 django.contrib.auth.models.User 的父类。比如我们想要在原来 User 模型的基础之上添加一个 telephoneschool 字段。 示例代码如下: (注意: 第一次映射数据库的时候就要创建好)

# models.py
# 继承自 AbstractUser

from django.contrib.auth.models import BaseUserManager
class UserManager(BaseUserManager):
    use_in_migrations = True
    def _create_user(self, telephone, username, password, **extra_fields):
        if not telephone:
            raise ValueError(''必须要传递手机号码'')
        if not password:
            raise ValueError(''必须要传递手机号码'')
        user = self.model(telephone=telephone, *extra_fields)
        user.set_password(password)
        user.save()
        return user
    def create_user(self, telephone, username, password, **kwargs):
        kwargs[''is_superuser''] = False
        return self._create_user(telephone=telephone, username=username, password=password, **kwargs)
    def create_superuser(self, telephone, username, password, **kwargs):
        kwargs[''is_superuser''] = True
        return self._create_user(telephone=telephone, username=username, password=password, **kwargs)

# 继承自 AbstractUser
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
    telephone = models.CharField(max_length=11, unique=True, verbose_name=''电话号码'')
    school = models.CharField(max_length=100)

    # 指定 telephone 作为 USERNAME_FIELD, 以后使用 authenticate
    # 函数验证的时候,就可以根据 telephone 来验证
    # 而不是原来的 username
    USERNAME_FIELD = ''telephone''
    REQUIRED_FIELDS = []

    objects = UserManager()

# settings.py
# 并且在 settins.py 中添加这样一句话:
AUTH_USER_MODEL = ''blog.User''  # blog 是 app 名字, User 是blog.models 下面新建的一个类,即上面那个
from django.contrib.auth.models import AbstractUser, UserManager as _UserManager

class UserManager(_UserManager):
    """"""
    # def create_superuser(self, username, mobile, password, email=None, **extra_fields):
    #     super().create_superuser(username=username, mobile=mobile, password=password, email=None, **extra_fields)

    def create_superuser(self, username, password, email=None, **extra_fields):
        super().create_superuser(username=username, password=password, email=email, **extra_fields)

class Users(AbstractUser):
    """
    add mobile  、 email_active fields to Django uswers models
    """
    mobile = models.CharField(max_length=11, unique=True, verbose_name=''手机号'', help_text=''手机号'', error_messages={
        ''unique'': ''此手机号已经被注册过了'',
    })
    email_active = models.BooleanField(default=False, verbose_name=''邮箱验证状态'')

    REQUIRED_FIELDS = [''mobile'']
    objects = UserManager()   # objects 管理器 UserManager

    class Meta:
        db_table = ''tb_users''
        verbose_name = ''用户''
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.username

4. 继承自 AbstractBaseUser 模型:

如果你想修改默认的验证方式,并且对于原来 User模型上的一些字段不想要,那么可以自定义一个模型,然后继承自 AbstractBaseUser ,再添加你想要的字段。这种方式会比较麻烦,最好是确定自己对 Django 比较才推荐使用。

完整例子:

from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager
from shortuuidfield import ShortUUIDField


# 用户管理器
class UserManager(BaseUserManager):
    """
    自定义用户管理器
    """
    def _create_user(self, telephone, username, password, **kwargs):
        if not telephone:
            raise ValueError(''请传入手机号码'')
        if not username:
            raise ValueError(''请传入用户名'')
        if not password:
            raise ValueError(''请传入密码'')

        user = self.model(telephone=telephone, username=username, **kwargs)
        user.set_password(password)
        return user

    def create_user(self, telephone, username, password, **kwargs):
        """创建普通用户"""
        kwargs[''is_superuser''] = False
        return self._create_user(telephone, username, password, **kwargs)

    def create_superuser(self, telephone, username, password, **kwargs):
        """创建超级用户"""
        kwargs[''is_superuser''] = True
        return self._create_user(telephone, username, password, **kwargs)


# 定义用户模型
class User(AbstractBaseUser):
    # 我们不使用默认的自增长的主键
    # uuid/shortuuid
    # shortuuidfield: pip install django-shortuuidfield
    uid = ShortUUIDField(primary_key=True, verbose_name=''以uuid作为主键,不使用默认的主键'')
    telephone = models.CharField(max_length=11, unique=True, verbose_name=''手机号'', help_text=''手机号'')
    # password = models.CharField(max_length=200, verbose_name=''密码'', help_text=''密码'')
    email = models.EmailField(unique=True, verbose_name=''邮箱'', help_text=''邮箱'')
    username = models.CharField(max_length=100, unique=True, verbose_name=''用户名'', help_text=''用户名'')
    is_active = models.BooleanField(default=True, verbose_name=''是否是可用的, 默认是可用的,即默认该用户就是激活了的'', help_text=''该用户是否是可用的'')
    is_staff = models.BooleanField(default=False, verbose_name=''是否是员工, 即是否能够登录到后台'', help_text=''是否是员工'')
    join_time = models.DateTimeField(auto_now_add=True, verbose_name=''用户加入时间'')

    USERNAME_FIELD = ''telephone''
    REQUIRED_FIELDS = [''username'']
    EMAIL_FIELD = ''email''

    # 用户管理器
    objects = UserManager()

    def get_full_name(self):
        return self.username

    def get_short_name(self):
        return self.username

    class Meta:
        db_table = ''cms_user''
        verbose_name = ''用户''
        verbose_name_plural = verbose_name

django from组件 ,model—from,django的缓存机制,dango的信号,django的序列号

django from组件 ,model—from,django的缓存机制,dango的信号,django的序列号

1.构建一个表单

假设你想在你的网站上创建一个简单的表单,以获得用户的名字。你需要类似这样的模板:

1
2
3
4
5
<form  action = "/your-name/"  method= "post" >
     <label  for = "your_name" >Your  name : </label>
     <input id= "your_name"  type= "text"  name = "your_name" >
     <input type= "submit"  value= "OK" >
</form>

这是一个非常简单的表单。实际应用中,一个表单可能包含几十上百个字段,其中大部分需要预填充,而且我们预料到用户将来回编辑-提交几次才能完成操作。

我们可能需要在表单提交之前,在浏览器端作一些验证。我们可能想使用非常复杂的字段,以允许用户做类似从日历中挑选日期这样的事情,等等。

这个时候,让Django 来为我们完成大部分工作是很容易的。

so,两个突出优点:

    1 form表单提交时,数据出现错误,返回的页面中仍可以保留之前输入的数据。

    2 方便地限制字段条件

 

                                      2.在Django 中构建一个表单

                      Form 类

    我们已经计划好了我们的 HTML 表单应该呈现的样子。在Django 中,我们的起始点是这里:

1
2
3
4
5
6
#forms.py
 
from django import forms
 
class NameForm(forms.Form):
    your_name = forms.CharField(label=''Your name'', max_length=100)

 它定义一个Form 类,只带有一个字段(your_name)。

字段允许的最大长度通过max_length 定义。它完成两件事情。首先,它在HTML 的<input> 上放置一个maxlength="100"(这样浏览器将在第一时间阻止用户输入多于这个数目的字符)。它还意味着当Django 收到浏览器发送过来的表单时,它将验证数据的长度。

Form 的实例具有一个is_valid() 方法,它为所有的字段运行验证的程序。当调用这个方法时,如果所有的字段都包含合法的数据,它将:

  • 返回True
  • 将表单的数据放到cleaned_data属性中。

完整的表单,第一次渲染时,看上去将像:

1
2
<label for="your_name">Your name: </label>
<input id="your_name" type="text" name="your_name" maxlength="100">

 注意它不包含 <form> 标签和提交按钮。我们必须自己在模板中提供它们。

                    视图:

发送给Django 网站的表单数据通过一个视图处理,一般和发布这个表单的是同一个视图。这允许我们重用一些相同的逻辑。

当处理表单时,我们需要在视图中实例化它:

 

 

如果访问视图的是一个GET 请求,它将创建一个空的表单实例并将它放置到要渲染的模板的上下文中。这是我们在第一个访问该URL 时预期发生的情况。

 

如果表单的提交使用POST 请求,那么视图将再次创建一个表单实例并使用请求中的数据填充它:form = NameForm(request.POST)。这叫做”绑定数据至表单“(它现在是一个绑定的表单)。

 

我们调用表单的is_valid()方法;如果它不为True,我们将带着这个表单返回到模板。这时表单不再为空(未绑定),所以HTML 表单将用之前提交的数据填充,然后可以根据要求编辑并改正它。

 

 

如果is_valid()True,我们将能够在cleaned_data 属性中找到所有合法的表单数据。在发送HTTP 重定向给浏览器告诉它下一步的去向之前,我们可以用这个数据来更新数据库或者做其它处理

 

 

            Django Form 类详解:

                绑定的和未绑定的表单实例

 

绑定的和未绑定的表单 之间的区别非常重要:

  • 未绑定的表单没有关联的数据。当渲染给用户时,它将为空或包含默认的值。
  • 绑定的表单具有提交的数据,因此可以用来检验数据是否合法。如果渲染一个不合法的绑定的表单,它将包含内联的错误信息,告诉用户如何纠正数据。
          •         字段详解

          • 考虑一个比上面的迷你示例更有用的一个表单,我们完成一个更加有用的注册表单:

          • #forms.py
            
            from django import forms
            
            class RegisterForm(forms.Form):
                username = forms.CharField(max_length=100,
                                           error_messages={"min_length":"最短为5个字符","required":"该字段不能为空"},
                                           )
                password = forms.CharField(max_length=100,
                                           widget=widgets.PasswordInput(attrs={"placeholder":"password"})
                                            )
            
                telephone=forms.IntegerField(
                    error_messages={
                        "invalid":"格式错误"
                    }
            
                                            )
            
            
                gender=forms.CharField(
                      initial=2,
                      widget=widgets.Select(choices=((1,''上海''),(2,''北京''),))
                         )
            
                email = forms.EmailField()
                is_married = forms.BooleanField(required=False)
            orms.py
            
            from django import forms
            
            class RegisterForm(forms.Form):
                username = forms.CharField(max_length=100,
                                           error_messages={"min_length":"最短为5个字符","required":"该字段不能为空"},
                                           )
                password = forms.CharField(max_length=100,
                                           widget=widgets.PasswordInput(attrs={"placeholder":"password"})
                                            )
            
                telephone=forms.IntegerField(
                    error_messages={
                        "invalid":"格式错误"
                    }
            
                                            )
            
            
                gender=forms.CharField(
                      initial=2,
                      widget=widgets.Select(choices=((1,''上海''),(2,''北京''),))
                         )
            
                email = forms.EmailField()
                is_married = forms.BooleanField(required=False)
            复制代码

            Widgets

            每个表单字段都有一个对应的Widget 类,它对应一个HTML 表单Widget,例如<input type="text">

            在大部分情况下,字段都具有一个合理的默认Widget。例如,默认情况下,CharField 具有一个TextInput Widget,它在HTML 中生成一个<input type="text">

            字段的数据

            不管表单提交的是什么数据,一旦通过调用is_valid() 成功验证(is_valid() 返回True),验证后的表单数据将位于form.cleaned_data 字典中。这些数据已经为你转换好为Python 的类型。

            注:此时,你依然可以从request.POST 中直接访问到未验证的数据,但是访问验证后的数据更好一些。

            在上面的联系表单示例中,is_married将是一个布尔值。类似地,IntegerField 和FloatField 字段分别将值转换为Python 的int 和float

            回到顶部

            使用表单模板

            你需要做的就是将表单实例放进模板的上下文。如果你的表单在Context 中叫做form,那么{{ form }}将正确地渲染它的<label> 和 <input>元素。

            表单渲染的选项

            对于<label>/<input> 对,还有几个输出选项:

            • {{ form.as_table }} 以表格的形式将它们渲染在<tr> 标签中
            • {{ form.as_p }} 将它们渲染在<p> 标签中
            • {{ form.as_ul }} 将它们渲染在<li> 标签中

            注意,你必须自己提供<table> 或<ul> 元素。

            {{ form.as_p }}会渲染如下:

          • <form action="">
                <p>
                    <label for="id_username">Username:</label>
                    <input id="id_username" maxlength="100" name="username" type="text" required="">
                </p>
             
             
                <p>
                    <label for="id_password">Password:</label>
                    <input id="id_password" maxlength="100" name="password" placeholder="password" type="password" required="">
                </p>
             
             
                <p>
                    <label for="id_telephone">Telephone:</label> <input id="id_telephone" name="telephone" type="number" required="">
                </p>
             
             
                <p>
                    <label for="id_email">Email:</label> <input id="id_email" name="email" type="email" required="">
                </p>
             
             
                <p>
                    <label for="id_is_married">Is married:</label> <input id="id_is_married" name="is_married" type="checkbox">
                </p>
             
             
                <input type="submit" value="注册">
            </form>
            View Code

             

          • 手工渲染字段:

            我们没有必要非要让Django 来分拆表单的字段;如果我们喜欢,我们可以手工来做(例如,这样允许重新对字段排序)。每个字段都是表单的一个属性,可以使用{{ form.name_of_field }} 访问,并将在Django 模板中正确地渲染。例如:

            1
            2
            3
            4
            5
            < div  >
                 {{ form.Username.errors }}
                 {{ form.Username.label_tag }}
                 {{ form.Username }}
            </ div >

            渲染表单的错误信息

            1、

            1
            2
            3
            registerForm=RegisterForm(request.POST)
            print(type(registerForm.errors))                      #< class  ''django.forms.utils.ErrorDict''>
            print(type(registerForm.errors["username"]))          #< class  ''django.forms.utils.ErrorList''>

            2、

            使用{{ form.name_of_field.errors }} 显示表单错误的一个清单,并渲染成一个ul。看上去可能像:

            1
            2
            3
            < ul  >
                 < li >Sender is required.</ li >
            </ ul >

             form组件的钩子

            复制代码
            def foo(request):
            
            
                if request.method=="POST":
            
                    regForm=RegForm(request.POST)
            
                    if regForm.is_valid():
                        pass
                        # 可用数据: regForm.cleaned_data,
                        # 将数据插入数据库表中
            
            
                    else:
                        pass
                        # 可用数据: regForm.errors
                        # 可以利用模板渲染讲errors嵌套到页面中返回
                        # 也可以打包到一个字典中,用于ajax返回
            
                else:
                    regForm=RegForm()
                return render(request,"register.html",{"regForm":regForm})
            
                
            
                ''''''
                实例化时:
            
                    self.fields={
                        "username":"字段规则对象",
                        "password":"字段规则对象",
            
                    }
            
            
                is_valid时:
            
                    self._errors = {}
                    self.cleaned_data = {}
            
            
                    #局部钩子:
            
                    for name, field in self.fields.items():
                          try:
            
                                value = field.clean(value)
                                self.cleaned_data[name] = value
                                if hasattr(self, ''clean_%s'' % name):
                                    value = getattr(self, ''clean_%s'' % name)()
                                    self.cleaned_data[name] = value
                          except ValidationError as e:
                                self.add_error(name, e)
            
                    # 全局钩子:
            
                    self.clean()     # def self.clean():return self.cleaned_data
            
                    return  not self.errors    # True或者False

             

                                                                    form组件补充

1、Django内置字段如下:

  

复制代码
Field
    required=True,               是否允许为空
    widget=None,                 HTML插件
    label=None,                  用于生成Label标签或显示内容
    initial=None,                初始值
    help_text='''',                帮助信息(在标签旁边显示)
    error_messages=None,         错误信息 {''required'': ''不能为空'', ''invalid'': ''格式错误''}
    show_hidden_initial=False,   是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直)
    validators=[],               自定义验证规则
    localize=False,              是否支持本地化
    disabled=False,              是否可以编辑
    label_suffix=None            Label内容后缀
 
 
CharField(Field)
    max_length=None,             最大长度
    min_length=None,             最小长度
    strip=True                   是否移除用户输入空白
 
IntegerField(Field)
    max_value=None,              最大值
    min_value=None,              最小值
 
FloatField(IntegerField)
    ...
 
DecimalField(IntegerField)
    max_value=None,              最大值
    min_value=None,              最小值
    max_digits=None,             总长度
    decimal_places=None,         小数位长度
 
BaseTemporalField(Field)
    input_formats=None          时间格式化   
 
DateField(BaseTemporalField)    格式:2015-09-01
TimeField(BaseTemporalField)    格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
 
DurationField(Field)            时间间隔:%d %H:%M:%S.%f
    ...
 
RegexField(CharField)
    regex,                      自定制正则表达式
    max_length=None,            最大长度
    min_length=None,            最小长度
    error_message=None,         忽略,错误信息使用 error_messages={''invalid'': ''...''}
 
EmailField(CharField)      
    ...
 
FileField(Field)
    allow_empty_file=False     是否允许空文件
 
ImageField(FileField)      
    ...
    注:需要PIL模块,pip3 install Pillow
    以上两个字典使用时,需要注意两点:
        - form表单中 enctype="multipart/form-data"
        - view函数中 obj = MyForm(request.POST, request.FILES)
 
URLField(Field)
    ...
 
 
BooleanField(Field)  
    ...
 
NullBooleanField(BooleanField)
    ...
 
ChoiceField(Field)
    ...
    choices=(),                选项,如:choices = ((0,''上海''),(1,''北京''),)
    required=True,             是否必填
    widget=None,               插件,默认select插件
    label=None,                Label内容
    initial=None,              初始值
    help_text='''',              帮助提示
 
 
ModelChoiceField(ChoiceField)
    ...                        django.forms.models.ModelChoiceField
    queryset,                  # 查询数据库中的数据
    empty_label="---------",   # 默认空显示内容
    to_field_name=None,        # HTML中value的值对应的字段
    limit_choices_to=None      # ModelForm中对queryset二次筛选
     
ModelMultipleChoiceField(ModelChoiceField)
    ...                        django.forms.models.ModelMultipleChoiceField
 
 
     
TypedChoiceField(ChoiceField)
    coerce = lambda val: val   对选中的值进行一次转换
    empty_value= ''''            空值的默认值
 
MultipleChoiceField(ChoiceField)
    ...
 
TypedMultipleChoiceField(MultipleChoiceField)
    coerce = lambda val: val   对选中的每一个值进行一次转换
    empty_value= ''''            空值的默认值
 
ComboField(Field)
    fields=()                  使用多个验证,如下:即验证最大长度20,又验证邮箱格式
                               fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
 
MultiValueField(Field)
    PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用
 
SplitDateTimeField(MultiValueField)
    input_date_formats=None,   格式列表:[''%Y--%m--%d'', ''%m%d/%Y'', ''%m/%d/%y'']
    input_time_formats=None    格式列表:[''%H:%M:%S'', ''%H:%M:%S.%f'', ''%H:%M'']
 
FilePathField(ChoiceField)     文件选项,目录下文件显示在页面中
    path,                      文件夹路径
    match=None,                正则匹配
    recursive=False,           递归下面的文件夹
    allow_files=True,          允许文件
    allow_folders=False,       允许文件夹
    required=True,
    widget=None,
    label=None,
    initial=None,
    help_text=''''
 
GenericIPAddressField
    protocol=''both'',           both,ipv4,ipv6支持的IP格式
    unpack_ipv4=False          解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用
 
SlugField(CharField)           数字,字母,下划线,减号(连字符)
    ...
 
UUIDField(CharField)           uuid类型
    ...
View Code

 

2、Django内置插件:

 

TextInput(Input)
NumberInput(TextInput)
EmailInput(TextInput)
URLInput(TextInput)
PasswordInput(TextInput)
HiddenInput(TextInput)
Textarea(Widget)
DateInput(DateTimeBaseInput)
DateTimeInput(DateTimeBaseInput)
TimeInput(DateTimeBaseInput)
CheckboxInput
Select
NullBooleanSelect
SelectMultiple
RadioSelect
CheckboxSelectMultiple
FileInput
ClearableFileInput
MultipleHiddenInput
SplitDateTimeWidget
SplitHiddenDateTimeWidget
SelectDateWidget
复制代码
View Code

 


3、常用选择插件:

 

# 单radio,值为字符串
# user = fields.CharField(
#     initial=2,
#     widget=widgets.RadioSelect(choices=((1,''上海''),(2,''北京''),))
# )
 
# 单radio,值为字符串
# user = fields.ChoiceField(
#     choices=((1, ''上海''), (2, ''北京''),),
#     initial=2,
#     widget=widgets.RadioSelect
# )
 
# 单select,值为字符串
# user = fields.CharField(
#     initial=2,
#     widget=widgets.Select(choices=((1,''上海''),(2,''北京''),))
# )
 
# 单select,值为字符串
# user = fields.ChoiceField(
#     choices=((1, ''上海''), (2, ''北京''),),
#     initial=2,
#     widget=widgets.Select
# )
 
# 多选select,值为列表
# user = fields.MultipleChoiceField(
#     choices=((1,''上海''),(2,''北京''),),
#     initial=[1,],
#     widget=widgets.SelectMultiple
# )
 
 
# 单checkbox
# user = fields.CharField(
#     widget=widgets.CheckboxInput()
# )
 
 
# 多选checkbox,值为列表
# user = fields.MultipleChoiceField(
#     initial=[2, ],
#     choices=((1, ''上海''), (2, ''北京''),),
#     widget=widgets.CheckboxSelectMultiple
# )
View Code

 

Django如何在Django表单中自动保存用户?

Django如何在Django表单中自动保存用户?

如何解决Django如何在Django表单中自动保存用户??

当我将“用户”字段传递给我的模型表单时。我正在获取所有用户详细信息作为下拉列表。看图:

enter image description here

我试图在不显示此下拉列表的情况下保存当前用户实例,因为我希望用户将在不选择或显示此下拉列表的情况下自动保存。

这是我的 forms.py 文件:

class ProfileFroms(forms.ModelForm):
      
      class Meta:
          model = UserProfile
          fields = ["user","profile_pic","mobile","country","website_link"] 

当我从字段中删除“用户”时,出现此错误:

"NOT NULL constraint Failed: members_userprofile.user_id"

我也试过这个代码来保存当前用户,但它给我带来了同样的错误。

views.py

if forms.is_valid():
          forms.user = request.user

这是我的完整代码:

models.py

class UserManagement(AbstractUser):
      is_subscriber = models.BooleanField(default=False)
      is_customer = models.BooleanField(default=False)


class UserProfile(models.Model):
      user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,related_name="userprofile")
      profile_pic = models.ImageField(upload_to=''profile/images/'',validators=[validate_file_size,FileExtensionValidator( [''png'',''jpg''] )],blank=True,null=True)
      mobile = models.IntegerField(blank=True,null=True)
      country = models.CharField(max_length=200,null=True)
      website_link = models.CharField(max_length=3000,null=True)

views.py

def UserProfileView(request):

   userinfo = UserManagement.objects.filter(username=request.user)
    
   
   forms = ProfileFroms(request.POST,request.FILES or None)
   if request.method == "POST":
      if forms.is_valid():
          #forms.user = request.user #tried this line for save current user but didn''t work 
          forms.save()
          messages.add_message(request,messages.INFO,''Profile updated sucessfully'') 
          return redirect("members:user-profile-private")
   else:
      messages.add_message(request,''Somethings wrong. Profile not updated'')  
      print("invalid")

   context={"userinfo":userinfo,"forms":forms}

   return render(request,"members/privateprofile.html",context)

解决方法

从表单中删除 user 字段:

class ProfileFroms(forms.ModelForm):
    class Meta:
        model = UserProfile
        fields = [''profile_pic'',''mobile'',''country'',''website_link'']

然后您更改表单的 .instance(不是表单本身),因此:

if forms.is_valid():
    forms.instance.user = request.user
    forms.save()

Django:如何在model.py页面上获取用户ID并动态设置默认值

Django:如何在model.py页面上获取用户ID并动态设置默认值

如果要通过“管理控制台”进行保存,请尝试以下操作:

class VariablesAdmin(admin.ModelAdmin):
    def save_model(self,request,obj,form,change):
        obj.user_var_id = request.user.id
        super().save_model(request,change)

如果要通过api或视图集进行保存,请尝试以下操作:

variable = Variables()
variable.user_var_id = request.user.id
variable.save()
,

在您的视图内部,request.user.id将始终返回当前用户的ID。您可以在查询中简单地使用它来获取所需的模型。 您还错误地将代码中的“对象”和“获取”都大写,这是不正确的。

因此您的查询应如下所示:

variable = Variables.objects.get(user_var_id=request.user.id)

编辑:您似乎想访问模型文件中的“当前用户”,而不是(逻辑上)访问视图文件中的“当前用户”; request.user.id仅在视图中可用,因为每个视图都收到一个请求。

,

所以您想要的是,当用户创建项目时,它将从他们的变量中获取值。

您可以做的是创建一个信号,以便在创建项目时将获得用户和相关字段,并将其添加到项目中,然后保存。

https://docs.djangoproject.com/en/3.1/topics/signals/

,
#to get request in models.py
from crequest.middleware import CrequestMiddleware
current_request = CrequestMiddleware.get_request()

pip install django-crequest

第1步:在您的settings.py中将crequest添加到INSTALLED_APPS

步骤2:在身份验证和会话中间件之后,将crequest.middleware.CrequestMiddleware添加到MIDDLEWARE_CLASSES。

今天关于如何在mongodb中扩展django的默认用户?mongodb django的讲解已经结束,谢谢您的阅读,如果想了解更多关于18_django的用户模型和扩展django的用户模型、django from组件 ,model—from,django的缓存机制,dango的信号,django的序列号、Django如何在Django表单中自动保存用户?、Django:如何在model.py页面上获取用户ID并动态设置默认值的相关知识,请在本站搜索。

本文标签: