Django allauth:自定义注册表单不会保存所有字段

时间:2021-03-21 18:22:27

标签: python django django-models django-forms django-allauth

我制作了自定义注册表单,但我的应用似乎并未尝试保存发布请求中的所有数据。执行的 SQL 查询显然缺少几个字段。你知道发生了什么吗?我还应该为注册创建自定义视图吗?

错误

django.db.utils.IntegrityError: (1048, "Column 'birth_date' cannot be null")

发布请求正文

csrfmiddlewaretoken 'S6s1kocaG5nKQyeKfJd4cTD6do3Dv2VjrElQ4DYESybICDQtueQG5TkqQf5HgP7W'
username    'User123'
email   'mrjst1995@gmail.com'
first_name  'John'
last_name   'Doe'
city    '2'
address 'blahblahblah'
phone   '005006007'
birth_date  '2006-06-09'
password1   'somerandpass'
password2   'somerandpass'

执行的查询

    db  
<_mysql.connection open to 'localhost' at 02154B30>
q   
(b'INSERT INTO `users_user` (`email`, `username`, `password`, `date_joined`, `l'
 b'ast_login`, `is_admin`, `is_active`, `is_staff`, `is_superuser`, `first_name'
 b"`, `last_name`, `phone`, `city_id`, `address`, `birth_date`) VALUES ('mrjst1"
 b"995@gmail.com', 'User123', 'pbkdf2_sha256$216000$6H02ElhAxQ3y$y56l29/sTf0Oyy"
 b"+sa39MX2cgLlgvPzsA+K5HWOb/NjU=', '2021-03-21 18:05:49.199287', '2021-03-21 1"
 b"8:05:49.199287', 0, 1, 0, 0, 'John', 'Doe', '', NULL, '', NULL)")
self    
<MySQLdb.cursors.Cursor object at 0x05194BB0>

models.py

from django.db import models
from django.contrib.auth import get_user_model
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.contrib.auth.hashers import make_password


class City(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=20,null=False)
    def __str__(self):
         return self.name
class UserManager(BaseUserManager):
def create_user(self, email, username, first_name, last_name, city, address,phone, birth_date, password=None):
    if not email:
        raise ValueError('Korisnik mora imati email adresu')
    if not username:
        raise ValueError('Korisnik mora imati korisničko ime')
    if not first_name:
        raise ValueError("Korisnik mora imati ime")
    if not last_name:
        raise ValueError("Korisnik mora imati prezime")
    if not city:
        raise ValueError("Korisnik mora mesto stanovanja")
    if not address:
        raise ValueError("Korisnik mora imati adresu stanovanja")
    if not phone:
        raise ValueError("Korisnik mora imati broj telefona")
    if not birth_date:
        raise ValueError("Korisnik mora imati datum rođenja")
 
    user = self.model(email=self.normalize_email(email),
                      username=username,
                      first_name=first_name,
                      last_name=last_name,
                      city=city,
                      address=address,
                      phone=phone,
                      birth_date=birth_date,
                      password=password,)
    user.password=make_password(user.password)
    user.save()
    return user

def create_superuser(self, email, username,first_name,last_name,city,address,phone,birth_date, password):
    user = self.create_user(email=self.normalize_email(email),
                            password=password,
                            username=username,
                            first_name=first_name,
                            last_name=last_name,
                            city=city,
                            address=address,
                            phone=phone,
                            birth_date=birth_date,)
    user.is_admin = True
    user.is_staff = True
    user.is_superuser = True
    user.save()
    return user
class User(AbstractBaseUser):
    class Meta:
        verbose_name = 'korisnik'
    email = models.EmailField(verbose_name="email", max_length=60, unique=True)
    username = models.CharField(max_length=30, verbose_name="korisničko ime", unique=True)
    password = models.CharField(verbose_name="lozinka", max_length=1000)
    date_joined = models.DateTimeField(verbose_name='datum pridruživanja', auto_now_add=True)
    last_login = models.DateTimeField(verbose_name='poslednji put ulogovan', auto_now=True)
    is_admin = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    first_name = models.CharField(verbose_name="ime", max_length=20)
    last_name = models.CharField(max_length=20, verbose_name="prezime")
    phone = models.CharField(max_length=20,unique=True, verbose_name="broj telefona")
    city = models.ForeignKey(City,null=True,on_delete=models.SET_NULL)
    address = models.CharField(max_length=50, verbose_name="adresa")
    birth_date= models.DateField(verbose_name="datum rođenja")
    
    USERNAME_FIELD = 'email'
    EMAIL_FIELD = 'email'
    REQUIRED_FIELDS = ['username','first_name','last_name','city','address','birth_date','phone']
    
    objects = UserManager()
    
    def get_absolute_url(self):
        return "/users/%i/" % (self.pk)
    
    def __int__(self):
        return self.id
    
    def has_perm(self, perm, obj=None):
        return self.is_admin
    
    def has_module_perms(self, app_label):
        return True
    
    def get_id(self):
        return self.id

