I'm trying to add some additional fields to the allauth signup form (first_name and last_name). I'm thinking the best way to do this is to create a allauth SignupForm subclass and add my own fields (very new to django so please let me know if I'm going about this wrong)
I added
ACCOUNT_SIGNUP_FORM_CLASS = 'accounts.forms.UserCreateForm'
to my base settings file
and here is my accounts.forms.py...
from django.contrib.auth import get_user_model
from allauth.account.forms import SignupForm
from django import forms
class UserCreateForm(SignupForm):
class Meta:
fields = ("first_name", "last_name", "email", "username", "password1", "password2")
model = get_user_model()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["first_name"].label = ''
self.fields["first_name"].widget.attrs["placeholder"] = "First Name"
self.fields["last_name"].label = ''
self.fields["last_name"].widget.attrs["placeholder"] = "Last Name"
self.fields["email"].label = ''
self.fields["email"].widget.attrs["placeholder"] = "Email"
self.fields["username"].label = ''
self.fields["username"].widget.attrs["placeholder"] = "Username"
self.fields["password1"].label = ''
self.fields["password1"].widget.attrs["placeholder"] = "Password"
self.fields["password2"].label = ''
self.fields["password2"].widget.attrs["placeholder"] = "Confirm Password"
for some reason I keep getting the error ...
django.core.exceptions.ImproperlyConfigured: Error importing form class accounts.forms: "cannot import name 'SignupForm'"
Not sure why. Obviously there is a SignupForm in allauth.account.forms.py, seen here...
https://github.com/pennersr/django-allauth/blob/master/allauth/account/forms.py
I dont know what I'm doing wrong. Any help you can give is much appreciated
https://stackoverflow.com/a/12308807/3415357
You do not need to inherit allauth.account.forms.SignupForm, you should inherit from forms.Form specify fields and write your custom signup function (username, email, password should stay intact)
Related
I am trying to make an Instagram API clone using Django rest framework.
I have created an account module that has two fields - user,AccountType. user is a OnetoOneField with the Django User model.
from django.db import models
from django.conf import settings
User=settings.AUTH_USER_MODEL
# Create your models here.
class Account(models.Model):
user=models.OneToOneField(User,on_delete=models.CASCADE)
PUBLIC='pub'
PRIVATE='pvt'
Account_choices=[
(PUBLIC,'Public'),
(PRIVATE,'Private')
]
AccountType=models.CharField(max_length=3,choices=Account_choices,default=PUBLIC)
I created a serializer for this model.
from rest_framework import serializers
from .models import Account
class AccountCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields=['user','AccountType']
In the views I received data from a client and used the data to create a User object and then use this user object to create an Account object. But when I try to serialize the data and check if it is_valid it reurns False. Can someone tell me how to fix this?
#api_view(['POST'])
def register_view(request,*args,**kwargs):
username = request.data['username']
password = request.data['password']
email = request.data['email']
user = User.objects.create_user(username, email, password)
data={
'user':user,
'AccountType':'pub'
}
serializer = AccountCreateSerializer(data=data)
return Response(data)
I tried giving the serializer input as a dictionary and even the username as just a string.
githubLink: https://github.com/henselwilson/Instafam.git
You alredy created an account for that user: a OneToOneField is a ForeignKey that is unique, so you can not create a second account for that user.
You thus let the serializer do the work:
#api_view(['POST'])
def register_view(request, *args, **kwargs):
username = request.data['username']
password = request.data['password']
email = request.data['email']
user = User.objects.create_user(username, email, password)
# do not create an Account
data = {'user': user, 'AccountType': 'pub'}
serializer = AccountCreateSerializer(data=data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
I'm fairly new to Django and feel I must be missing something. I have an application where I want two user types (UserType1 and UserType2). I am using the base user model with boolean flags and then created OneToOne fields on these objects to the user (no extra data added at this point).
This gives me the following user models:
from django.conf import settings
from django.contrib.auth.models import AbstractUser, UserManager
from django.core.exceptions import ValidationError
from django.db import models
from django_extensions.db.models import TimeStampedModel
class User(AbstractUser):
"""
Default user model for the platform
"""
email = models.EmailField()
is_user_type_1 = models.BooleanField(default=False)
is_user_type_2 = models.BooleanField(default=False)
# Use default UserManager for now
objects = UserManager()
class UserType1(TimeStampedModel):
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
primary_key=True,
related_name='user_type1',
)
class UserType2(TimeStampedModel):
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
primary_key=True,
related_name='user_type2'
)
I then wrote serializes for these classes where I only want to expose and endpoint for UserType1 and UserType2 (rather than User itself). This should allow the users to create an instance of UserType1 or UserType2 which will also create the row in the User table (although maybe not super important for this). Here are the serializers:
from django.db import transaction
from rest_framework import serializers
from .models import User, UserType1, UserType2
class UserSerializer(serializers.ModelSerializer):
"""
Serializer for the `User` model
"""
class Meta:
model = User
fields = (
'username',
'email',
'password',
'first_name',
'last_name',
'is_active',
)
extra_kwargs = {'password': {'write_only': True}}
class UserType1Serializer(serializers.ModelSerializer):
user = UserSerializer(required=True)
class Meta:
model = UserType1
fields = (
'user',
'created',
'modified',
)
#transaction.atomic
def create(self, validated_data):
user_data = validated_data.pop('user')
user_data.is_user_type_1 = True
user_data.is_user_type_2 = False
user = UserSerializer.create(UserSerializer(), validated_data=user_data)
user_type_1, created = UserType1.objects.update_or_create(
user=user,
)
return user_type_1
class UserType2Serializer(serializers.ModelSerializer):
user = UserSerializer(required=True)
class Meta:
model = UserType2
fields = (
'user',
'created',
'modified',
)
#transaction.atomic
def create(self, validated_data):
user_data = validated_data.pop('user')
user_data.is_user_type_1 = False
user_data.is_user_type_2 = True
user = UserSerializer.create(UserSerializer(), validated_data=user_data)
user_type2, created = UserType2.objects.update_or_create(
user=user,
)
return user_type2
The User model was registered in my settings:
AUTH_USER_MODEL = 'user.User'
After I create a superuser, I am successfully able to get my tokens and use them to access other views:
{
"refresh": "xxxx",
"access": "xxxx"
}
However, if I create a user from admin (or I have fixtures that create users and user_type1/user_type2 objects), every time I try to get the tokens I am getting:
{
"detail": "No active account found with the given credentials"
}
but I know they exist in the DB since I can see them properly in the admin console. I thought this was something to do with hashing of the password but was unable to solve it.
This also contains the following admin.py file:
from django.contrib import admin
from .models import User, UserType1, UserType2
admin.site.register(User)
admin.site.register(UserType1)
admin.site.register(UserType2)
Any help would be greatly appreciated!!
Register your custom User model in the admin with:
from django.contrib.auth.admin import UserAdmin
admin.site.register(models.User, UserAdmin)
Or follow the documentation on how to register a custom User model in admin.
A full example
create a new User via admin panel and check if the password is hashed.
Then make the api call to your jwt endpoint again.
I am trying to return a queryset as a JSON response in DRF but I always get a TypeError Object Not JSON serializable.
I have tried different methods but none of them worked. I have tried to use the JSONRenderer class and I have also tried to serialize a single object using SentSerializer. But nothing seems to solve the issue. I have just started learning DRF so it is a little confusing to me and really don't understand how serializers work and I am not sure if I have written them correctly or using them correctly.
# models
...
from django.contrib.auth.models import User
class Sentence(models.Model):
sent = models.CharField(max_length=255)
sent_correct = models.CharField(max_length=255, null=True)
pub_date = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE, null=True, related_name='sentences')
# serializers
...
from django.contrib.auth.models import User
class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True)
username = serializers.CharField(max_length=50)
class Meta:
model = User
# Tuple of serialized model fields (see link [2])
fields = ( "id", "username", "password", )
class SentSerializer(serializers.ModelSerializer):
sent = serializers.CharField(max_length=255)
sent_correct = serializers.CharField(max_length=255, required=False)
author = UserSerializer(read_only=True, required=False)
class Meta:
model = Sentence
fields = (
'sent', 'sent_correct', 'author'
)
# views
...
class SentCreateAPIView(APIView):
serializer_class = SentSerializer
permission_classes = (IsAuthenticated,)
def post(self, request):
ss = Sentence.objects.filter(author=request.user)[0:1]
ss = list(ss)
print("sentences " + str(ss))
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
vd = serializer.validated_data
sent_str = vd['sent']
s = Sentence(sent=sent_str, sent_correct=sent_str)
s.author = request.user
print(vd)
print(request.user)
s.save()
sent = nlp(sent_str)
tokens = [t.text for t in sent] # this list returns successfully
return Response(
{ 'sent': sent_str,
'sent_correct': sent_str,
'tokens': tokens,
'ss': ss, # this list throws TypeError},
status=status.HTTP_201_CREATED
)
Jakub Maślanka answered my question on Facebook in Django Python Web Framework group. I had to serialize the queryset like this:
# views.py
...
return Response(
{ 'sent': sent_str,
'sent_correct': sent_str,
'tokens': tokens,
'ss': SentSerializer(ss, many=True).data},
status=status.HTTP_201_CREATED
)
ss -> dict
Why dont you use generics.ListAPIView.
It has get_query_set method
You just need to override that method by your own query set
Less code is better -> class based and framework
This is my forms.py in Django app.But I have not understand the save() function specially the commit keyword. I took this code from a blog . here the writter is making a form for user registration.
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from . models import Document
class NewUserForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ("username", "email", "password1", "password2")
def save(self, commit = True):
user = super(NewUserForm, self).save(commit = False)
user.email = self.cleaned_data["email"]
if commit:
user.save()
return user
please explain the whole save function.
I have created sqlalchemy class and wtform Form from class.
from wtforms.ext.sqlalchemy.orm import model_form
class ClientGroup(Base, BaseModel):
__tablename__ = 'client_groups'
id = Column(Integer, primary_key=True)
name = Column(String(255))
sale = Column(Integer)
def __unicode__(self):
return self.name
ClientGroupForm = model_form(ClientGroup, Form, field_args={
'name': {'validators' : [validators.Required(), validators.Length(min=5)]},
})
in app I have following code:
form = ClientGroupForm(request.form)
if form.validate():
.. save data
When i send a new data to app its returns me validation error. ID must be an integer field.
But a new data hasn't any id.
Please, give me advice How can I use wtforms with sqlalchemy?
Make it optional explicitly, by adding the following to the field_args:
'id': {'validators' : [validators.Optional()],
However, I think you should exclude the id field from the form completely:
ClientGroupForm = model_form(ClientGroup, Form, field_args={
'name': {'validators' : [validators.Required(), validators.Length(min=5)]},
exclude=['id'],
})