Modifying Sign Up tab created using django framework

给你一囗甜甜゛ 提交于 2021-02-04 08:34:27

问题


I have made a sign up tab that registers new users and log in page that allows the registered users to continue with the site. I want if any registered user (having a registered email) tries to sign up again , an error message should pop up saying 'You are already having an account. Please Log in'. I stored the data(s) of registered user(s) in a table created in models.py named SignedUpUsers. Please help me achieve my task.

models.py


# Create your models here.


class SignedUpUsers(models.Model):
    email = models.EmailField(max_length=122)
    name = models.CharField(max_length=122)
    username = models.CharField(max_length=122)
    password = models.CharField(max_length=122)
    date = models.DateField()

    def __str__(self):
        return self.name

views.py

from Home.models import SignedUpUsers
from django.contrib import messages
from datetime import datetime

def login(request):
    return render(request, 'login.html')


def signup(request):
    if request.method == 'POST':
        name = request.POST.get('name')
        email = request.POST.get('email')
        username = request.POST.get('username')
        password = request.POST.get('password')
        cont = SignedUpUsers(name=name,email=email,username=username,password=password,date=datetime.today())
        cont.save()
        messages.success(request,"\t\tYour account has successfully been created . Kindly Log In\t\t")
    return render(request, 'signup.html')

signup.html

<!--Form-->
<form method="post" action="/signup" style="
    position: absolute;
    top: 260px;
    left: 500px;
    font-size: larger;
">
    {%csrf_token%}
    <!--Email-->
  <div class="form-group" >
    <label for="email">Email address</label>
    <input type="email" size="25" class="form-control" id="email" name="email" placeholder="name@example.com" style="block-size: 25px; position: absolute; left: 120px;">
  </div>
    <!--Name-->
    <div class="form-group" >
    <label for="name" style="position: absolute;left: 0px;top: 30px;">Name</label>
    <input type="text" size="25" class="form-control" id="name" name="name" placeholder="Arbaaz Ahmed" style="block-size: 25px;position: absolute;left: 120px;top: 30px;">
  </div>
    <!--Username-->
    <div class="form-group" >
    <label for="username" style="position: absolute;left: 0px;top: 60px;">Username</label>
    <input type="text" size="25" class="form-control" id="username" name="username" placeholder="arbaazahmed2134" style="block-size: 25px;position: absolute;left: 120px;top: 60px;">
  </div>
    <!--Password-->
    <div class="form-group" >
    <label for="password" style="position: absolute;left: 0px;top: 90px;">Password</label>
    <input type="password" class="form-control" size="25" id="password" name="password" style="block-size: 25px;position: absolute;left: 120px;top: 90px;">
  </div>
    <!--Sign up Button-->
    <button type="submit" class="btn btn-primary" style="
    position: absolute;
    top: 130px;
    left: 120px;
    background-color: antiquewhite;
    height: 27px;
    width: 100px
">Sign Up</button>
</form>

<!--Account Created-->
{% if messages %}
{% for message in messages%}
<div class="alert alert-{{message.tags}}" role="alert" style="position: absolute; background-color: aqua; left: 470px; top: 430px">
  <!--<h4 class="alert-heading">Well done!</h4>-->
    {{ message }}
</div>
{% endfor %}
{% endif %}

回答1:


Ok, so here is full solution. I have done some modifications to your existing solution, I hope this will help you.

Django comes with built in User model which already have authentication logic built in. Great thing is, it can be extended too. So I created UserDetails model which extends User using OneToOneField. Create and put following code in models.py .

models.py

from django.db import models
from django.contrib.auth.models import User

class UserDetails(models.Model):
    user = models.OneToOneField(User,on_delete=models.CASCADE)
    name = models.CharField(max_length=122)
    dob = models.DateField()

    def __str__(self):
        return self.name

After creating that, create migrations using following command python manage.py makemigrations and after that python manage.py migrate

Handling Sign Up logic:

We already have created our models, now to get data from user We need forms. Django have built in support for handling forms logic. I created two model forms as UserForm and UserDetailsForm. Here comes a tricky part, both forms are acting as a individual forms and each form is not aware of other. So I created a formset which is going to be used later to link our User with UserDetails inside view. Create and put following code in forms.py.