forms.py

    from allauth.account.forms import SignupForm
from users import models as UserModel
from django import forms
from django.forms import ModelForm
import datetime



class MyCustomSignupForm(SignupForm):
    first_name = forms.CharField(max_length=20, label='Ime')
    last_name= forms.CharField(max_length=20, label='Prezime')
    phone= forms.CharField(max_length=20, label='Broj telefona')
    birth_date= forms.DateField(label="Datum rođenja", initial=datetime.date.today,
                                widget=forms.DateInput(attrs={'class':'form-control',
                                                              'id': "example-date-input",
                                                              'type':'date'}))
    city = forms.ModelChoiceField(queryset=UserModel.City.objects.all(), 
                                  empty_label=None, label="Grad",
                                  widget=forms.Select(attrs={'class':'form-control'}))
    address = forms.CharField(max_length=50, label="Adresa")
    def save(self, request):
        user = super(MyCustomSignupForm, self).save(request)
        user.first_name=self.cleaned_data['first_name']
        user.last_name=self.cleaned_data['last_name']
        user.phone=self.cleaned_data['phone']
        user.birth_date=self.cleaned_data['birth_date']
        user.city=self.cleaned_data['city']
        user.address=self.cleaned_data['address']
        user.save()
        return user

signup.html(我只复制了表单)

 <form method="POST" action="{% url 'account_signup' %}">
           {% csrf_token %}
            <div class="form-group">
                {% comment %} username {% endcomment %}
                <label for="username">Korisničko ime</label>
                <input type="text" class="form-control" id="username" name="username" placeholder="Unesi korisničko ime"
                    required>
                <!-- email -->
                <label for="email">Email adresa</label>
                <input type="email" class="form-control" id="email" name="email" placeholder="Unesi email adresu"
                    aria-describedby="emailHelp" required>
                <!-- Ime -->
                <label for="first_name">Ime</label>
                <input type="text" class="form-control" id="first_name" name="first_name"
                    placeholder="Unesite svoje ime" required>
                <!-- Prezime -->
                <label for="last_name">Prezime</label>
                <input type="text" class="form-control" id="last_name" name="last_name"
                    placeholder="Unesite svoje prezime" required>
                <!--Mesto-->
                <label for="city">Mesto</label>
                {% comment %} <select placeholder="Izaberite grad" class="form-control form-control" id="city" name="city">
                {% for city in form.city %}
                    <option value={{ city.id }}>{{ city }}</option>
                {% endfor %}
                </select> {% endcomment %}
                {{form.city}}
                <!--Adresa-->
                <label for="address">Adresa</label>
                <input type="text" class="form-control" id="address" name="address" placeholder="Unesite adresu"
                    required>
                <!-- Kontakt-->
                <label for="phone">Kontakt telefon</label>
                <input type="text" pattern="^[0-9/-]*$" class="form-control" id="phone" name="phone" placeholder="Unesite kontakt telefon (samo brojevi, / ili - bez razmaka)" required>
                <!--Datum-->
                <label for="example-date-input" class="col-form-label">Datum rođenja</label>
                {% comment %} <input name="birth_date" class="form-control" type="date" value="1980-08-19" id="example-date-input"> {% endcomment %}
                {{form.birth_date}}
                <!-- password -->
                <label for="password1">Lozinka</label>
                <input type="password" class="form-control" id="password1" name="password1" required>
                <!-- password confirmation -->
                <label for="password2">Potvrdite lozinku</label>
                <input type="password" class="form-control" id="password2" name="password2" required>
            </div>
            <input type="submit" class="btn btn-outline-dark btn-custom mt-3" value="Registruj se">
        </form>

我也更改了allauth表单的设置,所以我很确定使用了这个表单

ACCOUNT_FORMS = {
    'signup': 'users.forms.MyCustomSignupForm'
    }

1 个答案:

答案 0 :(得分:0)

我自己设法解决了这个问题。我不得不重写 DefaultAccountAdapter 因为它的 save_user 方法默认只保存用户名、密码、last_name 和 first_name。我希望它是用 allauth 文档编写的。如果有人在挣扎,答案如下。我在我的用户应用中创建了一个新文件。

adapter.py

from django.conf import settings
from allauth.account.adapter import DefaultAccountAdapter
from django import utils
class MyAccountAdapter(DefaultAccountAdapter):
    def save_user(self, request, user, form, commit=True):
        data = form.cleaned_data
        user.first_name = data["first_name"]
        user.last_name = data["last_name"]
        user.email = data["email"]
        user.username = data["username"]
        user.phone = data['phone']
        user.birth_date = data['birth_date']
        user.city = data['city']
        user.address = data['address']
        if "password1" in data:
            user.set_password(data["password1"])
        else:
            user.set_unusable_password()
        self.populate_username(request, user)
        user.save()
        return user

settings.py 中我添加了这一行

ACCOUNT_ADAPTER = 'users.adapter.MyAccountAdapter'