forms.py

from django import forms
from .models import UserDetails
from django.contrib.auth.models import User 
from django.contrib.auth.forms import UserCreationForm

class UserForm(UserCreationForm):
   class Meta:
      model = User
      fields = ('email','username','password1', 'password2',)

class UserDetailsForm(forms.ModelForm):
    class Meta:
        model = UserDetails
        fields = ('name', 'dob',)


from django.forms import inlineformset_factory
# Formset is combining UserForm and UserDetailsForm
UserDetailsFormSet = inlineformset_factory(User, UserDetails, form=UserDetailsForm, 
extra=1, can_delete = False)

To render both forms create a template signUpTemplate.html. (Note: You can style it later)

signUpTemplate.html

<form method="POST">
    {% csrf_token %}
    {{ user_form.as_p }}
    {{ user_details_form.as_p }}
    <button type="submit">Submit</button>
</form>

Now, I have created view as signUpView which will handle SignUp requests. Here I passed UserForm and UserDetailsFormSet in context and rendered the form using template. If you have seen carefully in signUpTemplate I am using single form tag <form>***code***</form> to render both the forms as it will force to send both the forms in single request.

Now this is how I am processing the forms data in view. First I check for UserForm. If UserForm is valid then I process UserDetailsFormSet and pass instance of UserForm in it (you may have seen commit=false parameter in save method. this parameter means that just save it in memory not in actual database). If UserDetailsFormSet is valid then I am calling the save() method on both forms. If forms are not valid then it will automatically render the error on template*(this is the power of built in forms)*. Here is the view code in views.py .

views.py

from django.shortcuts import render,redirect
from django.conf import settings
from .forms import UserForm, UserDetailsFormSet

def signUpView(request):
    user_form = UserForm(request.POST or None)
    user_details_form = UserDetailsFormSet(request.POST or None)

    if request.method == 'POST':
        user_form = UserForm(request.POST)

        if user_form.is_valid():
            user = user_form.save(commit=False)
            user_details_form = UserDetailsFormSet(request.POST,instance=user)

            if user_details_form.is_valid():
                user.save()
                user_details_form.save()
                return redirect('login')

    context = {
        'user_form': user_form,
        'user_details_form': user_details_form,
    }

    return render(request, 'signUpTemplate.html',context=context)

Handling Login logic:

Login functionality is pretty straight forward. To handle login I have created loginView. Django provides built in AuthenticationForm for handling User authentication. To render AuthenticationForm create a template loginTemplate.html.

loginTemplate.html

<form method="POST">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Submit</button>
</form>

The login() method is Django's built in functionality to handle User Login. Put following code in views.py (Note: do not forget to add URL after successful login in redirect() method).

views.py

from django.contrib.auth import login
from django.contrib.auth.forms import AuthenticationForm
from django.conf import settings

def loginView(request):
    form = AuthenticationForm(request.POST or None)

    if request.method == 'POST':
        form = AuthenticationForm(data=request.POST)
        if form.is_valid():
            user = form.get_user()
            login(request, user)
            return redirect('URL_after_successful_login')

    return render(request, 'loginTemplate.html', context = {'form': form})

As we have done all the main part, now we can register both views in our apps urls.py file.

urls.py

from .views import index,loginView,signUpView
from django.urls import path

urlpatterns = [
    path('', index, name='index'),
    path('login', loginView, name = 'login' ),
    path('signup', signUpView, name = 'signup')
]

also in your projects urls file do not forget to add referance to your apps url file by putting path('', include('your_app.urls')) in urlpatterns (Note: replace your_app with your appname)

Now you can run the server by using python manage.py runserver command. Go to your web browser and browse localhost:port/signup to get signup page, and localhost:port/login to get login page.

I hope you are familiar with admin site (i.e creation of super user and login into admin site), register your model with admin site as follows. And login with your super user credentials and check User and UserDetails tables at admin site.

admin.py

from django.contrib import admin
from .models import UserDetails

admin.site.register(UserDetails)

I hope this will help you. :)



来源:https://stackoverflow.com/questions/61408279/modifying-sign-up-tab-created-using-django-framework

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!